From rspencer at reidspencer.com Mon Jul 31 00:34:42 2006 From: rspencer at reidspencer.com (rspencer at reidspencer.com) Date: Mon, 31 Jul 2006 00:34:42 -0700 Subject: [hlvm-commits] r433 - hlvm/AST hlvm/CodeGen hlvm/Pass hlvm/Reader hlvm/Writer test/return0 test/xml2xml tools/hlvm-gentestcase Message-ID: <200607310734.k6V7YgLQ010069@server1.hlvm.org> Author: reid Date: 2006-07-31 00:34:42 -0700 (Mon, 31 Jul 2006) New Revision: 433 Log: A rather large patch to get hlvm-gentestcase generating test cases that include a variety of operators instead of just function calls. Some important changes that accompany this are: 1. AutoVars are now initialized by any expression not just constant expression 2. There is a new "ConvertOp" for handling arithmetic type conversions. This generally emits as an LLVM cast operator, but we might do fancier conversions in the future (like array->int gives size of array). 3. The SizeOfOp was implemented in the code generator. It returns the runtime size of its argument which can be any value. 4. ReferenceOp became GetOp for consistency, brevity, and clarity. The function of this operator has expanded to include fetching not only values, but types, as needed by the ConvertOp. This is the first step toward making types first-class values. 5. IndexOp became GetFieldOp and GetIndexOp to make a distinction between getting fields of DisparateContainerTypes and elements of UniformDTs. Also this eliminates a multi-operand operator (index) and simplifies the implementation of indexing (one index at a time). These have now been implemented in the code generator as GetElementPtrInst in LLVM. 6. Implemented the various real number math operations. There's no code gen for these yet, but they're now recognized, generated, and printed. 7. The pre/post increment/decrement operators can now operate on any location, not just an autovar. 8. Function argument handling in the code generator was implemented. 9. The hlvm::dump(...) function was made more resilient to allow dumping of partial trees, detached trees, operator nodes, etc. Modified: hlvm/AST/AST.cpp hlvm/AST/AST.h hlvm/AST/Arithmetic.cpp hlvm/AST/Arithmetic.h hlvm/AST/Bundle.cpp hlvm/AST/ContainerType.cpp hlvm/AST/ContainerType.h hlvm/AST/ControlFlow.cpp hlvm/AST/Linkables.cpp hlvm/AST/Linkables.h hlvm/AST/MemoryOps.cpp hlvm/AST/MemoryOps.h hlvm/AST/Node.cpp hlvm/AST/Node.h hlvm/CodeGen/LLVMEmitter.h hlvm/CodeGen/LLVMGenerator.cpp hlvm/Pass/Pass.cpp hlvm/Pass/Pass.h hlvm/Pass/Validate.cpp hlvm/Reader/HLVM.rng hlvm/Reader/XMLReader.cpp hlvm/Writer/XMLWriter.cpp test/return0/arithmetic.hlx test/return0/bitwise.hlx test/return0/boolean.hlx test/return0/break.hlx test/return0/call.hlx test/return0/complement.hlx test/return0/continue.hlx test/return0/helloworld.hlx test/return0/loop.hlx test/return0/noresult.hlx test/return0/resultoverride.hlx test/return0/return0.hlx test/return0/select.hlx test/return0/unless.hlx test/return0/until.hlx test/return0/unused.hlx test/return0/while.hlx test/xml2xml/argscall.hlx test/xml2xml/arithmetic.hlx test/xml2xml/autovar.hlx test/xml2xml/block.hlx test/xml2xml/booleanops.hlx test/xml2xml/break.hlx test/xml2xml/call.hlx test/xml2xml/continue.hlx test/xml2xml/doc.hlx test/xml2xml/helloworld.hlx test/xml2xml/loop.hlx test/xml2xml/progargs.hlx test/xml2xml/return.hlx test/xml2xml/select.hlx test/xml2xml/switch.hlx test/xml2xml/unless.hlx test/xml2xml/until.hlx test/xml2xml/while.hlx tools/hlvm-gentestcase/Generate.cpp Modified: hlvm/AST/AST.cpp =================================================================== --- hlvm/AST/AST.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/AST.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -740,32 +740,31 @@ AST::new_AutoVarOp( const std::string& name, const Type* Ty, - Constant* init, const Locator* loc) { hlvmAssert(Ty != 0 && "AutoVarOp must have a Type!"); AutoVarOp* result = new AutoVarOp(); result->setType(Ty); result->setLocator(loc); - result->setInitializer(init); result->setName(name); return result; } -ReferenceOp* -AST::new_ReferenceOp(const Value* V, const Locator*loc) +GetOp* +AST::new_GetOp(const Documentable* D, const Locator*loc) { - hlvmAssert(V != 0 && "ReferenceOp must have a Value to reference"); - ReferenceOp* result = new ReferenceOp(); - const Type* refType = V->getType(); - if (llvm::isa(V) || - llvm::isa(V) || - llvm::isa(V)) - result->setType(refType); - else + hlvmAssert(D != 0 && "GetOp must have a Value to reference"); + GetOp* result = new GetOp(); + if (llvm::isa(D) || + llvm::isa(D) || + llvm::isa(D)) { + result->setType(llvm::cast(D)->getType()); + } else if (llvm::isa(D)) { + result->setType(llvm::cast(D)); + } else hlvmAssert(!"Invalid referent type"); result->setLocator(loc); - result->setReferent(V); + result->setReferent(D); return result; } @@ -826,7 +825,7 @@ ) { hlvmAssert(oprnd1 != 0 && "Invalid Operand for BinaryOp"); - hlvmAssert(oprnd2 != 0 && "Invalid Operand for BinUnaryOp"); + hlvmAssert(oprnd2 != 0 && "Invalid Operand for BinaryOp"); OpClass* result = new OpClass(); result->setLocator(loc); result->setType(Ty); @@ -932,17 +931,37 @@ AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); template PostIncrOp* -AST::new_UnaryOp( - const Type* Ty, Operator* op1, const Locator* loc); +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); template PostIncrOp* AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); template PostDecrOp* -AST::new_UnaryOp( - const Type* Ty, Operator* op1, const Locator* loc); +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); template PostDecrOp* AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); +template SizeOfOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template SizeOfOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template ConvertOp* +AST::new_BinaryOp( + const Type* Ty, Operator* op1, Operator* op2, const Locator* loc); + +template<> ConvertOp* +AST::new_BinaryOp( + Operator* oprnd1, ///< The first operand + Operator* oprnd2, ///< The second operand + Bundle* B, ///< The bundle, for type lookup + const Locator* loc ///< The source locator +) +{ + GetOp* get = llvm::cast(oprnd2); + const Type* Ty = llvm::cast(get->getReferent()); + return new_BinaryOp(Ty,oprnd1,oprnd2,loc); +} + template AddOp* AST::new_BinaryOp( const Type* Ty, Operator* op1, Operator* op2, const Locator* loc); @@ -997,6 +1016,92 @@ template BNorOp* AST::new_BinaryOp(Operator* op1, Operator* op2, Bundle* B, const Locator* loc); +// Real Operators +template IsPInfOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template IsPInfOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template IsNInfOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template IsNInfOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template IsNanOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template IsNanOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template TruncOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template TruncOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template RoundOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template RoundOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template FloorOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template FloorOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template CeilingOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template CeilingOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template LogEOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template LogEOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template Log2Op* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template Log2Op* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template Log10Op* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template Log10Op* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template SquareRootOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template SquareRootOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template CubeRootOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template CubeRootOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template FactorialOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template FactorialOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); + +template PowerOp* +AST::new_BinaryOp(const Type* Ty, Operator* op1, Operator* op2, const Locator* loc); +template PowerOp* +AST::new_BinaryOp(Operator* op1, Operator* op2, Bundle* B, const Locator* loc); + +template RootOp* +AST::new_BinaryOp(const Type* Ty, Operator* op1, Operator* op2, const Locator* loc); +template RootOp* +AST::new_BinaryOp(Operator* op1, Operator* op2, Bundle* B, const Locator* loc); + +template GCDOp* +AST::new_BinaryOp(const Type* Ty, Operator* op1, Operator* op2, const Locator* loc); +template GCDOp* +AST::new_BinaryOp(Operator* op1, Operator* op2, Bundle* B, const Locator* loc); + +template LCMOp* +AST::new_BinaryOp(const Type* Ty, Operator* op1, Operator* op2, const Locator* loc); +template LCMOp* +AST::new_BinaryOp(Operator* op1, Operator* op2, Bundle* B, const Locator* loc); + // Boolean Operators template NotOp* AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); Modified: hlvm/AST/AST.h =================================================================== --- hlvm/AST/AST.h 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/AST.h 2006-07-31 07:34:42 UTC (rev 433) @@ -55,8 +55,7 @@ class Pool; class Operator; class AutoVarOp; -class ReferenceOp; -class ConstantReferenceOp; +class GetOp; class URI; /// This class is used to hold or contain an Abstract Syntax Tree. It forms the @@ -92,6 +91,10 @@ const std::string& getSystemID() const { return sysid; } const std::string& getPublicID() const { return pubid; } Pool* getPool() const { return pool; } + /// Provide support for isa and friends + static inline bool classof(const AST*) { return true; } + static inline bool classof(const Node* N) + { return N->is(TreeTopID); } /// @} /// @name Mutators @@ -433,7 +436,7 @@ /// Create a new ConstantPointer node. ConstantPointer* new_ConstantPointer( const std::string& name, ///< The name of the constant - Bundle* bundle, ///< The bundle to insert the type into + Bundle* bundle, ///< The bundle to insert the type into const Type* type, ///< The type of the constant pointer Constant* referent, ///< The value pointed to const Locator* loc = 0 ///< The source locator @@ -496,13 +499,12 @@ AutoVarOp* new_AutoVarOp( const std::string& name, ///< Name of the autovar in its scope const Type* Ty, ///< Type of the autovar - Constant* init, ///< Initializer for the autovar const Locator* loc ///< The source locator ); - /// Create a new ReferenceOp. - ReferenceOp* new_ReferenceOp( - const Value* V, ///< The value being referenced + /// Create a new GetOp. + GetOp* new_GetOp( + const Documentable* D,///< The value or type being referenced const Locator*loc = 0 ///< The source locator ); Modified: hlvm/AST/Arithmetic.cpp =================================================================== --- hlvm/AST/Arithmetic.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/Arithmetic.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -28,6 +28,9 @@ //===----------------------------------------------------------------------===// #include +#include +#include +#include namespace hlvm { @@ -38,6 +41,8 @@ PostIncrOp::~PostIncrOp() {} PreDecrOp::~PreDecrOp() {} PostDecrOp::~PostDecrOp() {} +SizeOfOp::~SizeOfOp() {} +ConvertOp::~ConvertOp() {} AddOp::~AddOp() {} SubtractOp::~SubtractOp() {} MultiplyOp::~MultiplyOp() {} Modified: hlvm/AST/Arithmetic.h =================================================================== --- hlvm/AST/Arithmetic.h 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/Arithmetic.h 2006-07-31 07:34:42 UTC (rev 433) @@ -175,6 +175,53 @@ friend class AST; }; +/// This class provides an Abstract Syntax Tree node that represents a +/// SizeOf operator. The SizeOfOp is a unary operator that returns the size, in +/// bytes, of its operand. The value returned is a constant. +/// @brief AST SizeOf Operator Node +class SizeOfOp : public UnaryOperator +{ + /// @name Constructors + /// @{ + protected: + SizeOfOp() : UnaryOperator(SizeOfOpID) {} + virtual ~SizeOfOp(); + + /// @} + /// @name Accessors + /// @{ + public: + static inline bool classof(const SizeOfOp*) { return true; } + static inline bool classof(const Node* N) { return N->is(SizeOfOpID); } + + /// @} + friend class AST; +}; + +/// This class provides an Abstract Syntax Tree node that represents a +/// conversion operator. The ConvertOp is a binary operator that converts its +/// first operand to the type provided in its second operand (which must be +/// a reference operator to the type). +/// @brief AST Conversion Operator Node +class ConvertOp : public BinaryOperator +{ + /// @name Constructors + /// @{ + protected: + ConvertOp() : BinaryOperator(ConvertOpID) {} + virtual ~ConvertOp(); + + /// @} + /// @name Accessors + /// @{ + public: + static inline bool classof(const ConvertOp*) { return true; } + static inline bool classof(const Node* N) { return N->is(ConvertOpID); } + + /// @} + friend class AST; +}; + /// This class provides an Abstract Syntax Tree node that represents an operator /// to add two quantities. The AddOp is a binary operator that /// computes the sum of its two operands and returns that value. Modified: hlvm/AST/Bundle.cpp =================================================================== --- hlvm/AST/Bundle.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/Bundle.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -58,8 +58,10 @@ unresolvedTypes.erase(ot); // getRoot()->old(ot); } - tlist.push_back(ty); - ttable.insert(ty); + if (!ttable.lookup(ty->getName())) { + tlist.push_back(ty); + ttable.insert(ty); + } } else if (Constant* C = dyn_cast(kid)) { clist.push_back(C); // Constants without names are permitted, but not Linkables Modified: hlvm/AST/ContainerType.cpp =================================================================== --- hlvm/AST/ContainerType.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/ContainerType.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -76,6 +76,15 @@ return 0; } +unsigned +DisparateContainerType::getFieldIndex(const std::string& fldname) const +{ + for (const_iterator I = begin(), E = end(); I != E; ++I ) + if ((*I)->getName() == fldname) + return I - begin() + 1; + return 0; +} + void DisparateContainerType::resolveTypeTo(const Type* from, const Type* to) { Modified: hlvm/AST/ContainerType.h =================================================================== --- hlvm/AST/ContainerType.h 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/ContainerType.h 2006-07-31 07:34:42 UTC (rev 433) @@ -268,6 +268,10 @@ public: virtual const char* getPrimitiveName() const; const NamedType* getField(unsigned index) const { return contents[index]; } + + /// Return the index of a named field starting at 1. If the field is not + /// found, returns 0. + unsigned getFieldIndex(const std::string& fldname) const; /// Methods to support type inquiry via is, cast, dyn_cast static inline bool classof(const DisparateContainerType*) { return true; } static inline bool classof(const Node* N) { Modified: hlvm/AST/ControlFlow.cpp =================================================================== --- hlvm/AST/ControlFlow.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/ControlFlow.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -84,9 +84,9 @@ Function* CallOp::getCalledFunction() const { - hlvmAssert(isa(getOperand(0))); - ReferenceOp* refop = cast(getOperand(0)); - const Value* referent = refop->getReferent(); + hlvmAssert(isa(getOperand(0))); + GetOp* refop = cast(getOperand(0)); + const Documentable* referent = refop->getReferent(); hlvmAssert(isa(referent)); return const_cast(cast(referent)); } Modified: hlvm/AST/Linkables.cpp =================================================================== --- hlvm/AST/Linkables.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/Linkables.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -39,9 +39,18 @@ Linkable::~Linkable() { } Variable::~Variable() { } Argument::~Argument() { } +unsigned +Argument::getArgNum() const +{ + Node* P = getParent(); + if (!P || !isa(P)) + return 0; + return cast(P)->getArgNum(this); +} + Function::~Function() { } -Value* +Argument* Function::getArgument(const std::string& name) const { for (const_iterator I = begin(), E = end(); I != E ; ++I ) @@ -50,6 +59,25 @@ return 0; } +Argument* +Function::getArgument(unsigned argNum ) const +{ + hlvmAssert(argNum < size()); + return args[argNum]; +} + +unsigned +Function::getArgNum(const Argument* arg) const +{ + unsigned num = 1; + for (const_iterator I = begin(), E = end(); I != E ; ++I ) + if ((*I) == arg) + return num; + else + num++; + return 0; +} + void Function::insertChild(Node* kid) { Modified: hlvm/AST/Linkables.h =================================================================== --- hlvm/AST/Linkables.h 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/Linkables.h 2006-07-31 07:34:42 UTC (rev 433) @@ -153,6 +153,9 @@ /// @{ public: const std::string& getName() const { return name; } + /// Return the 1-based index of this in this function it belongs to. + /// If this is not an argument of any function, returns 0; + unsigned getArgNum() const; static inline bool classof(const Argument*) { return true; } static inline bool classof(const Node* N) { return N->is(ArgumentID); } @@ -212,13 +215,18 @@ { return static_cast(type); } const Type* getResultType() const { return getSignature()->getResultType();} - Value* getArgument(const std::string& name) const; + Argument* getArgument(const std::string& name) const; + Argument* getArgument(unsigned argnum) const; + /// Return the 1-based index of the \p arg in this function. If \p arg + /// is not an argument of this function, returns 0; + unsigned getArgNum(const Argument* arg) const; + static inline bool classof(const Function*) { return true; } static inline bool classof(const Node* N) { return N->isFunction(); } /// @} - /// @name Iterators + /// @name Argument Iteration /// @{ public: iterator begin() { return args.begin(); } Modified: hlvm/AST/MemoryOps.cpp =================================================================== --- hlvm/AST/MemoryOps.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/MemoryOps.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -34,7 +34,7 @@ LoadOp::~LoadOp() {} StoreOp::~StoreOp() {} AutoVarOp::~AutoVarOp() {} -ReferenceOp::~ReferenceOp() {} +GetOp::~GetOp() {} GetIndexOp::~GetIndexOp() {} GetFieldOp::~GetFieldOp() {} Modified: hlvm/AST/MemoryOps.h =================================================================== --- hlvm/AST/MemoryOps.h 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/MemoryOps.h 2006-07-31 07:34:42 UTC (rev 433) @@ -174,12 +174,12 @@ /// variables may be declared to be constant in which case they must have an /// initializer and their value is immutable. /// @brief AST Automatic Variable Operator -class AutoVarOp : public NilaryOperator +class AutoVarOp : public UnaryOperator { /// @name Constructors /// @{ protected: - AutoVarOp() : NilaryOperator(AutoVarOpID), name(), initializer(0) {} + AutoVarOp() : UnaryOperator(AutoVarOpID), name() {} virtual ~AutoVarOp(); /// @} @@ -187,9 +187,9 @@ /// @{ public: const std::string& getName() const { return name; } - bool hasInitializer() const { return initializer != 0; } - Constant* getInitializer() const { return initializer; } - bool isZeroInitialized() const { return initializer == 0; } + bool hasInitializer() const { return getOperand(0) != 0; } + Operator* getInitializer() const { return getOperand(0); } + bool isZeroInitialized() const { return getOperand(0) == 0; } static inline bool classof(const AutoVarOp*) { return true; } static inline bool classof(const Node* N) { return N->is(AutoVarOpID); } @@ -198,56 +198,55 @@ /// @{ public: void setName(const std::string& n) { name = n; } - void setInitializer(Constant* C) { initializer = C; } + void setInitializer(Operator* init) { setOperand(0,init); } /// @} /// @name Data /// @{ protected: std::string name; - Constant* initializer; /// @} friend class AST; }; /// This class provides an Abstract Syntax Tree node that represents an operator -/// for obtaining a value. The operator has no operands but has a property -/// that is the Value to be referenced. The Value must be an AutoVarOp or one -/// of the Linkable (Variable, Constant, Function). This operator -/// bridges between non-operator Values and Operators. The result of this -/// operator is the address of the memory object. Typically this operator is +/// for getting a value. The operator has no operands but has a property +/// that is the Documentable to be retrieved. The retrieved object must be a +/// Type, or Linkable (Variable, Constant, Function). This operator bridges +/// bridges between non-operator Documentables and Operators. The result of this +/// operator is the address of the object. Typically this operator is /// used as the operand of a LoadOp or StoreOp. /// @see Variable AutoVarOp Operator Value Linkable LoadOp StoreOp /// @brief AST Reference Operator -class ReferenceOp : public NilaryOperator +class GetOp : public NilaryOperator { /// @name Constructors /// @{ protected: - ReferenceOp() : NilaryOperator(ReferenceOpID) {} - virtual ~ReferenceOp(); + GetOp() : NilaryOperator(GetOpID) {} + virtual ~GetOp(); /// @} /// @name Accessors /// @{ public: - const Value* getReferent() const { return referent; } - static inline bool classof(const ReferenceOp*) { return true; } + const Documentable* getReferent() const { return referent; } + static inline bool classof(const GetOp*) { return true; } static inline bool classof(const Node* N) { - return N->is(ReferenceOpID); + return N->is(GetOpID); } /// @} /// @name Mutators /// @{ public: - void setReferent(const Value* ref) { referent = ref; } + void setReferent(const Documentable* ref) { referent = ref; } /// @} /// @name Data /// @{ protected: - const Value* referent; + const Documentable* referent; /// @} friend class AST; }; Modified: hlvm/AST/Node.cpp =================================================================== --- hlvm/AST/Node.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/Node.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -34,6 +34,8 @@ #include #include +using namespace llvm; + namespace hlvm { Node::~Node() @@ -48,7 +50,9 @@ last = p; p = p->parent; } - return llvm::cast(last); + if (isa(last)) + return cast(last); + return 0; } Bundle* @@ -58,7 +62,7 @@ while (p && !p->is(BundleID)) p = p->getParent(); if (!p) return 0; - return llvm::cast(p); + return cast(p); } void Modified: hlvm/AST/Node.h =================================================================== --- hlvm/AST/Node.h 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/AST/Node.h 2006-07-31 07:34:42 UTC (rev 433) @@ -149,8 +149,8 @@ PInfOpID, ///< Constant Positive Infinity Real Value NInfOpID, ///< Constant Negative Infinity Real Value NaNOpID, ///< Constant Not-A-Number Real Value - ReferenceOpID, ///< Obtain value of Variable/Function/Constant -LastNilaryOperatorID = ReferenceOpID, + GetOpID, ///< Obtain value of Variable/Function/Constant +LastNilaryOperatorID = GetOpID, // Control Flow Unary Operators ResultOpID, ///< Specify the result of a block or function @@ -165,7 +165,8 @@ PostIncrOpID, ///< Post-Increment Unary Integer Operator PreDecrOpID, ///< Pre-Decrement Unary Integer Operator PostDecrOpID, ///< Post-Decrement Unary Integer Operator - SizeOfID, ///< Size of a constant + SizeOfOpID, ///< Size of a constant + ConvertOpID, ///< Convert one type to another // Real Arithmetic Unary Operators IsPInfOpID, ///< Real Number Positive Infinity Test Operator @@ -317,7 +318,8 @@ bool isIntegralType() const { return (id == IntegerTypeID) || (id == RangeTypeID) || - (id == EnumerationTypeID) || (id == BooleanTypeID); } + (id == EnumerationTypeID) || (id == BooleanTypeID) || + (id == CharacterTypeID); } bool isNumericType() const { return isIntegralType() || id == RealTypeID; } Modified: hlvm/CodeGen/LLVMEmitter.h =================================================================== --- hlvm/CodeGen/LLVMEmitter.h 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/CodeGen/LLVMEmitter.h 2006-07-31 07:34:42 UTC (rev 433) @@ -320,6 +320,12 @@ return llvm::BinaryOperator::create(llvm::Instruction::Xor, V, getAllOnes(V->getType()), "cmpl", TheBlock); } + llvm::Constant* emitSizeOf(llvm::Value* V1) { + return llvm::ConstantExpr::getSizeOf(V1->getType()); + } + llvm::Constant* emitSizeof(llvm::Type* Ty) { + return llvm::ConstantExpr::getSizeOf(Ty); + } llvm::BinaryOperator* emitAdd(llvm::Value* V1, llvm::Value* V2) { return llvm::BinaryOperator::create(llvm::Instruction::Add, V1, V2, "add", TheBlock); @@ -405,6 +411,13 @@ return new llvm::GetElementPtrInst(V,indices,"",TheBlock); } + llvm::GetElementPtrInst* emitGEP(llvm::Value* V, llvm::Value* index) { + ArgList indices; + indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy)); + indices.push_back(index); + return new llvm::GetElementPtrInst(V,indices,"",TheBlock); + } + /// This method implements an assignment of a src value to a pointer to a /// destination value. It handles all cases from a simple store instruction /// for first class types, to construction of temporary global variables Modified: hlvm/CodeGen/LLVMGenerator.cpp =================================================================== --- hlvm/CodeGen/LLVMGenerator.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/CodeGen/LLVMGenerator.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -114,11 +114,10 @@ llvm::Constant* getConstant(const hlvm::Constant* C); llvm::Value* getVariable(const hlvm::Variable* V); llvm::Function* getFunction(const hlvm::Function* F); + llvm::Argument* getArgument(const hlvm::Argument* arg); inline llvm::GlobalValue::LinkageTypes getLinkageTypes(LinkageKinds lk); inline std::string getLinkageName(const Linkable* li); - inline llvm::Value* getBoolean(llvm::Value* op); - inline llvm::Value* getInteger(llvm::Value* op); - inline llvm::Value* getReferent(hlvm::ReferenceOp* r); + inline llvm::Value* getReferent(hlvm::GetOp* r); inline llvm::Value* toBoolean(llvm::Value* op); inline llvm::Value* ptr2Value(llvm::Value* op); inline llvm::Value* coerce(llvm::Value* op); @@ -481,7 +480,7 @@ } llvm::Value* -LLVMGeneratorPass::getVariable(const Variable* V) +LLVMGeneratorPass::getVariable(const hlvm::Variable* V) { hlvmAssert(V != 0); hlvmAssert(V->is(VariableID)); @@ -527,6 +526,26 @@ ); } +llvm::Argument* +LLVMGeneratorPass::getArgument(const hlvm::Argument* arg) +{ + unsigned argNum = arg->getArgNum(); + hlvmAssert(argNum != 0); + argNum--; + hlvm::Function* hF = llvm::cast(arg->getParent()); + llvm::Function* lF = getFunction(hF); + llvm::Function::ArgumentListType& arglist = lF->getArgumentList(); + // Bump the argument number to accommodate the first argument being + // a pointer to the result, if the type of the result is not first-class. + if (!getType(hF->getResultType())->isFirstClassType()) + argNum++; + llvm::Function::arg_iterator I = lF->arg_begin(), E = lF->arg_end(); + for (; I != E && argNum; ++I, --argNum) + ; + hlvmAssert(I != E); + return I; +} + llvm::GlobalValue::LinkageTypes LLVMGeneratorPass::getLinkageTypes(LinkageKinds lk) { @@ -543,9 +562,9 @@ } llvm::Value* -LLVMGeneratorPass::getReferent(hlvm::ReferenceOp* r) +LLVMGeneratorPass::getReferent(hlvm::GetOp* r) { - hlvm::Value* referent = const_cast(r->getReferent()); + const hlvm::Documentable* referent = r->getReferent(); llvm::Value* v = 0; if (llvm::isa(referent)) { AutoVarMap::const_iterator I = @@ -566,7 +585,9 @@ hlvmAssert(F && "Function not found?"); v = F; } else if (llvm::isa(referent)) { - ; + llvm::Argument* arg = getArgument(llvm::cast(referent)); + hlvmAssert(arg && "Argument not found?"); + v = arg; } else hlvmDeadCode("Referent not a linkable or autovar?"); return v; @@ -731,12 +752,12 @@ // alloca is in a block that is in a loop. const llvm::Type* elemType = getType(av->getType()); llvm::Value* alloca = em.NewAutoVar(elemType,av->getName()); - llvm::Constant* C = 0; + llvm::Value* init = 0; if (av->hasInitializer()) - C = getConstant(av->getInitializer()); + init = popOperand(av->getInitializer()); else - C = em.getNullValue(elemType); - em.emitAssign(alloca,C); + init = em.getNullValue(elemType); + em.emitAssign(alloca,init); pushOperand(alloca,av); lvars[av] = alloca; } @@ -855,6 +876,49 @@ } template<> void +LLVMGeneratorPass::gen(SizeOfOp* op) +{ + llvm::Value* op1 = popOperand(op->getOperand(0)); + pushOperand(em.emitSizeOf(op1),op); +} + +template<> void +LLVMGeneratorPass::gen(ConvertOp* op) +{ + // Get the value to be converted + hlvm::Operator* op1 = op->getOperand(0); + // Get the type of the value to be converted + const hlvm::Type* srcTy = op1->getType(); + // Get the llvm Value for the value to be converted + llvm::Value* v1 = popOperand(op1); + + // Get the target type + hlvm::GetOp* op2 = llvm::cast(op->getOperand(1)); + const hlvm::Type* tgtTy = llvm::cast(op2->getReferent()); + llvm::Value* v2 = popOperand(op2); + + // Get the source and target types as an llvm type + const llvm::Type* lsrcTy = getType(srcTy); + const llvm::Type* ltgtTy = getType(tgtTy); + + // First, deal with the easy case of conversion of first class types. This + // can just be done with the LLVM cast operator + if (lsrcTy->isFirstClassType() && ltgtTy->isFirstClassType()) { + pushOperand(em.emitCast(v1,ltgtTy,v1->getName() + "_converted"),op); + return; + } + + // Okay, this isn't going to be pretty. HLVM gaurantees that an object of + // any type is coercible to any other type. The following code makes this + // happen. + switch (srcTy->getID()) + { + default: // FIXME!! + hlvmNotImplemented("Conversion of non-first-class types"); + } +} + +template<> void LLVMGeneratorPass::gen(AddOp* op) { llvm::Value* op1 = popOperand(op->getOperand(0)); @@ -1414,7 +1478,7 @@ } template<> void -LLVMGeneratorPass::gen(ReferenceOp* r) +LLVMGeneratorPass::gen(GetOp* r) { llvm::Value* referent = getReferent(r); pushOperand(referent,r); @@ -1423,8 +1487,27 @@ template<> void LLVMGeneratorPass::gen(GetFieldOp* i) { - llvm::Value* location = popOperand(i->getOperand(0)); - llvm::Value* fld = popOperand(i->getOperand(1)); + hlvm::Operator* loc = i->getOperand(0); + hlvm::Operator* field = i->getOperand(1); + if (hlvm::GetOp* Ref = llvm::dyn_cast(field)) + if (const hlvm::Documentable* referent = Ref->getReferent()) + if (const hlvm::ConstantString* CS = + llvm::dyn_cast(referent)) { + const std::string& fldName = CS->getValue(); + const DisparateContainerType* DCT = + llvm::cast(loc->getType()); + unsigned index = DCT->getFieldIndex(fldName); + hlvmAssert(index != 0 && "Invalid field name"); + llvm::Constant* idx = llvm::ConstantUInt::get(llvm::Type::UIntTy,index); + llvm::Value* location = popOperand(loc); + pushOperand(em.emitGEP(location,idx),i); + return; + } + + // The operand is not a constant string. We must look the field up at runtime + hlvmNotImplemented("Lookup of field at runtime"); + llvm::Value* location = popOperand(loc); + llvm::Value* fld = popOperand(field); } template<> void @@ -1432,6 +1515,7 @@ { llvm::Value* location = popOperand(i->getOperand(0)); llvm::Value* index = popOperand(i->getOperand(1)); + pushOperand(em.emitGEP(location,index),i); } template<> void @@ -1693,6 +1777,8 @@ case PreDecrOpID: gen(llvm::cast(n)); break; case PostIncrOpID: gen(llvm::cast(n)); break; case PostDecrOpID: gen(llvm::cast(n)); break; + case SizeOfOpID: gen(llvm::cast(n)); break; + case ConvertOpID: gen(llvm::cast(n)); break; case AddOpID: gen(llvm::cast(n)); break; case SubtractOpID: gen(llvm::cast(n)); break; case MultiplyOpID: gen(llvm::cast(n)); break; @@ -1726,7 +1812,7 @@ case CallOpID: gen(llvm::cast(n)); break; case LoadOpID: gen(llvm::cast(n)); break; case StoreOpID: gen(llvm::cast(n)); break; - case ReferenceOpID: gen(llvm::cast(n)); break; + case GetOpID: gen(llvm::cast(n)); break; case AutoVarOpID: gen(llvm::cast(n)); break; case OpenOpID: gen(llvm::cast(n)); break; case CloseOpID: gen(llvm::cast(n)); break; Modified: hlvm/Pass/Pass.cpp =================================================================== --- hlvm/Pass/Pass.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/Pass/Pass.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -45,7 +45,7 @@ PassManagerImpl() : PassManager(), pre(), post() {} void addPass(Pass* p); virtual void runOn(AST* tree); - virtual void runOn(AST* tree, Node* startAt); + virtual void runOnNode(Node* startAt); inline void runIfInterested(Pass* p, Node* n, Pass::TraversalKinds m); inline void runPreOrder(Node* n); @@ -190,16 +190,14 @@ } void -PassManagerImpl::runOn(AST* tree, Node* startAt) +PassManagerImpl::runOnNode(Node* startAt) { // Check to make sure startAt is in tree - hlvmAssert(tree != 0 && "Can't run passes on null tree"); hlvmAssert(startAt != 0 && "Can't run passes from null start"); - Node* parent = startAt; - while (parent->getParent() != 0) parent = parent->getParent(); - hlvmAssert(parent == tree && "Can't run passes on node that isn't in tree"); - if (isa(startAt)) + if (isa(startAt)) + runOn(cast(startAt)); + else if (isa(startAt)) runOn(cast(startAt)); else if (isa(startAt)) runOn(cast(startAt)); @@ -207,6 +205,8 @@ runOn(cast(startAt)); else if (isa(startAt)) runOn(cast(startAt)); + else if (isa(startAt)) + runOn(cast(startAt)); else hlvmAssert(!"startAt type not supported"); } Modified: hlvm/Pass/Pass.h =================================================================== --- hlvm/Pass/Pass.h 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/Pass/Pass.h 2006-07-31 07:34:42 UTC (rev 433) @@ -126,7 +126,7 @@ static PassManager* create(); virtual void addPass(Pass* p) = 0; virtual void runOn(AST* tree) = 0; - virtual void runOn(AST* tree, Node* startAt) = 0; + virtual void runOnNode(Node* startAt) = 0; }; bool validate(AST* tree); Modified: hlvm/Pass/Validate.cpp =================================================================== --- hlvm/Pass/Validate.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/Pass/Validate.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -995,13 +995,17 @@ ValidateImpl::validate(StoreOp* n) { if (checkOperator(n,StoreOpID,2)) { - const Type* Ty1 = n->getOperand(0)->getType(); - const Type* Ty2 = n->getOperand(1)->getType(); + Operator* op1 = n->getOperand(0); + Operator* op2 = n->getOperand(1); + const Type* Ty1 = op1->getType(); + const Type* Ty2 = op2->getType(); if (Ty1 != Ty2) { error(n,"StoreOp operands do not agree in type"); - } else if (const ReferenceOp* ref = - dyn_cast(n->getOperand(0))) { - const Value* R = ref->getReferent(); + } else if (isa(op1)) { + if (cast(op1)->isConstant()) + error(n,"Can't store to constant automatic variable"); + } else if (const GetOp* ref = dyn_cast(n->getOperand(0))) { + const Documentable* R = ref->getReferent(); if (isa(R) && cast(R)->isConstant()) error(n,"Can't store to constant variable"); else if (isa(R) && cast(R)->isConstant()) @@ -1044,13 +1048,13 @@ } template<> inline void -ValidateImpl::validate(ReferenceOp* op) +ValidateImpl::validate(GetOp* op) { - if (checkOperator(op,ReferenceOpID,0,true)) { - const Value* referent = op->getReferent(); + if (checkOperator(op,GetOpID,0,true)) { + const Documentable* referent = op->getReferent(); Block* blk = op->getContainingBlock(); if (!blk) - error(op,"ReferenceOp not in a block?"); + error(op,"GetOp not in a block?"); else if (const AutoVarOp* ref = dyn_cast(referent)) { while (blk != 0) { if (AutoVarOp* av = blk->getAutoVar(ref->getName())) @@ -1063,15 +1067,21 @@ } else if (const Argument* arg = dyn_cast(referent)) { Function* F = op->getContainingFunction(); if (!F) - error(op,"ReferenceOp not in a function?"); + error(op,"GetOp not in a function?"); else if (F->getArgument(arg->getName()) != arg) error(F,"Referent does not match function argument"); } else if (const Constant* cval = dyn_cast(referent)) { Bundle* B = op->getContainingBundle(); if (!B) - error(op,"ReferenceOp not in a bundle?"); + error(op,"GetOp not in a bundle?"); else if (B->getConst(cval->getName()) != cval) - error(cval,"Referent does not value found in Bundle"); + error(cval,"Constant not found in Bundle"); + } else if (const Type* Ty = dyn_cast(referent)) { + Bundle* B = op->getContainingBundle(); + if (!B) + error(op,"GetOp not in bundle?"); + else if (B->getType(Ty->getName()) != Ty) + error(Ty,"Type not found in Bundle"); } else { error(op,"Referent of unknown kind"); } @@ -1102,15 +1112,15 @@ ValidateImpl::validate(PreIncrOp* n) { if (checkOperator(n,PreIncrOpID,1)) { - if (ReferenceOp* oprnd = llvm::dyn_cast(n->getOperand(0))) { - const Value* V = oprnd->getReferent(); + if (GetOp* oprnd = llvm::dyn_cast(n->getOperand(0))) { + const Documentable* V = oprnd->getReferent(); if (V && (isa(V) || isa(V))) { - if (!V->getType()->isNumericType()) + if (!llvm::cast(V)->getType()->isNumericType()) error(n,"Target of PostIncrOp is not numeric type"); } else ; // Handled elsewhere } else - error(n,"Operand of PostIncrOp must be a ReferenceOp"); + error(n,"Operand of PostIncrOp must be a GetOp"); } } @@ -1118,15 +1128,15 @@ ValidateImpl::validate(PostIncrOp* n) { if (checkOperator(n,PostIncrOpID,1)) { - if (ReferenceOp* oprnd = llvm::dyn_cast(n->getOperand(0))) { - const Value* V = oprnd->getReferent(); + if (GetOp* oprnd = llvm::dyn_cast(n->getOperand(0))) { + const Documentable* V = oprnd->getReferent(); if (V && (isa(V) || isa(V))) { - if (!V->getType()->isNumericType()) + if (!llvm::cast(V)->getType()->isNumericType()) error(n,"Target of PostIncrOp is not numeric type"); } else ; // Handled elsewhere } else - error(n,"Operand of PostIncrOp must be a ReferenceOp"); + error(n,"Operand of PostIncrOp must be a GetOp"); } } @@ -1134,15 +1144,15 @@ ValidateImpl::validate(PreDecrOp* n) { if (checkOperator(n,PreDecrOpID,1)){ - if (ReferenceOp* oprnd = llvm::dyn_cast(n->getOperand(0))) { - const Value* V = oprnd->getReferent(); + if (GetOp* oprnd = llvm::dyn_cast(n->getOperand(0))) { + const Documentable* V = oprnd->getReferent(); if (V && (isa(V) || isa(V))) { - if (!V->getType()->isNumericType()) + if (!llvm::cast(V)->getType()->isNumericType()) error(n,"Target of PreDecrOp is not numeric type"); } else ; // Handled elsewhere } else - error(n,"Operand of PreDecrOp must be a ReferenceOp"); + error(n,"Operand of PreDecrOp must be a GetOp"); } } @@ -1150,19 +1160,40 @@ ValidateImpl::validate(PostDecrOp* n) { if (checkOperator(n,PostDecrOpID,1)) { - if (ReferenceOp* oprnd = llvm::dyn_cast(n->getOperand(0))) { - const Value* V = oprnd->getReferent(); + if (GetOp* oprnd = llvm::dyn_cast(n->getOperand(0))) { + const Documentable* V = oprnd->getReferent(); if (V && (isa(V) || isa(V))) { - if (!V->getType()->isNumericType()) + if (!llvm::cast(V)->getType()->isNumericType()) error(n,"Target of PostDecrOp is not numeric type"); } else ; // Handled elsewhere } else - error(n,"Operand of PostDecrOp must be a ReferenceOp"); + error(n,"Operand of PostDecrOp must be a GetOp"); } } template<> inline void +ValidateImpl::validate(SizeOfOp* n) +{ + if (checkOperator(n,SizeOfOpID,2)) + ; +} + +template<> inline void +ValidateImpl::validate(ConvertOp* n) +{ + if (checkOperator(n,ConvertOpID,2)) { + const Operator* Oprnd1 = n->getOperand(0); + const Operator* Oprnd2 = n->getOperand(1); + if (const GetOp* RO = dyn_cast(Oprnd2)) { + if (!isa(RO->getReferent())) + error(n,"Second operand must be a reference to atype"); + } else + error(n,"Second operand must be a GetOp"); + } +} + +template<> inline void ValidateImpl::validate(AddOp* n) { if (checkOperator(n,AddOpID,2)) { @@ -1656,7 +1687,7 @@ case AllocateOpID: validate(cast(n)); break; case DeallocateOpID: validate(cast(n)); break; case ReallocateOpID: /*validate(cast(n));*/ break; - case ReferenceOpID: validate(cast(n)); break; + case GetOpID: validate(cast(n)); break; case AutoVarOpID: validate(cast(n)); break; case NegateOpID: validate(cast(n)); break; case ComplementOpID: validate(cast(n)); break; @@ -1664,6 +1695,8 @@ case PostIncrOpID: validate(cast(n)); break; case PreDecrOpID: validate(cast(n)); break; case PostDecrOpID: validate(cast(n)); break; + case SizeOfOpID: validate(cast(n)); break; + case ConvertOpID: validate(cast(n)); break; case AddOpID: validate(cast(n)); break; case SubtractOpID: validate(cast(n)); break; case MultiplyOpID: validate(cast(n)); break; Modified: hlvm/Reader/HLVM.rng =================================================================== --- hlvm/Reader/HLVM.rng 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/Reader/HLVM.rng 2006-07-31 07:34:42 UTC (rev 433) @@ -500,7 +500,7 @@ - + @@ -636,13 +636,6 @@ - - - - - - - @@ -723,6 +716,8 @@ + + @@ -734,6 +729,8 @@ + + @@ -760,7 +757,7 @@ - + @@ -822,12 +819,12 @@ - + - - + + @@ -874,12 +871,10 @@ + - - - + - @@ -954,25 +949,25 @@ - + - + - + - + @@ -989,6 +984,7 @@ + @@ -1046,6 +1042,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modified: hlvm/Reader/XMLReader.cpp =================================================================== --- hlvm/Reader/XMLReader.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/Reader/XMLReader.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -941,26 +941,23 @@ std::string name, type; getNameType(cur, name, type); const Type* Ty = getType(type); - const char* init = getAttribute(cur,"init",false); - Constant*initializer = 0; - if (init) { - initializer = bundle->getConst(init); - if (!initializer) - error(loc,std::string("Initializer '") + init + "' not found ."); + AutoVarOp* result = ast->AST::new_AutoVarOp(name,Ty,loc); + xmlNodePtr child = checkDoc(cur,result); + if (child && skipBlanks(child)) { + Operator* oprnd1 = parseOperator(child); + oprnd1->setParent(result); } - AutoVarOp* autovar = ast->AST::new_AutoVarOp(name,Ty,initializer,loc); - checkDoc(cur,autovar); - return autovar; + return result; } -template<> ReferenceOp* -XMLReaderImpl::parse(xmlNodePtr& cur) +template<> GetOp* +XMLReaderImpl::parse(xmlNodePtr& cur) { std::string id = getAttribute(cur,"id"); Locator* loc = getLocator(cur); // Find the referrent variable in a block - Value* referent = 0; + Documentable* referent = 0; for (BlockStack::reverse_iterator I = blocks.rbegin(), E = blocks.rend(); I != E; ++I ) { @@ -980,11 +977,15 @@ if (!referent) referent= bundle->getConst(id); - // Didn't find a linkable? Try an error message for size + // Didn't find a linkable? Try a type. if (!referent) + referent = bundle->getType(id); + + // Didn't find a type? Try an error message for size + if (!referent) error(loc,std::string("Referent '") + id + "' not found"); - ReferenceOp* refop = ast->AST::new_ReferenceOp(referent, loc); + GetOp* refop = ast->AST::new_GetOp(referent, loc); checkDoc(cur,refop); return refop; } @@ -1281,6 +1282,24 @@ case TKN_gt: op = parseBinaryOp(cur); break; case TKN_ge: op = parseBinaryOp(cur); break; case TKN_le: op = parseBinaryOp(cur); break; + case TKN_ispinf: op = parseUnaryOp(cur); break; + case TKN_isninf: op = parseUnaryOp(cur); break; + case TKN_isnan: op = parseUnaryOp(cur); break; + case TKN_trunc: op = parseUnaryOp(cur); break; + case TKN_round: op = parseUnaryOp(cur); break; + case TKN_floor: op = parseUnaryOp(cur); break; + case TKN_ceiling: op = parseUnaryOp(cur); break; + case TKN_logE: op = parseUnaryOp(cur); break; + case TKN_log2: op = parseUnaryOp(cur); break; + case TKN_log10: op = parseUnaryOp(cur); break; + case TKN_squareroot: op = parseUnaryOp(cur); break; + case TKN_cuberoot: op = parseUnaryOp(cur); break; + case TKN_factorial: op = parseUnaryOp(cur); break; + case TKN_power: op = parseBinaryOp(cur); break; + case TKN_root: op = parseBinaryOp(cur); break; + case TKN_GCD: op = parseBinaryOp(cur); break; + case TKN_LCM: op = parseBinaryOp(cur); break; + case TKN_convert: op = parseBinaryOp(cur); break; case TKN_select: op = parseTernaryOp(cur); break; case TKN_switch: op = parseMultiOp(cur); break; case TKN_while: op = parseBinaryOp(cur); break; @@ -1299,7 +1318,7 @@ case TKN_open: op = parseUnaryOp(cur); break; case TKN_write: op = parseBinaryOp(cur); break; case TKN_close: op = parseUnaryOp(cur); break; - case TKN_ref: op = parse(cur); break; + case TKN_get: op = parse(cur); break; case TKN_autovar: op = parse(cur); break; case TKN_block: op = parse(cur); break; default: Modified: hlvm/Writer/XMLWriter.cpp =================================================================== --- hlvm/Writer/XMLWriter.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ hlvm/Writer/XMLWriter.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -705,10 +705,6 @@ startElement("autovar"); writeAttribute("id",av->getName()); writeAttribute("type",av->getType()->getName()); - if (av->hasInitializer()) { - Constant* C = llvm::cast(av->getInitializer()); - writeAttribute("init",C->getName()); - } putDoc(av); } @@ -895,6 +891,125 @@ } template<> void +XMLWriterImpl::WriterPass::put(const IsPInfOp* op) +{ + startElement("ispinf"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const IsNInfOp* op) +{ + startElement("isninf"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const IsNanOp* op) +{ + startElement("isnan"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const TruncOp* op) +{ + startElement("trunc"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const RoundOp* op) +{ + startElement("round"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const FloorOp* op) +{ + startElement("floor"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const CeilingOp* op) +{ + startElement("ceiling"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const LogEOp* op) +{ + startElement("loge"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const Log2Op* op) +{ + startElement("log2"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const Log10Op* op) +{ + startElement("log10"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const SquareRootOp* op) +{ + startElement("squareroot"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const CubeRootOp* op) +{ + startElement("cuberoot"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const FactorialOp* op) +{ + startElement("factorial"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const PowerOp* op) +{ + startElement("power"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const RootOp* op) +{ + startElement("root"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const GCDOp* op) +{ + startElement("GCD"); + putDoc(op); +} + +template<> void +XMLWriterImpl::WriterPass::put(const LCMOp* op) +{ + startElement("LCM"); + putDoc(op); +} + +template<> void XMLWriterImpl::WriterPass::put(const SelectOp* op) { startElement("select"); @@ -1000,10 +1115,10 @@ } template<> void -XMLWriterImpl::WriterPass::put(const ReferenceOp* r) +XMLWriterImpl::WriterPass::put(const GetOp* r) { - startElement("ref"); - const Value* ref = r->getReferent(); + startElement("get"); + const Documentable* ref = r->getReferent(); std::string name; if (isa(ref)) name = cast(ref)->getName(); @@ -1011,6 +1126,8 @@ name = cast(ref)->getName(); else if (isa(ref)) name = cast(ref)->getName(); + else if (isa(ref)) + name = cast(ref)->getName(); else name = "oops"; writeAttribute("id",name); @@ -1039,6 +1156,13 @@ } template<> void +XMLWriterImpl::WriterPass::put(const ConvertOp* r) +{ + startElement("convert"); + putDoc(r); +} + +template<> void XMLWriterImpl::WriterPass::put(const Bundle* b) { startElement("bundle"); @@ -1135,10 +1259,28 @@ case GetFieldOpID: put(cast(n)); break; case GetIndexOpID: put(cast(n)); break; case LoadOpID: put(cast(n)); break; - case ReferenceOpID: put(cast(n)); break; + case GetOpID: put(cast(n)); break; case OpenOpID: put(cast(n)); break; case CloseOpID: put(cast(n)); break; case WriteOpID: put(cast(n)); break; + case ConvertOpID: put(cast(n)); break; + case IsPInfOpID: put(cast(n)); break; + case IsNInfOpID: put(cast(n)); break; + case IsNanOpID: put(cast(n)); break; + case TruncOpID: put(cast(n)); break; + case RoundOpID: put(cast(n)); break; + case FloorOpID: put(cast(n)); break; + case CeilingOpID: put(cast(n)); break; + case LogEOpID: put(cast(n)); break; + case Log2OpID: put(cast(n)); break; + case Log10OpID: put(cast(n)); break; + case SquareRootOpID: put(cast(n)); break; + case CubeRootOpID: put(cast(n)); break; + case FactorialOpID: put(cast(n)); break; + case PowerOpID: put(cast(n)); break; + case RootOpID: put(cast(n)); break; + case GCDOpID: put(cast(n)); break; + case LCMOpID: put(cast(n)); break; default: hlvmDeadCode("Unknown Type"); break; @@ -1191,8 +1333,9 @@ { if (!node) return; - pass.handle(node,Pass::PreOrderTraversal); - pass.handle(node,Pass::PostOrderTraversal); + PassManager* PM = PassManager::create(); + PM->addPass(&pass); + PM->runOnNode(node); } #endif Modified: test/return0/arithmetic.hlx =================================================================== --- test/return0/arithmetic.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/arithmetic.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -13,14 +13,14 @@
- - + +
- +
- +
- + Modified: test/return0/bitwise.hlx =================================================================== --- test/return0/bitwise.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/bitwise.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -12,14 +12,14 @@ - - + + - + - + - + Modified: test/return0/boolean.hlx =================================================================== --- test/return0/boolean.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/boolean.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -13,17 +13,17 @@ - - + + - + - + - + - - + + Modified: test/return0/break.hlx =================================================================== --- test/return0/break.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/break.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -11,14 +11,14 @@ - + - + Modified: test/return0/call.hlx =================================================================== --- test/return0/call.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/call.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -6,7 +6,7 @@ - + @@ -16,7 +16,7 @@ - + Modified: test/return0/complement.hlx =================================================================== --- test/return0/complement.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/complement.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -8,7 +8,7 @@ - + Modified: test/return0/continue.hlx =================================================================== --- test/return0/continue.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/continue.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -9,17 +9,17 @@ - + - + Modified: test/return0/helloworld.hlx =================================================================== --- test/return0/helloworld.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/helloworld.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -15,18 +15,18 @@ - - + + - - + + - + - + Modified: test/return0/loop.hlx =================================================================== --- test/return0/loop.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/loop.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -12,13 +12,13 @@ - - + + - + - - + + Modified: test/return0/noresult.hlx =================================================================== --- test/return0/noresult.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/noresult.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -11,14 +11,14 @@ - + Modified: test/return0/resultoverride.hlx =================================================================== --- test/return0/resultoverride.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/resultoverride.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -6,10 +6,10 @@ - + - + Modified: test/return0/return0.hlx =================================================================== --- test/return0/return0.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/return0.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -5,7 +5,7 @@ - + Modified: test/return0/select.hlx =================================================================== --- test/return0/select.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/select.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -13,17 +13,17 @@ - + - + Modified: test/return0/unless.hlx =================================================================== --- test/return0/unless.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/unless.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -12,10 +12,10 @@ - - + + - + Modified: test/return0/until.hlx =================================================================== --- test/return0/until.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/until.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -11,10 +11,10 @@ - + - - + + Modified: test/return0/unused.hlx =================================================================== --- test/return0/unused.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/unused.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -11,14 +11,14 @@ - + Modified: test/return0/while.hlx =================================================================== --- test/return0/while.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/return0/while.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -12,10 +12,10 @@ - - + + - + Modified: test/xml2xml/argscall.hlx =================================================================== --- test/xml2xml/argscall.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/argscall.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -26,25 +26,25 @@ - + - - + + - - - + + + - - - - + + + + - + Modified: test/xml2xml/arithmetic.hlx =================================================================== --- test/xml2xml/arithmetic.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/arithmetic.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -12,97 +12,97 @@ - + - + - + - + - + - + - + - + - + - + - + - +
- + - +
- + - + - + - + - + - + - + - + - + - + - +
Modified: test/xml2xml/autovar.hlx =================================================================== --- test/xml2xml/autovar.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/autovar.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -6,7 +6,7 @@ - + Modified: test/xml2xml/block.hlx =================================================================== --- test/xml2xml/block.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/block.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -17,19 +17,19 @@ - - + + - + - + Modified: test/xml2xml/booleanops.hlx =================================================================== --- test/xml2xml/booleanops.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/booleanops.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -16,91 +16,91 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
Modified: test/xml2xml/break.hlx =================================================================== --- test/xml2xml/break.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/break.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -10,14 +10,14 @@ - + - + - + Modified: test/xml2xml/call.hlx =================================================================== --- test/xml2xml/call.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/call.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -9,10 +9,10 @@ - + - + Modified: test/xml2xml/continue.hlx =================================================================== --- test/xml2xml/continue.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/continue.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -10,14 +10,14 @@ - + - + - + Modified: test/xml2xml/doc.hlx =================================================================== --- test/xml2xml/doc.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/doc.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -79,7 +79,7 @@ This block just returns a constant result - + This just references the intval constant as the result @@ -95,7 +95,7 @@ Again, doesn't do much but return a result - + This just references the intval constant as the result Modified: test/xml2xml/helloworld.hlx =================================================================== --- test/xml2xml/helloworld.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/helloworld.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -14,24 +14,24 @@ - + - + - + - + - + - + Modified: test/xml2xml/loop.hlx =================================================================== --- test/xml2xml/loop.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/loop.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -15,11 +15,11 @@ - - + + - - + + Modified: test/xml2xml/progargs.hlx =================================================================== --- test/xml2xml/progargs.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/progargs.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -4,7 +4,7 @@ - + Modified: test/xml2xml/return.hlx =================================================================== --- test/xml2xml/return.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/return.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -7,7 +7,7 @@ - + Modified: test/xml2xml/select.hlx =================================================================== --- test/xml2xml/select.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/select.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -15,11 +15,11 @@ Modified: test/xml2xml/switch.hlx =================================================================== --- test/xml2xml/switch.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/switch.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -29,20 +29,20 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + Modified: test/xml2xml/unless.hlx =================================================================== --- test/xml2xml/unless.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/unless.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -11,13 +11,13 @@ - - + + - + - + Modified: test/xml2xml/until.hlx =================================================================== --- test/xml2xml/until.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/until.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -10,14 +10,14 @@ - + - - + + - + Modified: test/xml2xml/while.hlx =================================================================== --- test/xml2xml/while.hlx 2006-07-29 00:34:57 UTC (rev 432) +++ test/xml2xml/while.hlx 2006-07-31 07:34:42 UTC (rev 433) @@ -11,13 +11,13 @@ - - + + - + - + Modified: tools/hlvm-gentestcase/Generate.cpp =================================================================== --- tools/hlvm-gentestcase/Generate.cpp 2006-07-29 00:34:57 UTC (rev 432) +++ tools/hlvm-gentestcase/Generate.cpp 2006-07-31 07:34:42 UTC (rev 433) @@ -46,42 +46,40 @@ using namespace llvm; using namespace hlvm; -namespace -{ - -cl::opt +static cl::opt Complexity("complexity", cl::init(5), cl::desc("Specify complexity of generated code"), cl::value_desc("num")); -cl::opt +static cl::opt TypeComplexity("type-complexity", cl::init(4), cl::desc("Specify type complexity of generated code"), cl::value_desc("num")); -cl::opt +static cl::opt Seed("seed", cl::init(unsigned(time(0))), cl::desc("Specify random number generator seed"), cl::value_desc("num")); -cl::opt +static cl::opt Size("size",cl::desc("Specify size of generated code"), cl::value_desc("num")); -AST* ast = 0; -URI* uri = 0; -Bundle* bundle = 0; -Program* program = 0; -unsigned line = 0; typedef std::vector ValueList; typedef std::map TypeValueMap; -TypeValueMap values; typedef std::vector TypeList; -TypeList types; +static AST* ast = 0; +static URI* uri = 0; +static Bundle* bundle = 0; +static Program* program = 0; +static unsigned line = 0; +static TypeValueMap values; +static TypeList types; + inline Locator* getLocator() { @@ -110,7 +108,7 @@ return low; } -Type* +static Type* genType(unsigned limit) { Type* result = 0; @@ -201,7 +199,7 @@ Locator* loc = getLocator(); std::string name = "array_" + utostr(line); result = ast->new_ArrayType(name,bundle, - genType(limit),randRange(1,Size),loc); + genType(limit),randRange(1,Size*10),loc); break; } case VectorTypeID: @@ -209,7 +207,7 @@ Locator* loc = getLocator(); std::string name = "vector_" + utostr(line); result = ast->new_VectorType(name,bundle, - genType(limit),randRange(1,Size),loc); + genType(limit),randRange(1,Size*10),loc); break; } case OpaqueTypeID: @@ -236,7 +234,7 @@ return result; } -Type* +static Type* genType() { bool shouldGenNewType = randRange(0,5) < TypeComplexity; @@ -248,7 +246,42 @@ return types[ randRange(0,types.size()-1) ]; } -Value* +static ConstantString* +getConstantString(const std::string& str) +{ + typedef std::map strmap; + static strmap stringmap; + strmap::iterator I = stringmap.find(str); + if (I == stringmap.end()) { + Locator* loc = getLocator(); + Type* Ty = bundle->getIntrinsicType(stringTy); + ConstantString* cstr = ast->new_ConstantString( + std::string("cstr_")+utostr(line),bundle,Ty,str,loc); + stringmap[str] = cstr; + return cstr; + } + return I->second; +} + +static ConstantInteger* +getConstantInteger(int32_t val) +{ + typedef std::map intmap; + static intmap integermap; + intmap::iterator I = integermap.find(val); + if (I == integermap.end()) { + Locator* loc = getLocator(); + Type* Ty = bundle->getIntrinsicType(intTy); + std::string val_str = itostr(val); + ConstantInteger* cint = ast->new_ConstantInteger( + std::string("cint_")+utostr(line),bundle,Ty,val_str,10,loc); + integermap[val] = cint; + return cint; + } + return I->second; +} + +static Value* genValue(const Type* Ty, bool is_constant = false) { if (!is_constant && randRange(0,Complexity) < Complexity/2) { @@ -299,8 +332,7 @@ unsigned numChars = randRange(1,Size+Complexity,true); for (unsigned i = 0 ; i < numChars; i++) val += char(randRange(35,126)); - C = ast->new_ConstantString( - std::string("cstr_")+utostr(line),bundle,Ty,val,loc); + C = getConstantString(val); break; } case BufferTypeID: @@ -433,49 +465,530 @@ return result; } -inline Operator* -genValueOperator(const Type *Ty, bool is_constant = false) +static inline GetOp* +getReference(const Value* val) { + hlvmAssert(isa(val) || isa(val) || isa(val)); + return ast->new_GetOp(val,getLocator()); +} + +static inline Operator* +genValueAsOperator(const Type *Ty, bool is_constant = false) +{ Value* V = genValue(Ty,is_constant); - Operator* O = ast->new_ReferenceOp(V,getLocator()); + Operator* O = getReference(V); if (isa(V)) O = ast->new_UnaryOp(O,bundle,getLocator()); return O; } - -CallOp* +static CallOp* genCallTo(Function* F) { std::vector args; - Operator* O = ast->new_ReferenceOp(F,getLocator()); + Operator* O = ast->new_GetOp(F,getLocator()); args.push_back(O); const SignatureType* sig = F->getSignature(); for (SignatureType::const_iterator I = sig->begin(), E = sig->end(); I != E; ++I) { const Type* argTy = (*I)->getType(); - Operator* O = genValueOperator(argTy); + Operator* O = genValueAsOperator(argTy); hlvmAssert(argTy == O->getType()); args.push_back(O); } return ast->new_MultiOp(args,bundle,getLocator()); } -Block* -genBlock() +static Operator* +genIndex(Operator* V) { + if (V->typeis()) { + const StructureType* Ty = cast(V->getType()); + const NamedType* fldname = Ty->getField(randRange(0,Ty->size()-1)); + Constant* cfield = getConstantString(fldname->getName()); + GetOp* field = getReference(cfield); + return ast->new_BinaryOp(V,field,bundle,getLocator()); + } else if (V->typeis()) { + const ArrayType* Ty = cast(V->getType()); + Constant* cindex = getConstantInteger(0); //FIXME: gen rand at runtime + GetOp* index = getReference(cindex); + return ast->new_BinaryOp(V,index,bundle,getLocator()); + } else if (V->typeis()) { + const VectorType* Ty = cast(V->getType()); + int64_t idx = randRange(0,Ty->getSize()-1); + Constant* cindex = getConstantInteger(idx); + GetOp* index = getReference(cindex); + return ast->new_BinaryOp(V,index,bundle,getLocator()); + } else if (V->typeis()) { + const StringType* Ty = cast(V->getType()); + Constant* cindex = getConstantInteger(0); //FIXME: gen rand at runtime + GetOp* index = getReference(cindex); + return ast->new_BinaryOp(V,index,bundle,getLocator()); + } else if (V->typeis()) { + Constant* cindex = getConstantInteger(0); + GetOp* index = getReference(cindex); + return ast->new_BinaryOp(V,index,bundle,getLocator()); + } else + hlvmAssert(!"Can't index this type!"); + return 0; +} + +static Operator* +genBooleanUnary(Operator* V1) +{ + hlvmAssert(V1->getType()->getID() == BooleanTypeID); + return ast->new_UnaryOp(V1,bundle,getLocator()); +} + +static Operator* +genBooleanBinary(Operator* V1, Operator* V2) +{ + hlvmAssert(V1->getType()->getID() == BooleanTypeID); + hlvmAssert(V2->getType()->getID() == BooleanTypeID); + Operator* result = 0; + NodeIDs id = NodeIDs(randRange(AndOpID,InequalityOpID)); + switch (id) { + case AndOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case OrOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case NorOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case XorOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case LessThanOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case GreaterThanOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case LessEqualOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case GreaterEqualOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case EqualityOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case InequalityOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + default: + hlvmAssert(!"Invalid boolean op ID"); + } + return result; +} + +static Operator* +genCharacterUnary(Operator* V1) +{ + hlvmAssert(V1->getType()->getID() == CharacterTypeID); + return 0; +} + +static Operator* +genCharacterBinary(Operator* V1, Operator* V2) +{ + hlvmAssert(V1->getType()->getID() == CharacterTypeID); + hlvmAssert(V2->getType()->getID() == CharacterTypeID); + return 0; +} + +static Operator* +genIntegerUnary(Operator* V1) +{ + hlvmAssert(V1->getType()->getID() == IntegerTypeID); + Operator* result = 0; + NodeIDs id = NodeIDs(randRange(NegateOpID, PostDecrOpID)); + switch (id) { + case NegateOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case ComplementOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case PreIncrOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case PostIncrOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case PreDecrOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case PostDecrOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + default: + hlvmAssert(!"Invalid unary op id for integer"); + result = ast->new_UnaryOp(V1,bundle,getLocator()); + } + return result; +} + +static Operator* +genIntegerBinary(Operator* V1, Operator* V2) +{ + hlvmAssert(V1->getType()->getID() == IntegerTypeID); + hlvmAssert(V2->getType()->getID() == IntegerTypeID); + Operator* result = 0; + NodeIDs id = NodeIDs(randRange(AddOpID, BNorOpID)); + switch (id) { + case AddOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case SubtractOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case MultiplyOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case DivideOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case ModuloOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case BAndOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case BOrOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case BXorOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case BNorOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + default: + hlvmAssert(!"Invalid binary op id for integer"); + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + } + return result; +} + +static Operator* +genRealUnary(Operator* V1) +{ + hlvmAssert(V1->getType()->getID() == RealTypeID); + Operator* result = 0; + NodeIDs id = NodeIDs(randRange(TruncOpID,FactorialOpID)); + switch (id) { + case TruncOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case RoundOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case FloorOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case CeilingOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case LogEOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case Log2OpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case Log10OpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case SquareRootOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case CubeRootOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + case FactorialOpID: + result = ast->new_UnaryOp(V1,bundle,getLocator()); + break; + default: + hlvmAssert(!"Invalid unary op id for integer"); + result = ast->new_UnaryOp(V1,bundle,getLocator()); + } + return result; +} + +static Operator* +genRealBinary(Operator* V1, Operator* V2) +{ + hlvmAssert(V1->getType()->getID() == RealTypeID); + hlvmAssert(V2->getType()->getID() == RealTypeID); + Operator* result = 0; + NodeIDs id = hlvm::NodeIDs(randRange(PowerOpID, LCMOpID)); + switch (id) { + case PowerOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case RootOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case GCDOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + case LCMOpID: + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + break; + default: + hlvmAssert(!"Invalid binary op id for integer"); + result = ast->new_BinaryOp(V1,V2,bundle,getLocator()); + } + return result; +} + +static Operator* +genStringUnary(Operator* V1) +{ + hlvmAssert(V1->getType()->getID() == RealTypeID); + return 0; +} + +static Operator* +genStringBinary(Operator* V1, Operator* V2) +{ + return 0; +} + +static Operator* +genPointerUnary(Operator* V1) +{ + hlvmAssert(V1->getType()->getID() == RealTypeID); + return 0; +} + +static Operator* +genPointerBinary(Operator* V1, Operator* V2) +{ + return 0; +} + +static Operator* +genArrayUnary(Operator* V1) +{ + hlvmAssert(V1->getType()->getID() == RealTypeID); + return 0; +} + +static Operator* +genArrayBinary(Operator* V1, Operator* V2) +{ + return 0; +} + +static Operator* +genVectorUnary(Operator* V1) +{ + hlvmAssert(V1->getType()->getID() == RealTypeID); + return 0; +} + +static Operator* +genVectorBinary(Operator* V1, Operator* V2) +{ + return 0; +} + +static Operator* +genStructureUnary(Operator* V1) +{ + hlvmAssert(V1->getType()->getID() == RealTypeID); + return 0; +} + +static Operator* +genStructureBinary(Operator* V1, Operator* V2) +{ + return 0; +} + +// Forward declare +static Function* genFunction(const Type* resultType, unsigned depth); + +static Operator* +genExpression(Operator* Val, const Type* Ty, unsigned depth) +{ + hlvmAssert(Val->getType() == Ty); + if (depth > 0) { + // Generate a function + Function* F = genFunction(Ty, depth-1); + // Generate a call to that function + return genCallTo(F); + } + + Operator* result = 0; + + // Determine whether to generate a binary or unary expression + if (5 <= randRange(1,10)) { + switch (Ty->getID()) { + case BooleanTypeID: result = genBooleanUnary(Val); break; + case CharacterTypeID: result = genCharacterUnary(Val); break; + case AnyTypeID: + case BufferTypeID: + case StreamTypeID: + case TextTypeID: + case SignatureTypeID: + case RationalTypeID: + // FALL THROUGH: Not Implemented + case RangeTypeID: + case IntegerTypeID: + case EnumerationTypeID: result = genIntegerUnary(Val); break; + case RealTypeID: result = genRealUnary(Val); break; + case StringTypeID: result = genStringUnary(Val); break; + case PointerTypeID: result = genPointerUnary(Val); break; + case ArrayTypeID: result = genArrayUnary(Val); break; + case VectorTypeID: result = genVectorUnary(Val); break; + case OpaqueTypeID: + case ContinuationTypeID: + case StructureTypeID: result = genStructureUnary(Val); break; + default: + hlvmAssert(!"Invalid type?"); + break; + } + } else { + switch (Ty->getID()) { + case BooleanTypeID: + result = genBooleanBinary(Val,genValueAsOperator(Ty)); break; + case CharacterTypeID: + result = genCharacterBinary(Val,genValueAsOperator(Ty)); break; + case AnyTypeID: + case BufferTypeID: + case StreamTypeID: + case TextTypeID: + case SignatureTypeID: + case RationalTypeID: + // FALL THROUGH: Not Implemented + case RangeTypeID: + case IntegerTypeID: + case EnumerationTypeID: + result = genIntegerBinary(Val,genValueAsOperator(Ty));break; + case RealTypeID: + result = genRealBinary(Val,genValueAsOperator(Ty)); break; + case StringTypeID: + result = genStringBinary(Val,genValueAsOperator(Ty)); break; + case PointerTypeID: + result = genPointerBinary(Val,genValueAsOperator(Ty)); break; + case ArrayTypeID: + result = genArrayBinary(Val,genValueAsOperator(Ty)); break; + case VectorTypeID: + result = genVectorBinary(Val,genValueAsOperator(Ty)); break; + case OpaqueTypeID: + case ContinuationTypeID: + case StructureTypeID: + result = genStructureBinary(Val,genValueAsOperator(Ty));break; + default: + hlvmAssert(!"Invalid type?"); + break; + } + } + return result; +} + +static void +genMergeExpression(AutoVarOp* op1, Operator* op2, Block* B) +{ + // Assert precondition + hlvmAssert(op1->getType() == op2->getType()); + + // Get the type of the thing to be merged + const Type* Ty = op2->getType(); + + + // If its just a numeric type, simply add the merged value into the autovar + if (Ty->isNumericType()) { + Operator* get1 = ast->new_GetOp(op1,getLocator()); + Operator* avload = ast->new_UnaryOp(get1,bundle,getLocator()); + Operator* add = ast->new_BinaryOp(avload,op2,bundle,getLocator()); + Operator* get2 = ast->new_GetOp(op1,getLocator()); + Operator* store = ast->new_BinaryOp(get2,add,bundle,getLocator()); + store->setParent(B); + return; + } + + // If its a VectorType or ArrayType then add all the elements, if possible + if (const UniformContainerType* UCT = + llvm::dyn_cast(op2->getType())) { + const Type* elemType = UCT->getElementType(); + if (elemType->isNumericType()) { + Operator* get1 = ast->new_GetOp(op1,getLocator()); + Operator* avload = ast->new_UnaryOp(get1,bundle,getLocator()); + Operator* add = ast->new_BinaryOp(avload,op2,bundle,getLocator()); + Operator* get2 = ast->new_GetOp(op1,getLocator()); + Operator* store =ast->new_BinaryOp(get2,add,bundle,getLocator()); + store->setParent(B); + return; + } + } + + // For everything else, just store the result + Operator* get = ast->new_GetOp(op1,getLocator()); + Operator* op = ast->new_BinaryOp(get,op2,bundle,getLocator()); + op->setParent(B); + return; +} + +static Block* +genFunctionBody(Function* F, unsigned depth) +{ + // Create the function body block and initialize it Block* B = ast->new_Block(getLocator()); + B->setParent(F); + B->setLabel(F->getName() + "_body"); + + // Create an autovar for the function result + AutoVarOp* result = + ast->new_AutoVarOp(F->getName() + "_result", + F->getResultType(),getLocator()); + result->setParent(B); + + // Generate "Size" expressions + for (unsigned i = 0; i < Size; i++) { + // Get a value for the basis of the expression + Operator* theValue = 0; + if (F->size() > 0) { + // Pick an argument randomly to use in the expression + unsigned argNum = randRange(0,F->size()-1); + Argument* arg = F->getArgument(argNum); + theValue = ast->new_GetOp(arg,getLocator()); + } else { + theValue = genValueAsOperator(F->getResultType()); + } + + // Generate the expression + Operator* expr = genExpression(theValue,F->getResultType(),depth-1); + + // Merge the current value of the autovar result with the generated + // expression. + genMergeExpression(result,expr,B); + } + + // Create the block result. + GetOp* get = ast->new_GetOp(result,getLocator()); + ResultOp* rslt = ast->new_UnaryOp(get,bundle,getLocator()); + rslt->setParent(B); + + // Done, Return the new block return B; } -Function* -genFunction(Type* resultType, unsigned numArgs) +static Function* +genFunction(const Type* resultType, unsigned depth) { // Get the function name Locator* loc = getLocator(); std::string name = "func_" + utostr(line); + // Generate a random number of arguments + unsigned numArgs = int(randRange(0,int(Complexity))); + // Get the signature std::string sigName = name + "_type"; SignatureType* sig = ast->new_SignatureType(sigName,bundle,resultType,loc); @@ -484,67 +997,100 @@ for (unsigned i = 0; i < numArgs; ++i ) { std::string name = "arg_" + utostr(i+1); - Parameter* param = ast->new_Parameter(name,genType(),loc); + Parameter* param = ast->new_Parameter(name,resultType,loc); sig->addParameter(param); } sig->setParent(bundle); - // Create the function and set its linkage + // Determine the kind of linkage for this function LinkageKinds LK = LinkageKinds(randRange(ExternalLinkage,InternalLinkage)); if (LK == AppendingLinkage) LK = InternalLinkage; + + // Create the function and set its linkage kind Function* F = ast->new_Function(name,bundle,sig,loc); F->setLinkageKind(LK); - // Create a block and set its parent - Block* B = genBlock(); - B->setParent(F); + // Create the body of the function + Block* blk = genFunctionBody(F,depth); - // Get the function result and return instruction - Operator* O = genValueOperator(F->getResultType()); - ResultOp* rslt = ast->new_UnaryOp(O,bundle,getLocator()); - rslt->setParent(B); - + // Insert the return operator ReturnOp* ret = ast->new_NilaryOp(bundle,getLocator()); - ret->setParent(B); + ret->setParent(blk); // Install the function in the value map values[sig].push_back(F); + // Make the function belong to the bundle + F->setParent(bundle); + return F; } -} - AST* GenerateTestCase(const std::string& pubid, const std::string& bundleName) { + // Seed the random number generator srandom(Seed); + + // Create the top level node of the tree ast = AST::create(); ast->setPublicID(pubid); ast->setSystemID(bundleName); + + // Get a URI for this tree uri = ast->new_URI(pubid); + + // Create a bundle to place the program in. bundle = ast->new_Bundle(bundleName,getLocator()); + + // Create a program node for the generated test program program = ast->new_Program(bundleName,bundle,getLocator()); - Block* blk = ast->new_Block(getLocator()); - blk->setParent(program); + const SignatureType* SigTy = program->getSignature(); + + // Create the function body block and initialize it + Block* B = ast->new_Block(getLocator()); + B->setParent(program); + B->setLabel(program->getName() + "_body"); + + // Create an autovar for the function result + AutoVarOp* result = + ast->new_AutoVarOp(program->getName() + "_result", + program->getResultType(),getLocator()); + result->setParent(B); + + // Generate calls to "Size" random functions for (unsigned i = 0; i < Size; i++) { - Type* result = genType(); - Type* argTy = genType(); - unsigned numArgs = int(randRange(0,int(Complexity))); - Function* F = genFunction(result,numArgs); - F->setParent(bundle); + // Generate a function to a random type + Type* Ty = genType(); + Function* F = genFunction(Ty, Complexity); + + // Generate a call to that function CallOp* call = genCallTo(F); - call->setParent(blk); + + // Coalesce the result of the random function into the autovar we + // created for the result of this block. + if (Ty->isNumericType()) { + Operator* get = + ast->new_GetOp(program->getResultType(),getLocator()); + Operator* cvt = + ast->new_BinaryOp(call,get,bundle,getLocator()); + genMergeExpression(result,cvt,B); + } } + + // Create the block result. + GetOp* get = ast->new_GetOp(result,getLocator()); + ResultOp* rslt = ast->new_UnaryOp(get,bundle,getLocator()); + rslt->setParent(B); - // Get the function result and return instruction - Operator* O = genValueOperator(program->getResultType()); - ResultOp* rslt = ast->new_UnaryOp(O,bundle,getLocator()); - rslt->setParent(blk); + // Insert the return instruction in that block + ReturnOp* ret = ast->new_NilaryOp(bundle,getLocator()); + ret->setParent(B); - ReturnOp* ret = ast->new_NilaryOp(bundle,getLocator()); - ret->setParent(blk); + // Make the program a child of the bundle last so it is output last. program->setParent(bundle); + + // Done. return ast; } From rspencer at reidspencer.com Mon Jul 31 00:42:19 2006 From: rspencer at reidspencer.com (rspencer at reidspencer.com) Date: Mon, 31 Jul 2006 00:42:19 -0700 Subject: [hlvm-commits] r434 - tools/hlvm-config Message-ID: <200607310742.k6V7gJ8v010103@server1.hlvm.org> Author: reid Date: 2006-07-31 00:42:19 -0700 (Mon, 31 Jul 2006) New Revision: 434 Log: Bring the node-ids printout up to date. Modified: tools/hlvm-config/hlvm-config.cpp Modified: tools/hlvm-config/hlvm-config.cpp =================================================================== --- tools/hlvm-config/hlvm-config.cpp 2006-07-31 07:34:42 UTC (rev 433) +++ tools/hlvm-config/hlvm-config.cpp 2006-07-31 07:42:19 UTC (rev 434) @@ -93,7 +93,7 @@ "PInfOp", "NInfOp", "NaNOp", - "ReferenceOp", + "GetOp", "ResultOp", "ThrowOp", "NotOp", @@ -103,7 +103,8 @@ "PostIncrOp", "PreDecrOp", "PostDecrOp", - "SizeOf", + "SizeOfOp", + "ConvertOp", "IsPInfOp", "IsNInfOp", "IsNanOp", @@ -149,6 +150,8 @@ "LCMOp", "ReallocateOp", "StoreOp", + "GetIndexOp", + "GetFieldOp", "WhileOp", "UnlessOp", "UntilOp", @@ -166,7 +169,6 @@ "InvokeOp", "DispatchOp", "CallWithContOp", - "IndexOp", "SwitchOp", "**INVALID**", "**INVALID**", From rspencer at reidspencer.com Mon Jul 31 07:34:46 2006 From: rspencer at reidspencer.com (rspencer at reidspencer.com) Date: Mon, 31 Jul 2006 07:34:46 -0700 Subject: [hlvm-commits] r435 - in test: return0 xml2xml Message-ID: <200607311434.k6VEYkj7012315@server1.hlvm.org> Author: reid Date: 2006-07-31 07:34:46 -0700 (Mon, 31 Jul 2006) New Revision: 435 Log: Fix tests to deal with reality. Modified: test/return0/continue.hlx test/xml2xml/booleanops.hlx test/xml2xml/doc.hlx Modified: test/return0/continue.hlx =================================================================== --- test/return0/continue.hlx 2006-07-31 07:42:19 UTC (rev 434) +++ test/return0/continue.hlx 2006-07-31 14:34:46 UTC (rev 435) @@ -6,7 +6,7 @@ 10 - + Modified: test/xml2xml/booleanops.hlx =================================================================== --- test/xml2xml/booleanops.hlx 2006-07-31 07:42:19 UTC (rev 434) +++ test/xml2xml/booleanops.hlx 2006-07-31 14:34:46 UTC (rev 435) @@ -12,8 +12,12 @@ - - + + + + + + Modified: test/xml2xml/doc.hlx =================================================================== --- test/xml2xml/doc.hlx 2006-07-31 07:42:19 UTC (rev 434) +++ test/xml2xml/doc.hlx 2006-07-31 14:34:46 UTC (rev 435) @@ -83,7 +83,7 @@ This just references the intval constant as the result - + @@ -99,7 +99,7 @@ This just references the intval constant as the result -
+
From rspencer at reidspencer.com Mon Jul 31 14:30:12 2006 From: rspencer at reidspencer.com (rspencer at reidspencer.com) Date: Mon, 31 Jul 2006 14:30:12 -0700 Subject: [hlvm-commits] r436 - hlvm/AST hlvm/CodeGen hlvm/Pass hlvm/Reader hlvm/Writer tools/hlvm-config tools/hlvm-gentestcase Message-ID: <200607312130.k6VLUC8v013898@server1.hlvm.org> Author: reid Date: 2006-07-31 14:30:12 -0700 (Mon, 31 Jul 2006) New Revision: 436 Log: Several changes to start making the code generated by the test case generator work: 1. No need for NInf, PInf, NaN value operators, they are generated at runtime 2. Fill in the missing code generation for Pointers, Vectors, Structures. 3. Making Types be an operand via a GetOp is a bad idea. The type hierarchy gets broken and it causes havoc with code gen. Just use the Type directlry in the ConvertOp. 4. Implement the string operators (insert, erase, replace, concat) 5. Implement code gen shell for the math operators (requires runtime support) 6. Start to support the Rational Type. 7. Implement the Length operator. Modified: hlvm/AST/AST.cpp hlvm/AST/AST.h hlvm/AST/Arithmetic.cpp hlvm/AST/Arithmetic.h hlvm/AST/Bundle.cpp hlvm/AST/Bundle.h hlvm/AST/IntrinsicTypes.rng hlvm/AST/MemoryOps.h hlvm/AST/Node.h hlvm/AST/StringOps.cpp hlvm/AST/StringOps.h hlvm/AST/Type.cpp hlvm/AST/Type.h hlvm/CodeGen/LLVMGenerator.cpp hlvm/Pass/Validate.cpp hlvm/Reader/HLVM.rng hlvm/Reader/XMLReader.cpp hlvm/Writer/XMLWriter.cpp tools/hlvm-config/hlvm-config.cpp tools/hlvm-gentestcase/Generate.cpp Modified: hlvm/AST/AST.cpp =================================================================== --- hlvm/AST/AST.cpp 2006-07-31 14:34:46 UTC (rev 435) +++ hlvm/AST/AST.cpp 2006-07-31 21:30:12 UTC (rev 436) @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -751,23 +752,33 @@ } GetOp* -AST::new_GetOp(const Documentable* D, const Locator*loc) +AST::new_GetOp(const Value* V, const Locator*loc) { - hlvmAssert(D != 0 && "GetOp must have a Value to reference"); + hlvmAssert(V != 0 && "GetOp must have a Value to reference"); GetOp* result = new GetOp(); - if (llvm::isa(D) || - llvm::isa(D) || - llvm::isa(D)) { - result->setType(llvm::cast(D)->getType()); - } else if (llvm::isa(D)) { - result->setType(llvm::cast(D)); + if (llvm::isa(V) || + llvm::isa(V) || + llvm::isa(V)) { + result->setType(llvm::cast(V)->getType()); } else hlvmAssert(!"Invalid referent type"); result->setLocator(loc); - result->setReferent(D); + result->setReferent(V); return result; } +ConvertOp* +AST::new_ConvertOp(Operator* V, const Type* Ty, const Locator* loc) +{ + hlvmAssert(V != 0 && "ConvertOp must have a Value to convert"); + hlvmAssert(Ty != 0 && "ConvertOp must have a type to convert the value"); + ConvertOp* result = new ConvertOp(); + result->setType(Ty); + result->setOperand(V); + result->setLocator(loc); + return result; +} + template OpClass* AST::new_NilaryOp( const Type* Ty, ///< Result type of the operator @@ -945,23 +956,11 @@ template SizeOfOp* AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); -template ConvertOp* -AST::new_BinaryOp( - const Type* Ty, Operator* op1, Operator* op2, const Locator* loc); +template LengthOp* +AST::new_UnaryOp(const Type* Ty, Operator* op1, const Locator* loc); +template LengthOp* +AST::new_UnaryOp(Operator* op1, Bundle* B, const Locator* loc); -template<> ConvertOp* -AST::new_BinaryOp( - Operator* oprnd1, ///< The first operand - Operator* oprnd2, ///< The second operand - Bundle* B, ///< The bundle, for type lookup - const Locator* loc ///< The source locator -) -{ - GetOp* get = llvm::cast(oprnd2); - const Type* Ty = llvm::cast(get->getReferent()); - return new_BinaryOp(Ty,oprnd1,oprnd2,loc); -} - template AddOp* AST::new_BinaryOp( const Type* Ty, Operator* op1, Operator* op2, const Locator* loc); @@ -1212,6 +1211,28 @@ return AST::new_BinaryOp(Ty,op1,op2,loc); } +// String Operators +template StrInsertOp* +AST::new_TernaryOp(const Type* Ty, Operator*op1,Operator*op2,Operator*op3,const Locator* loc); +template StrInsertOp* +AST::new_TernaryOp(Operator*op1,Operator*op2,Operator*op3,Bundle* B,const Locator* loc); + +template StrEraseOp* +AST::new_TernaryOp(const Type* Ty, Operator*op1,Operator*op2,Operator*op3,const Locator* loc); +template StrEraseOp* +AST::new_TernaryOp(Operator*op1,Operator*op2,Operator*op3,Bundle* B,const Locator* loc); + +template StrReplaceOp* +AST::new_MultiOp( + const Type* Ty, const std::vector& ops, const Locator*loc); +template StrReplaceOp* +AST::new_MultiOp(const std::vector& ops, Bundle* B, const Locator*loc); + +template StrConcatOp* +AST::new_BinaryOp(const Type* Ty, Operator* op1, Operator* op2, const Locator* loc); +template StrConcatOp* +AST::new_BinaryOp(Operator* op1, Operator* op2, Bundle* B, const Locator* loc); + // Control Flow Operators template Block* AST::new_MultiOp( @@ -1373,6 +1394,14 @@ case intTy: result = new IntegerType(32,true); break; case longTy: result = new IntegerType(64,true); break; case octetTy: result = new IntegerType(8,false); break; + case qs16Ty: result = new RationalType(true,8,8); break; + case qs32Ty: result = new RationalType(true,16,16); break; + case qs64Ty: result = new RationalType(true,32,32); break; + case qs128Ty: result = new RationalType(true,64,64); break; + case qu16Ty: result = new RationalType(false,8,8); break; + case qu32Ty: result = new RationalType(false,16,16); break; + case qu64Ty: result = new RationalType(false,32,32); break; + case qu128Ty: result = new RationalType(false,64,64); break; case r8Ty: result = new RangeType(INT8_MIN,INT8_MAX); break; case r16Ty: result = new RangeType(INT16_MIN,INT16_MAX); break; case r32Ty: result = new RangeType(INT32_MIN,INT32_MAX); break; Modified: hlvm/AST/AST.h =================================================================== --- hlvm/AST/AST.h 2006-07-31 14:34:46 UTC (rev 435) +++ hlvm/AST/AST.h 2006-07-31 21:30:12 UTC (rev 436) @@ -56,6 +56,7 @@ class Operator; class AutoVarOp; class GetOp; +class ConvertOp; class URI; /// This class is used to hold or contain an Abstract Syntax Tree. It forms the @@ -504,10 +505,17 @@ /// Create a new GetOp. GetOp* new_GetOp( - const Documentable* D,///< The value or type being referenced + const Value* V, ///< The value being referenced const Locator*loc = 0 ///< The source locator ); + /// Create a new ConvertOp. + ConvertOp* new_ConvertOp( + Operator* oprnd, ///< The operand to be converted + const Type* Ty, ///< The Type to convert \p V to + const Locator* loc ///< THe source locator + ); + /// Provide a template function for creating standard nilary operators template OpClass* new_NilaryOp( Modified: hlvm/AST/Arithmetic.cpp =================================================================== --- hlvm/AST/Arithmetic.cpp 2006-07-31 14:34:46 UTC (rev 435) +++ hlvm/AST/Arithmetic.cpp 2006-07-31 21:30:12 UTC (rev 436) @@ -42,6 +42,7 @@ PreDecrOp::~PreDecrOp() {} PostDecrOp::~PostDecrOp() {} SizeOfOp::~SizeOfOp() {} +LengthOp::~LengthOp() {} ConvertOp::~ConvertOp() {} AddOp::~AddOp() {} SubtractOp::~SubtractOp() {} Modified: hlvm/AST/Arithmetic.h =================================================================== --- hlvm/AST/Arithmetic.h 2006-07-31 14:34:46 UTC (rev 435) +++ hlvm/AST/Arithmetic.h 2006-07-31 21:30:12 UTC (rev 436) @@ -177,7 +177,7 @@ /// This class provides an Abstract Syntax Tree node that represents a /// SizeOf operator. The SizeOfOp is a unary operator that returns the size, in -/// bytes, of its operand. The value returned is a constant. +/// bytes, of its operand. The value returned is a constant s32 /// @brief AST SizeOf Operator Node class SizeOfOp : public UnaryOperator { @@ -199,16 +199,42 @@ }; /// This class provides an Abstract Syntax Tree node that represents a +/// length operator. The LengthOp is a unary operator that returns the logical +/// length of its operand. The value returned is a u64. This operator may be +/// applied to any type of object. For most types, it returns 1. For arrays, +/// it returns the actual (dynamic) size of the array. Same for Text and String +/// type objects. For Structures it returns the number of fields. +/// @brief AST SizeOf Operator Node +class LengthOp : public UnaryOperator +{ + /// @name Constructors + /// @{ + protected: + LengthOp() : UnaryOperator(LengthOpID) {} + virtual ~LengthOp(); + + /// @} + /// @name Accessors + /// @{ + public: + static inline bool classof(const LengthOp*) { return true; } + static inline bool classof(const Node* N) { return N->is(LengthOpID); } + + /// @} + friend class AST; +}; + +/// This class provides an Abstract Syntax Tree node that represents a /// conversion operator. The ConvertOp is a binary operator that converts its /// first operand to the type provided in its second operand (which must be /// a reference operator to the type). /// @brief AST Conversion Operator Node -class ConvertOp : public BinaryOperator +class ConvertOp : public UnaryOperator { /// @name Constructors /// @{ protected: - ConvertOp() : BinaryOperator(ConvertOpID) {} + ConvertOp() : UnaryOperator(ConvertOpID) {} virtual ~ConvertOp(); /// @} Modified: hlvm/AST/Bundle.cpp =================================================================== --- hlvm/AST/Bundle.cpp 2006-07-31 14:34:46 UTC (rev 435) +++ hlvm/AST/Bundle.cpp 2006-07-31 21:30:12 UTC (rev 436) @@ -134,6 +134,14 @@ case HLVM_AST::TKN_int: return intTy; break; case HLVM_AST::TKN_long: return longTy; break; case HLVM_AST::TKN_octet: return octetTy; break; + case HLVM_AST::TKN_qs16: return qs16Ty; break; + case HLVM_AST::TKN_qs32: return qs32Ty; break; + case HLVM_AST::TKN_qs64: return qs64Ty; break; + case HLVM_AST::TKN_qs128: return qs128Ty; break; + case HLVM_AST::TK