[llvm-commits] [hlvm] r38325 - in /hlvm/trunk: hlvm/AST/ hlvm/CodeGen/ hlvm/Pass/ hlvm/Reader/ hlvm/Writer/ test/return0/ test/xml2xml/ tools/hlvm-compiler/ tools/hlvm-config/
Reid Spencer
reid at x10sys.com
Sat Jul 7 17:02:22 PDT 2007
Author: reid
Date: Sat Jul 7 19:02:21 2007
New Revision: 38325
URL: http://llvm.org/viewvc/llvm-project?rev=38325&view=rev
Log:
Get nested blocks, break and continue working correctly. This had to deal with
converting the hierarchical block structure of HLVM into the serial blocks that
LLVM requires.
Added:
hlvm/trunk/test/return0/break.hlx
Modified:
hlvm/trunk/hlvm/AST/AST.cpp
hlvm/trunk/hlvm/AST/AST.h
hlvm/trunk/hlvm/AST/Block.h
hlvm/trunk/hlvm/AST/ControlFlow.cpp
hlvm/trunk/hlvm/AST/ControlFlow.h
hlvm/trunk/hlvm/AST/InputOutput.h
hlvm/trunk/hlvm/AST/Linkables.h
hlvm/trunk/hlvm/AST/Node.h
hlvm/trunk/hlvm/AST/Operator.cpp
hlvm/trunk/hlvm/AST/Operator.h
hlvm/trunk/hlvm/AST/Type.cpp
hlvm/trunk/hlvm/AST/Type.h
hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp
hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h
hlvm/trunk/hlvm/Pass/Validate.cpp
hlvm/trunk/hlvm/Reader/HLVM.rng
hlvm/trunk/hlvm/Reader/XMLReader.cpp
hlvm/trunk/hlvm/Writer/XMLWriter.cpp
hlvm/trunk/test/return0/until.hlx
hlvm/trunk/test/xml2xml/doc.hlx
hlvm/trunk/test/xml2xml/intrinsics.hlx
hlvm/trunk/tools/hlvm-compiler/hlvm-compiler.cpp
hlvm/trunk/tools/hlvm-config/hlvm-config.cpp
Modified: hlvm/trunk/hlvm/AST/AST.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/AST.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/AST.cpp (original)
+++ hlvm/trunk/hlvm/AST/AST.cpp Sat Jul 7 19:02:21 2007
@@ -57,7 +57,7 @@
ASTImpl()
: types(), unresolvedTypes(),
AnyTypeSingleton(0), StringTypeSingleton(0),
- VoidSingleton(0), BooleanSingleton(), CharacterSingleton(0),
+ BooleanSingleton(), CharacterSingleton(0),
OctetSingleton(0), UInt8Singleton(0), UInt16Singleton(0),
UInt32Singleton(0), UInt64Singleton(0), UInt128Singleton(0),
SInt8Singleton(0), SInt16Singleton(0), SInt32Singleton(0),
@@ -81,7 +81,6 @@
SymbolTable<Type> unresolvedTypes;
AnyType* AnyTypeSingleton;
StringType* StringTypeSingleton;
- VoidType* VoidSingleton;
BooleanType* BooleanSingleton;
CharacterType* CharacterSingleton;
OctetType* OctetSingleton;
@@ -424,16 +423,6 @@
return result;
}
-VoidType*
-AST::new_VoidType(const std::string& id, const Locator* loc)
-{
- VoidType* result = new VoidType();
- result->setLocator(loc);
- result->setName(id);
- static_cast<ASTImpl*>(this)->addType(result);
- return result;
-}
-
PointerType*
AST::new_PointerType(
const std::string& id,
@@ -607,7 +596,7 @@
I != E; ++I )
{
const Type* Ty = (*I)->getElementType();
- assert(!Ty->is(VoidTypeID) && "Arguments can't be void type");
+ assert(Ty && "Arguments can't be void type");
Argument* arg = new Argument();
arg->setType(Ty);
arg->setName((*I)->getName());
@@ -631,7 +620,7 @@
I != E; ++I )
{
const Type* Ty = (*I)->getElementType();
- assert(!Ty->is(VoidTypeID) && "Arguments can't be void type");
+ assert(Ty && "Arguments can't be void type");
Argument* arg = new Argument();
arg->setType(Ty);
arg->setName((*I)->getName());
@@ -689,7 +678,6 @@
const Locator* loc ///< The source locator
)
{
- hlvmAssert(Ty != 0 && "Need a type to instantiate a NilaryOp");
OpClass* result = new OpClass();
result->setLocator(loc);
result->setType(Ty);
@@ -701,7 +689,7 @@
const Locator* loc ///< The source locator
)
{
- return new_NilaryOp<OpClass>(getPrimitiveType(VoidTypeID),loc);
+ return new_NilaryOp<OpClass>(0,loc);
}
/// Provide a template function for creating a unary operator
@@ -1013,11 +1001,6 @@
template Block*
AST::new_MultiOp<Block>(const std::vector<Operator*>& ops, const Locator*loc);
-template NullOp*
-AST::new_NilaryOp<NullOp>(const Type* Ty, const Locator*loc);
-template NullOp*
-AST::new_NilaryOp<NullOp>(const Locator*loc);
-
template SelectOp*
AST::new_TernaryOp<SelectOp>(
const Type* Ty, Operator*op1,Operator*op2,Operator*op3,const Locator* loc);
@@ -1049,8 +1032,8 @@
AST::new_TernaryOp<LoopOp>(Operator*op1,Operator*op2,Operator*op3,const Locator* loc)
{
const Type* Ty = op2->getType();
- if (llvm::isa<Block>(Ty))
- Ty = llvm::cast<Block>(op2)->getResultType();
+ if (Ty && llvm::isa<Block>(Ty))
+ Ty = llvm::cast<Block>(op2)->getType();
return new_TernaryOp<LoopOp>(Ty,op1,op2,op3,loc);
}
@@ -1062,8 +1045,8 @@
{
hlvmAssert(ops.size() >= 2 && "Too few operands for SwitchOp");
const Type* Ty = ops[1]->getType();
- if (llvm::isa<Block>(Ty))
- Ty = llvm::cast<Block>(ops[1])->getResultType();
+ if (Ty && llvm::isa<Block>(Ty))
+ Ty = llvm::cast<Block>(ops[1])->getType();
return new_MultiOp<SwitchOp>(Ty, ops, loc);
}
@@ -1098,7 +1081,7 @@
template<> StoreOp*
AST::new_BinaryOp<StoreOp>(Operator*op1,Operator*op2,const Locator*loc)
{
- return new_BinaryOp<StoreOp>(getPrimitiveType(VoidTypeID),op1,op2,loc);
+ return new_BinaryOp<StoreOp>(0,op1,op2,loc);
}
template LoadOp*
@@ -1135,7 +1118,7 @@
template<> CloseOp*
AST::new_UnaryOp<CloseOp>(Operator*op1,const Locator*loc)
{
- return new_UnaryOp<CloseOp>(getPrimitiveType(VoidTypeID),op1,loc);
+ return new_UnaryOp<CloseOp>(0,op1,loc);
}
Type*
@@ -1156,12 +1139,6 @@
ast->StringTypeSingleton->setName("string");
}
return ast->StringTypeSingleton;
- case VoidTypeID:
- if (!ast->VoidSingleton) {
- ast->VoidSingleton = new VoidType();
- ast->VoidSingleton->setName("void");
- }
- return ast->VoidSingleton;
case BooleanTypeID:
if (!ast->BooleanSingleton) {
ast->BooleanSingleton = new BooleanType();
Modified: hlvm/trunk/hlvm/AST/AST.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/AST.h?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/AST.h (original)
+++ hlvm/trunk/hlvm/AST/AST.h Sat Jul 7 19:02:21 2007
@@ -278,14 +278,6 @@
const std::string& id, ///< The name of the type
const Locator*loc = 0 ///< The source locator
);
- /// Create a new VoidType node. A VoidType represents a zero-length entity
- /// that has no address. In other words, its nothing, zilch, nada, empty,
- /// vacuum, etc. As you there's lots of ways to name the concept of
- /// nothing and that's why this method exists.
- VoidType* new_VoidType(
- const std::string& id, ///< The name of the type
- const Locator* loc =0 ///< The source locator
- );
/// Create a new PointerType node. A PointerType just refers to a location
/// of some other type.
PointerType* new_PointerType(
Modified: hlvm/trunk/hlvm/AST/Block.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Block.h?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/Block.h (original)
+++ hlvm/trunk/hlvm/AST/Block.h Sat Jul 7 19:02:21 2007
@@ -58,10 +58,9 @@
/// @name Accessors
/// @{
public:
- virtual const Type* getType() const { return this->back()->getType(); }
+ virtual const Type* getType() const { return (result?result->getType():0); }
const std::string& getLabel() const { return label; }
AutoVarOp* getAutoVar(const std::string& name) const;
- const Type* getResultType() const { return (result?result->getType():0); }
const Operator* getResult() const { return result; }
Block* getParentBlock() const;
bool isTerminated() const {
Modified: hlvm/trunk/hlvm/AST/ControlFlow.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/ControlFlow.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/ControlFlow.cpp (original)
+++ hlvm/trunk/hlvm/AST/ControlFlow.cpp Sat Jul 7 19:02:21 2007
@@ -37,7 +37,6 @@
namespace hlvm {
-NullOp::~NullOp() {}
SelectOp::~SelectOp() {}
SwitchOp::~SwitchOp() {}
WhileOp::~WhileOp() {}
@@ -46,13 +45,7 @@
{
hlvmAssert(getNumOperands() == 2);
Operator* op2 = getOperand(1);
- if (Block* B = llvm::dyn_cast<Block>(op2)) {
- if (const Type* Ty = B->getResultType())
- return Ty;
- return 0;
- } else {
- return op2->getType();
- }
+ return op2->getType();
}
UnlessOp::~UnlessOp() {}
@@ -61,13 +54,7 @@
{
hlvmAssert(getNumOperands() == 2);
Operator* op2 = getOperand(1);
- if (Block* B = llvm::dyn_cast<Block>(op2)) {
- if (const Type* Ty = B->getResultType())
- return Ty;
- return 0;
- } else {
- return op2->getType();
- }
+ return op2->getType();
}
UntilOp::~UntilOp() {}
@@ -76,13 +63,7 @@
{
hlvmAssert(getNumOperands() == 2);
Operator* op1 = getOperand(0);
- if (Block* B = llvm::dyn_cast<Block>(op1)) {
- if (const Type* Ty = B->getResultType())
- return Ty;
- return 0;
- } else {
- return op1->getType();
- }
+ return op1->getType();
}
LoopOp::~LoopOp() {}
@@ -92,13 +73,7 @@
{
hlvmAssert(getNumOperands() == 3);
Operator* op2 = getOperand(1);
- if (Block* B = llvm::dyn_cast<Block>(op2)) {
- if (const Type* Ty = B->getResultType())
- return Ty;
- return 0;
- } else {
- return op2->getType();
- }
+ return op2->getType();
}
ReturnOp::~ReturnOp() { }
Modified: hlvm/trunk/hlvm/AST/ControlFlow.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/ControlFlow.h?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/ControlFlow.h (original)
+++ hlvm/trunk/hlvm/AST/ControlFlow.h Sat Jul 7 19:02:21 2007
@@ -35,28 +35,6 @@
namespace hlvm
{
-/// This class provides an Abstract Syntax Tree node for the "noop" operator
-/// that does nothing.
-/// @brief AST NoOp Operator
-class NullOp : public NilaryOperator
-{
- /// @name Constructors
- /// @{
- protected:
- NullOp() : NilaryOperator(NullOpID) {}
- virtual ~NullOp();
-
- /// @}
- /// @name Accessors
- /// @{
- public:
- static inline bool classof(const NullOp*) { return true; }
- static inline bool classof(const Node* N) { return N->is(NullOpID); }
-
- /// @}
- friend class AST;
-};
-
/// This class provides an Abstract Syntax Tree node that represents a select
/// operator. The select operator is a ternary operator that evaluates its first
/// operand as a boolean. If the result is true, the second operand is evaluated
Modified: hlvm/trunk/hlvm/AST/InputOutput.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/InputOutput.h?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/InputOutput.h (original)
+++ hlvm/trunk/hlvm/AST/InputOutput.h Sat Jul 7 19:02:21 2007
@@ -69,10 +69,9 @@
/// previously returned by the OpenOp operator. The operator causes all
/// buffers written to the stream to be flushed. After the operator completes,
/// the stream will no longer be available for input/output operations. This
-/// operator returns a value of type VoidType.
+/// operator has no result value
/// @see OpenOp
/// @see StreamType
-/// @see VoidType
/// @brief AST Close Stream Operator
class CloseOp : public UnaryOperator
{
Modified: hlvm/trunk/hlvm/AST/Linkables.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Linkables.h?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/Linkables.h (original)
+++ hlvm/trunk/hlvm/AST/Linkables.h Sat Jul 7 19:02:21 2007
@@ -98,7 +98,7 @@
/// be a candidate for linkage with other Bundles. A Variable is a storage
/// location, with an address, of a specific type. Global variables may have
/// a constant value in which case HLVM will ensure that the value of the
-/// global variable is immutable. Variables can be of any type except VoidType.
+/// global variable is immutable. Variables can be of any type.
/// @see Linkable
/// @see Bundle
/// @brief AST Variable Node
Modified: hlvm/trunk/hlvm/AST/Node.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Node.h?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/Node.h (original)
+++ hlvm/trunk/hlvm/AST/Node.h Sat Jul 7 19:02:21 2007
@@ -62,10 +62,9 @@
// SUBCLASSES OF TYPE
// Primitive Types (inherently supported by HLVM)
- VoidTypeID, ///< The Void Type (The Null Type)
-FirstTypeID = VoidTypeID,
-FirstPrimitiveTypeID = VoidTypeID,
BooleanTypeID, ///< The Boolean Type (A simple on/off boolean value)
+FirstTypeID = BooleanTypeID,
+FirstPrimitiveTypeID = BooleanTypeID,
CharacterTypeID, ///< The Character Type (UTF-16 encoded character)
OctetTypeID, ///< The Octet Type (8 bits uninterpreted)
UInt8TypeID, ///< Unsigned 8-bit integer quantity
@@ -167,9 +166,8 @@
LastNilaryOperatorID = ReferenceOpID,
// Control Flow Unary Operators
- NullOpID, ///< The "do nothing" NullOp (no-op) Operator
-FirstUnaryOperatorID = NullOpID,
ResultOpID, ///< Specify the result of a block or function
+FirstUnaryOperatorID = ResultOpID,
ThrowOpID, ///< Throw an exception out of the function
// Integer Arithmetic Unary Operators
@@ -388,6 +386,10 @@
inline bool isTerminator() const {
return (id >= BreakOpID && id <= ReturnOpID) || (id == ThrowOpID); }
+ inline bool isLoop() const {
+ return id == LoopOpID || (id >= WhileOpID && id <= UntilOpID);
+ }
+
inline bool isNilaryOperator() const {
return id >= FirstNilaryOperatorID && id <= LastNilaryOperatorID; }
Modified: hlvm/trunk/hlvm/AST/Operator.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Operator.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/Operator.cpp (original)
+++ hlvm/trunk/hlvm/AST/Operator.cpp Sat Jul 7 19:02:21 2007
@@ -61,14 +61,14 @@
return cast<Block>(p);
}
-LoopOp*
+Operator*
Operator::getContainingLoop()
{
Node* p = getParent();
- while (p && !isa<LoopOp>(p)) p = p->getParent();
+ while (p && !p->isLoop()) p = p->getParent();
if (!p)
return 0;
- return cast<LoopOp>(p);
+ return cast<Operator>(p);
}
NilaryOperator::~NilaryOperator()
Modified: hlvm/trunk/hlvm/AST/Operator.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Operator.h?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/Operator.h (original)
+++ hlvm/trunk/hlvm/AST/Operator.h Sat Jul 7 19:02:21 2007
@@ -75,8 +75,10 @@
/// Return the block containing this operator
Block* getContainingBlock();
- /// Return the loop operator containing this operator
- LoopOp* getContainingLoop();
+ /// Return the loop operator containing this operator. This can return
+ /// any of the loop constructs (Loop, While, Unless, etc.) so its result
+ /// type is Operator*.
+ Operator* getContainingLoop();
/// Determine if this is a classof some other type.
static inline bool classof(const Operator*) { return true; }
Modified: hlvm/trunk/hlvm/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Type.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/Type.cpp (original)
+++ hlvm/trunk/hlvm/AST/Type.cpp Sat Jul 7 19:02:21 2007
@@ -216,16 +216,6 @@
return 0;
}
-VoidType::~VoidType()
-{
-}
-
-const char*
-VoidType::getPrimitiveName() const
-{
- return "void";
-}
-
OpaqueType::~OpaqueType()
{
}
Modified: hlvm/trunk/hlvm/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Type.h?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/AST/Type.h (original)
+++ hlvm/trunk/hlvm/AST/Type.h Sat Jul 7 19:02:21 2007
@@ -54,7 +54,6 @@
/// @{
public:
const std::string& getName() const { return name; }
- bool isSized() const { return id != VoidTypeID; }
virtual const char* getPrimitiveName() const;
bool isPrimitive() const { return getPrimitiveName() != 0; }
@@ -217,30 +216,6 @@
friend class AST;
};
-/// This class provides an Abstract Syntax Tree node that represents the void
-/// type. The void type represents a Value that has no value. It is zero bits
-/// long. Consequently, its utility is limited.
-/// @brief AST Void Type
-class VoidType : public Type
-{
- /// @name Constructors
- /// @{
- protected:
- VoidType() : Type(VoidTypeID) {}
- virtual ~VoidType();
-
- /// @}
- /// @name Accessors
- /// @{
- public:
- virtual const char* getPrimitiveName() const;
- // Methods to support type inquiry via is, cast, dyn_cast
- static inline bool classof(const VoidType*) { return true; }
- static inline bool classof(const Node* T) { return T->is(VoidTypeID); }
- /// @}
- friend class AST;
-};
-
/// This class provides an Abstract Syntax Tree node that represents an integer
/// type in HLVM. An integer is simply a sequence of bits, of specific length,
/// that is interpreted to be an integer value. An integer type declares the
Modified: hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp (original)
+++ hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp Sat Jul 7 19:02:21 2007
@@ -75,30 +75,35 @@
class LLVMGeneratorPass : public hlvm::Pass
{
typedef std::vector<llvm::Module*> ModuleList;
- typedef std::vector<llvm::Value*> OperandList;
+ typedef std::vector<llvm::BranchInst*> BranchList;
typedef std::vector<llvm::BasicBlock*> BlockStack;
- typedef std::map<llvm::BasicBlock*,llvm::Value*> ResultsDictionary;
- typedef std::map<const hlvm::Variable*,llvm::Value*> VariableDictionary;
- typedef std::map<const hlvm::AutoVarOp*,llvm::Value*> AutoVarDictionary;
- typedef std::map<const hlvm::ConstantValue*,llvm::Constant*>
- ConstantDictionary;
- typedef std::map<const hlvm::Function*,llvm::Function*> FunctionDictionary;
- ModuleList modules; ///< The list of modules we construct
- llvm::Module* lmod; ///< The current module we're generation
- llvm::Function* lfunc; ///< The current LLVM function we're generating
- llvm::BasicBlock* lblk; ///< The current LLVM block we're generating
- OperandList lops; ///< The current list of instruction operands
- BlockStack blocks; ///< The stack of blocks we're constructing
- ResultsDictionary results; ///< Dictionary of LLVM blocks to result values
- VariableDictionary gvars; ///< Dictionary of HLVM -> LLVM gvars
- AutoVarDictionary lvars; ///< Dictionary of HLVM -> LLVM auto vars
+ typedef std::map<const hlvm::Operator*,llvm::Value*> OperandMap;
+ typedef std::map<const hlvm::Block*,llvm::BasicBlock*> BlockMap;
+ typedef std::map<const hlvm::Operator*,llvm::BasicBlock*> LoopMap;
+ typedef std::map<const hlvm::Block*,llvm::Instruction*> ResultsMap;
+ typedef std::map<const hlvm::Variable*,llvm::Value*> VariableMap;
+ typedef std::map<const hlvm::AutoVarOp*,llvm::Value*> AutoVarMap;
+ typedef std::map<const hlvm::ConstantValue*,llvm::Constant*> ConstantMap;
+ typedef std::map<const hlvm::Function*,llvm::Function*> FunctionMap;
+ ModuleList modules; ///< The list of modules we construct
+ llvm::Module* lmod; ///< The current module we're generation
+ llvm::Function* lfunc; ///< The current LLVM function we're generating
+ llvm::BasicBlock* lblk; ///< The current LLVM block we're generating
+ OperandMap operands; ///< The current list of instruction operands
+ BlockMap enters; ///< Map of Block to entry BasicBlock
+ BlockMap exits; ///< Map of Block to exit BasicBlock
+ BlockStack blocks; ///< The stack of blocks we're constructing
+ BranchList breaks; ///< The list of break instructions to fix up
+ BranchList continues; ///< The list of continue instructions to fix up
+ VariableMap gvars; ///< Map of HLVM -> LLVM gvars
+ AutoVarMap lvars; ///< Map of HLVM -> LLVM auto vars
llvm::TypeSymbolTable ltypes; ///< The cached LLVM types we've generated
- ConstantDictionary consts; ///< The cached LLVM constants we've generated
- FunctionDictionary funcs; ///< The cached LLVM constants we've generated
- const AST* ast; ///< The current Tree we're traversing
- const Bundle* bundle; ///< The current Bundle we're traversing
+ ConstantMap consts; ///< The cached LLVM constants we've generated
+ FunctionMap funcs; ///< The cached LLVM constants we've generated
+ const AST* ast; ///< The current Tree we're traversing
+ const Bundle* bundle; ///< The current Bundle we're traversing
const hlvm::Function* function; ///< The current Function we're traversing
- const Block* block; ///< The current Block we're traversing
+ const Block* block; ///< The current Block we're traversing
std::vector<llvm::Function*> progs; ///< The list of programs to emit
/// Interfaces to the HLVM Runtime Library
@@ -121,7 +126,8 @@
public:
LLVMGeneratorPass(const AST* tree)
: Pass(0,Pass::PreAndPostOrderTraversal),
- modules(), lmod(0), lfunc(0), lblk(0), lops(), blocks(), results(),
+ modules(), lmod(0), lfunc(0), lblk(0), operands(), blocks(), breaks(),
+ continues(),
gvars(), lvars(), ltypes(), consts(), funcs(),
ast(tree), bundle(0), function(0), block(0),
hlvm_text(0), hlvm_text_create(0), hlvm_text_delete(0),
@@ -147,12 +153,25 @@
inline llvm::Value* toBoolean(llvm::Value* op);
inline llvm::Value* ptr2Value(llvm::Value* op);
inline llvm::Value* coerce(llvm::Value* op);
- inline void saveOperand(llvm::Value* v, const Operator* op);
- inline bool hasResult(llvm::BasicBlock* B) const;
- llvm::AllocaInst* getBlockResult(llvm::BasicBlock* B, const char* name);
- llvm::BasicBlock* getBodyBlock(llvm::Value* V, const std::string& name);
- llvm::BasicBlock* getExpressionBlock(
- llvm::Value* V, llvm::Value*& cond, const std::string& name);
+ inline void pushOperand(llvm::Value* v, const Operator* op);
+ inline llvm::Value* popOperand(const Operator*op);
+ inline llvm::Value* popOperandAsBlock(
+ const Operator* op, const std::string&,
+ llvm::BasicBlock*& entry_block, llvm::BasicBlock*& exit_block);
+ inline llvm::Value* popOperandAsCondition(
+ const Operator* op, const std::string&,
+ llvm::BasicBlock*& entry_block, llvm::BasicBlock*& exit_block);
+ inline llvm::BasicBlock* newBlock(const std::string& name);
+ inline llvm::BasicBlock* pushBlock(const std::string& name);
+ inline llvm::BasicBlock* popBlock(llvm::BasicBlock* curBlock);
+ inline bool hasResult(hlvm::Block* B) const;
+ llvm::AllocaInst* getOperatorResult(Operator* op, const std::string& name);
+ llvm::Value* getBlockResult(Block* blk);
+ inline void branchIfNotTerminated(
+ llvm::BasicBlock* to, llvm::BasicBlock* from);
+
+ inline void startNewFunction();
+ void resolveBranches(BranchList& list, llvm::BasicBlock* exit);
/// Accessors for HLVM Runtime Library things
inline llvm::Type* get_hlvm_size();
@@ -443,7 +462,6 @@
// Okay, we haven't seen this type before so let's construct it
switch (ty->getID()) {
- case VoidTypeID: result = llvm::Type::VoidTy; break;
case BooleanTypeID: result = llvm::Type::BoolTy; break;
case CharacterTypeID: result = llvm::Type::UShortTy; break;
case OctetTypeID: result = llvm::Type::SByteTy; break;
@@ -559,7 +577,7 @@
hlvmAssert(C->isConstantValue());
// First, lets see if its cached already
- ConstantDictionary::iterator I =
+ ConstantMap::iterator I =
consts.find(const_cast<hlvm::ConstantValue*>(C));
if (I != consts.end())
return I->second;
@@ -621,7 +639,7 @@
hlvmAssert(V->is(VariableID));
// First, lets see if its cached already
- VariableDictionary::iterator I =
+ VariableMap::iterator I =
gvars.find(const_cast<hlvm::Variable*>(V));
if (I != gvars.end())
return I->second;
@@ -651,7 +669,7 @@
hlvmAssert(F->is(FunctionID));
// First, lets see if its cached already
- FunctionDictionary::iterator I = funcs.find(const_cast<hlvm::Function*>(F));
+ FunctionMap::iterator I = funcs.find(const_cast<hlvm::Function*>(F));
if (I != funcs.end())
return I->second;
@@ -713,87 +731,168 @@
}
void
-LLVMGeneratorPass::saveOperand(llvm::Value* v, const Operator* op)
+LLVMGeneratorPass::pushOperand(llvm::Value* v, const Operator* op)
{
- if (op)
- if (!llvm::isa<Block>(op->getParent()))
- lops.push_back(v);
+ hlvmAssert(v && "No value to push for operand?");
+ hlvmAssert(op && "No operator for value to be pushed?");
+ operands[op] = v;
}
-bool
-LLVMGeneratorPass::hasResult(llvm::BasicBlock* B) const
+llvm::Value*
+LLVMGeneratorPass::popOperand(const Operator* op)
{
- if (B) {
- ResultsDictionary::const_iterator I = results.find(B);
- return I != results.end();
+ hlvmAssert(op && "No operator to pop?");
+ OperandMap::iterator I = operands.find(op);
+ if (I == operands.end())
+ return 0;
+ llvm::Value* result = I->second;
+ operands.erase(I);
+ return result;
+}
+
+llvm::Value*
+LLVMGeneratorPass::popOperandAsBlock(
+ const Operator* op, const std::string& name,
+ llvm::BasicBlock*& entry_block, llvm::BasicBlock*& exit_block)
+{
+ llvm::Value* result = 0;
+ llvm::Value* operand = popOperand(op);
+
+ if (const hlvm::Block* B = llvm::dyn_cast<hlvm::Block>(op)) {
+ // Get the corresponding entry and exit blocks for B1
+ entry_block = enters[B];
+ hlvmAssert(entry_block && "No entry block?");
+ exit_block = exits[B];
+ hlvmAssert(exit_block && "No exit block?");
+ // Set the name of the entry block to match its purpose here
+ if (entry_block != exit_block) {
+ entry_block->setName(name + "_entry");
+ exit_block->setName(name + "_exit");
+ } else {
+ entry_block->setName(name);
+ }
+ result = operand;
+ } else {
+ hlvmAssert(operand && "No operand for operator?");
+ entry_block = exit_block = new llvm::BasicBlock(name,lfunc);
+ llvm::Value* V = operand;
+ hlvmAssert(V && "No value for operand?");
+ if (llvm::Instruction* ins = llvm::dyn_cast<llvm::Instruction>(V)) {
+ ins->removeFromParent();
+ entry_block->getInstList().push_back(ins);
+ result = ins;
+ } else {
+ // Its just a value or a constant or something, just cast it to itself
+ // so we can get its value
+ result =
+ new llvm::CastInst(V,V->getType(),"",entry_block);
+ }
}
- return false;
+ if (result)
+ result->setName(name + "_val");
+ return result;
+}
+
+llvm::Value*
+LLVMGeneratorPass::popOperandAsCondition(
+ const Operator* op, const std::string& name,
+ llvm::BasicBlock*& entry_block, llvm::BasicBlock*& exit_block)
+{
+ llvm::Value* result =
+ popOperandAsBlock(op,name+"_cond",entry_block,exit_block);
+ hlvmAssert(result);
+ hlvmAssert(result->getType() == llvm::Type::BoolTy);
+
+ return result;
+}
+
+llvm::BasicBlock*
+LLVMGeneratorPass::pushBlock(const std::string& name)
+{
+ lblk = new llvm::BasicBlock(name,lfunc);
+ blocks.push_back(lblk);
+ return lblk;
+}
+
+llvm::BasicBlock*
+LLVMGeneratorPass::popBlock(llvm::BasicBlock* curBlock)
+{
+ llvm::BasicBlock* result = blocks.back();
+ blocks.pop_back();
+ if (blocks.empty())
+ lblk = 0;
+ else
+ lblk = blocks.back();
+ return result;
+}
+
+llvm::BasicBlock*
+LLVMGeneratorPass::newBlock(const std::string& name)
+{
+ blocks.pop_back();
+ lblk = new llvm::BasicBlock(name,lfunc);
+ blocks.push_back(lblk);
+ return lblk;
}
llvm::AllocaInst*
-LLVMGeneratorPass::getBlockResult(llvm::BasicBlock* B, const char* name)
+LLVMGeneratorPass::getOperatorResult(Operator* op, const std::string& name)
{
- if (hasResult(B)) {
- const llvm::Type* Ty = results[B]->getType();
- llvm::AllocaInst* result = new llvm::AllocaInst(
+ llvm::AllocaInst* result = 0;
+ if (!llvm::isa<Block>(op->getParent())) {
+ const llvm::Type* Ty = getType(op->getType());
+ result = new llvm::AllocaInst(
/*Ty=*/ Ty,
/*ArraySize=*/ llvm::ConstantUInt::get(llvm::Type::UIntTy,1),
/*Name=*/ name,
/*InsertAtEnd=*/ lblk
);
- // Initialize the autovar to null
new llvm::StoreInst(llvm::Constant::getNullValue(Ty),result,lblk);
- // Store the value on each iteration
- new llvm::StoreInst(results[B],result,B);
+ }
+ return result;
+}
+
+llvm::Value*
+LLVMGeneratorPass::getBlockResult(Block* B)
+{
+ if (B->getResult() && !lblk->getTerminator()) {
+ llvm::Instruction* result = llvm::cast<llvm::Instruction>(operands[B]);
+ result = new llvm::LoadInst(result,lblk->getName()+"_result",lblk);
+ pushOperand(result,B);
return result;
}
return 0;
}
-llvm::BasicBlock*
-LLVMGeneratorPass::getBodyBlock(llvm::Value* V, const std::string& name)
+void
+LLVMGeneratorPass::branchIfNotTerminated(
+ llvm::BasicBlock* to, llvm::BasicBlock* from )
{
- llvm::BasicBlock* B = llvm::dyn_cast<llvm::BasicBlock>(V);
- if (B)
- return B;
- B = new llvm::BasicBlock(name,lfunc);
- if (llvm::Instruction* ins = llvm::dyn_cast<llvm::Instruction>(V)) {
- ins->removeFromParent();
- B->getInstList().push_back(ins);
- results[B] = ins;
- } else {
- // Its just a value or a constant or something, just cast it to itself
- // so we can get its value
- results[B] = new llvm::CastInst(V,V->getType(),name+"_result",B);
- }
- return B;
+ if (!from->getTerminator())
+ new llvm::BranchInst(to,from);
}
-llvm::BasicBlock*
-LLVMGeneratorPass::getExpressionBlock(
- llvm::Value* V, llvm::Value*& cond, const std::string& name)
+void
+LLVMGeneratorPass::startNewFunction()
{
- // Extract the condition value and make sure the condition expression is
- // a block.
- cond = 0;
- llvm::BasicBlock* B = llvm::dyn_cast<llvm::BasicBlock>(V);
- if (B) {
- hlvmAssert(hasResult(B) && "No result in expression block?");
- cond = results[B];
- return B;
- }
- B = new llvm::BasicBlock(name,lfunc);
- if (llvm::Instruction* ins = llvm::dyn_cast<llvm::Instruction>(V)) {
- ins->removeFromParent();
- B->getInstList().push_back(ins);
- cond = results[B] = V;
- } else {
- // Its just a value or a constant or something, just cast it to itself
- // so we can get its value
- cond = results[B] = new llvm::CastInst(V,V->getType(),name+"_result",B);
+ // Clear the function related variables
+ lblk = 0;
+ operands.clear();
+ enters.clear();
+ exits.clear();
+ blocks.clear();
+ breaks.clear();
+ continues.clear();
+ lvars.clear();
+}
+
+void
+LLVMGeneratorPass::resolveBranches(BranchList& list, llvm::BasicBlock* exit)
+{
+ for (BranchList::iterator I = list.begin(), E = list.end(); I != E; ++I) {
+ (*I)->setOperand(0,exit);
}
- hlvmAssert(cond->getType() == llvm::Type::BoolTy);
- return B;
+ list.clear();
}
template<> void
@@ -803,16 +902,16 @@
// emit a stack variable
const llvm::Type* elemType = getType(av->getType());
llvm::Value* alloca = new llvm::AllocaInst(
- /*Ty=*/ elemType,
- /*ArraySize=*/ llvm::ConstantUInt::get(llvm::Type::UIntTy,1),
- /*Name=*/ av->getName(),
- /*InsertAtEnd=*/ lblk
+ /*Ty=*/ elemType,
+ /*ArraySize=*/ llvm::ConstantUInt::get(llvm::Type::UIntTy,1),
+ /*Name=*/ av->getName(),
+ /*InsertAtEnd=*/ lblk
);
llvm::Constant* C = 0;
if (av->hasInitializer())
- C = getConstant(av->getInitializer());
+ C = getConstant(av->getInitializer());
else
- C = llvm::Constant::getNullValue(elemType);
+ C = llvm::Constant::getNullValue(elemType);
if (C) {
const llvm::Type* CType = C->getType();
@@ -840,9 +939,9 @@
hlvmAssert(CType->isLosslesslyConvertibleTo(elemType));
C = llvm::ConstantExpr::getCast(C,elemType);
}
- llvm::Value* store = new llvm::StoreInst(C,alloca,"",lblk);
+ llvm::Value* store = new llvm::StoreInst(C,alloca,lblk);
}
- saveOperand(alloca,av);
+ pushOperand(alloca,av);
lvars[av] = alloca;
}
@@ -850,36 +949,33 @@
template<> void
LLVMGeneratorPass::gen(NegateOp* op)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for NegateOp");
- llvm::Value* operand = lops.back(); lops.pop_back();
+ llvm::Value* operand = popOperand(op->getOperand(0));
hlvmAssert((operand->getType()->isInteger() ||
- operand->getType()->isFloatingPoint()) &&
- "Can't negate non-numeric");
+ operand->getType()->isFloatingPoint()) &&
+ "Can't negate non-numeric");
llvm::BinaryOperator* neg =
- llvm::BinaryOperator::createNeg(operand,"neg",lblk);
- saveOperand(neg,op);
+ llvm::BinaryOperator::createNeg(operand,"neg",lblk);
+ pushOperand(neg,op);
}
template<> void
LLVMGeneratorPass::gen(ComplementOp* op)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for ComplementOp");
- llvm::Value* operand = lops.back(); lops.pop_back();
+ llvm::Value* operand = popOperand(op->getOperand(0));
operand = ptr2Value(operand);
const llvm::Type* lType = operand->getType();
hlvmAssert(lType->isInteger() && "Can't complement non-integral type");
llvm::ConstantIntegral* allOnes =
- llvm::ConstantIntegral::getAllOnesValue(lType);
+ llvm::ConstantIntegral::getAllOnesValue(lType);
llvm::BinaryOperator* cmpl = llvm::BinaryOperator::create(
- llvm::Instruction::Xor,operand,allOnes,"cmpl",lblk);
- saveOperand(cmpl,op);
+ llvm::Instruction::Xor,operand,allOnes,"cmpl",lblk);
+ pushOperand(cmpl,op);
}
template<> void
LLVMGeneratorPass::gen(PreIncrOp* op)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for PreIncrOp");
- llvm::Value* operand = lops.back(); lops.pop_back();
+ llvm::Value* operand = popOperand(op->getOperand(0));
const llvm::Type* lType = operand->getType();
hlvmAssert(llvm::isa<llvm::PointerType>(lType));
const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
@@ -889,14 +985,14 @@
llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
llvm::BinaryOperator* add = llvm::BinaryOperator::create(
llvm::Instruction::Add, load, one, "preincr", lblk);
- new llvm::StoreInst(add,operand,"preincr",lblk);
- saveOperand(add,op);
+ new llvm::StoreInst(add,operand,lblk);
+ pushOperand(add,op);
} else if (lType->isInteger()) {
llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
llvm::BinaryOperator* add = llvm::BinaryOperator::create(
llvm::Instruction::Add, load, one, "preincr", lblk);
- new llvm::StoreInst(add,operand,"preincr",lblk);
- saveOperand(add,op);
+ new llvm::StoreInst(add,operand,lblk);
+ pushOperand(add,op);
} else {
hlvmAssert(!"PreIncrOp on non-numeric");
}
@@ -905,8 +1001,7 @@
template<> void
LLVMGeneratorPass::gen(PreDecrOp* op)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for PreDecrOp");
- llvm::Value* operand = lops.back(); lops.pop_back();
+ llvm::Value* operand = popOperand(op->getOperand(0));
const llvm::Type* lType = operand->getType();
hlvmAssert(llvm::isa<llvm::PointerType>(lType));
const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
@@ -916,14 +1011,14 @@
llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
llvm::Instruction::Sub, load, one, "predecr", lblk);
- new llvm::StoreInst(sub,operand,"predecr",lblk);
- saveOperand(sub,op);
+ new llvm::StoreInst(sub,operand,lblk);
+ pushOperand(sub,op);
} else if (lType->isInteger()) {
llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
llvm::Instruction::Sub, load, one, "predecr", lblk);
- new llvm::StoreInst(sub,operand,"predecr",lblk);
- saveOperand(sub,op);
+ new llvm::StoreInst(sub,operand,lblk);
+ pushOperand(sub,op);
} else {
hlvmAssert(!"PreIncrOp on non-numeric");
}
@@ -932,8 +1027,7 @@
template<> void
LLVMGeneratorPass::gen(PostIncrOp* op)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for PostIncrOp");
- llvm::Value* operand = lops.back(); lops.pop_back();
+ llvm::Value* operand = popOperand(op->getOperand(0));
const llvm::Type* lType = operand->getType();
hlvmAssert(llvm::isa<llvm::PointerType>(lType));
const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
@@ -943,14 +1037,14 @@
llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
llvm::BinaryOperator* add = llvm::BinaryOperator::create(
llvm::Instruction::Add, load, one, "postincr", lblk);
- new llvm::StoreInst(add,operand,"postincr",lblk);
- saveOperand(load,op);
+ new llvm::StoreInst(add,operand,lblk);
+ pushOperand(load,op);
} else if (lType->isInteger()) {
llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
llvm::BinaryOperator* add = llvm::BinaryOperator::create(
llvm::Instruction::Add, load, one, "postincr", lblk);
- new llvm::StoreInst(add,operand,"postincr",lblk);
- saveOperand(load,op);
+ new llvm::StoreInst(add,operand,lblk);
+ pushOperand(load,op);
} else {
hlvmAssert(!"PostDecrOp on non-numeric");
}
@@ -959,8 +1053,7 @@
template<> void
LLVMGeneratorPass::gen(PostDecrOp* op)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for PostDecrOp");
- llvm::Value* operand = lops.back(); lops.pop_back();
+ llvm::Value* operand = popOperand(op->getOperand(0));
const llvm::Type* lType = operand->getType();
hlvmAssert(llvm::isa<llvm::PointerType>(lType));
const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
@@ -970,14 +1063,14 @@
llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
llvm::Instruction::Sub, load, one, "postdecr", lblk);
- new llvm::StoreInst(sub,operand,"postdecr",lblk);
- saveOperand(load,op);
+ new llvm::StoreInst(sub,operand,lblk);
+ pushOperand(load,op);
} else if (lType->isInteger()) {
llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
llvm::Instruction::Sub, load, one, "postdecr", lblk);
- new llvm::StoreInst(sub,operand,"postdecr",lblk);
- saveOperand(load,op);
+ new llvm::StoreInst(sub,operand,lblk);
+ pushOperand(load,op);
} else {
hlvmAssert(!"PostDecrOp on non-numeric");
}
@@ -986,542 +1079,548 @@
template<> void
LLVMGeneratorPass::gen(AddOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for AddOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::BinaryOperator* add = llvm::BinaryOperator::create(
- llvm::Instruction::Add, op1, op2, "add", lblk);
- saveOperand(add,op);
+ llvm::Instruction::Add, op1, op2, "add", lblk);
+ pushOperand(add,op);
}
template<> void
LLVMGeneratorPass::gen(SubtractOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for SubtractOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
- llvm::Instruction::Sub, op1, op2, "add", lblk);
- saveOperand(sub,op);
+ llvm::Instruction::Sub, op1, op2, "add", lblk);
+ pushOperand(sub,op);
}
template<> void
LLVMGeneratorPass::gen(MultiplyOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for MultiplyOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::BinaryOperator* mul = llvm::BinaryOperator::create(
- llvm::Instruction::Mul, op1, op2, "mul", lblk);
- saveOperand(mul,op);
+ llvm::Instruction::Mul, op1, op2, "mul", lblk);
+ pushOperand(mul,op);
}
template<> void
LLVMGeneratorPass::gen(DivideOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for DivideOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::BinaryOperator* div = llvm::BinaryOperator::create(
- llvm::Instruction::Div, op1, op2, "div", lblk);
- saveOperand(div,op);
+ llvm::Instruction::Div, op1, op2, "div", lblk);
+ pushOperand(div,op);
}
template<> void
LLVMGeneratorPass::gen(ModuloOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for ModuloOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::BinaryOperator* rem = llvm::BinaryOperator::create(
- llvm::Instruction::Rem, op1, op2, "mod", lblk);
- saveOperand(rem,op);
+ llvm::Instruction::Rem, op1, op2, "mod", lblk);
+ pushOperand(rem,op);
}
template<> void
LLVMGeneratorPass::gen(BAndOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for BAndOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::BinaryOperator* band = llvm::BinaryOperator::create(
- llvm::Instruction::And, op1, op2, "band", lblk);
- saveOperand(band,op);
+ llvm::Instruction::And, op1, op2, "band", lblk);
+ pushOperand(band,op);
}
template<> void
LLVMGeneratorPass::gen(BOrOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for BOrOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::BinaryOperator* bor = llvm::BinaryOperator::create(
- llvm::Instruction::Or, op1, op2, "bor", lblk);
- saveOperand(bor,op);
+ llvm::Instruction::Or, op1, op2, "bor", lblk);
+ pushOperand(bor,op);
}
template<> void
LLVMGeneratorPass::gen(BXorOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for BXorOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::BinaryOperator* Xor = llvm::BinaryOperator::create(
- llvm::Instruction::Xor, op1, op2, "bxor", lblk);
- saveOperand(Xor,op);
+ llvm::Instruction::Xor, op1, op2, "bxor", lblk);
+ pushOperand(Xor,op);
}
template<> void
LLVMGeneratorPass::gen(BNorOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for BNorOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::BinaryOperator* bor = llvm::BinaryOperator::create(
- llvm::Instruction::Or, op1, op2, "bnor", lblk);
+ llvm::Instruction::Or, op1, op2, "bnor", lblk);
llvm::BinaryOperator* nor = llvm::BinaryOperator::createNot(bor,"bnor",lblk);
- saveOperand(nor,op);
-}
-
-template<> void
-LLVMGeneratorPass::gen(NullOp* op)
-{
- // Not surprisingly, there's nothing to do here.
+ pushOperand(nor,op);
}
template<> void
LLVMGeneratorPass::gen(NotOp* op)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for BNorOp");
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
llvm::Value* b1 = toBoolean(op1);
llvm::BinaryOperator* Not = llvm::BinaryOperator::createNot(b1,"not",lblk);
- saveOperand(Not,op);
+ pushOperand(Not,op);
}
template<> void
LLVMGeneratorPass::gen(AndOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for BNorOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::Value* b1 = toBoolean(op1);
llvm::Value* b2 = toBoolean(op2);
llvm::BinaryOperator* And = llvm::BinaryOperator::create(
- llvm::Instruction::And, b1, b2, "and", lblk);
- saveOperand(And,op);
+ llvm::Instruction::And, b1, b2, "and", lblk);
+ pushOperand(And,op);
}
template<> void
LLVMGeneratorPass::gen(OrOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for BNorOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::Value* b1 = toBoolean(op1);
llvm::Value* b2 = toBoolean(op2);
llvm::BinaryOperator* Or = llvm::BinaryOperator::create(
- llvm::Instruction::Or, b1, b2, "or", lblk);
- saveOperand(Or,op);
+ llvm::Instruction::Or, b1, b2, "or", lblk);
+ pushOperand(Or,op);
}
template<> void
LLVMGeneratorPass::gen(NorOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for NorOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::Value* b1 = toBoolean(op1);
llvm::Value* b2 = toBoolean(op2);
llvm::BinaryOperator* Or = llvm::BinaryOperator::create(
- llvm::Instruction::Or, b1, b2, "nor", lblk);
+ llvm::Instruction::Or, b1, b2, "nor", lblk);
llvm::BinaryOperator* Nor = llvm::BinaryOperator::createNot(Or,"nor",lblk);
- saveOperand(Nor,op);
+ pushOperand(Nor,op);
}
template<> void
LLVMGeneratorPass::gen(XorOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for XorOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::Value* b1 = toBoolean(op1);
llvm::Value* b2 = toBoolean(op2);
llvm::BinaryOperator* Xor = llvm::BinaryOperator::create(
- llvm::Instruction::Xor, b1, b2, "xor", lblk);
- saveOperand(Xor,op);
+ llvm::Instruction::Xor, b1, b2, "xor", lblk);
+ pushOperand(Xor,op);
}
template<> void
LLVMGeneratorPass::gen(EqualityOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for EqualityOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::SetCondInst* SCI =
- new llvm::SetCondInst(llvm::Instruction::SetEQ, op1,op2,"eq",lblk);
- saveOperand(SCI,op);
+ new llvm::SetCondInst(llvm::Instruction::SetEQ, op1,op2,"eq",lblk);
+ pushOperand(SCI,op);
}
template<> void
LLVMGeneratorPass::gen(InequalityOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for InequalityOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
op1 = ptr2Value(op1);
op2 = ptr2Value(op2);
llvm::SetCondInst* SCI =
- new llvm::SetCondInst(llvm::Instruction::SetNE, op1,op2,"ne",lblk);
- saveOperand(SCI,op);
+ new llvm::SetCondInst(llvm::Instruction::SetNE, op1,op2,"ne",lblk);
+ pushOperand(SCI,op);
}
template<> void
LLVMGeneratorPass::gen(LessThanOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for LessThanOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
llvm::SetCondInst* SCI =
- new llvm::SetCondInst(llvm::Instruction::SetLT, op1,op2,"lt",lblk);
- saveOperand(SCI,op);
+ new llvm::SetCondInst(llvm::Instruction::SetLT, op1,op2,"lt",lblk);
+ pushOperand(SCI,op);
}
template<> void
LLVMGeneratorPass::gen(GreaterThanOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for GreaterThanOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
llvm::SetCondInst* SCI =
- new llvm::SetCondInst(llvm::Instruction::SetGT, op1,op2,"gt",lblk);
- saveOperand(SCI,op);
+ new llvm::SetCondInst(llvm::Instruction::SetGT, op1,op2,"gt",lblk);
+ pushOperand(SCI,op);
}
template<> void
LLVMGeneratorPass::gen(GreaterEqualOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for GreaterEqualOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
llvm::SetCondInst* SCI =
- new llvm::SetCondInst(llvm::Instruction::SetGE, op1,op2,"ge",lblk);
- saveOperand(SCI,op);
+ new llvm::SetCondInst(llvm::Instruction::SetGE, op1,op2,"ge",lblk);
+ pushOperand(SCI,op);
}
template<> void
LLVMGeneratorPass::gen(LessEqualOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for LessEqualOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
llvm::SetCondInst* SCI =
- new llvm::SetCondInst(llvm::Instruction::SetLE, op1,op2,"le",lblk);
- saveOperand(SCI,op);
+ new llvm::SetCondInst(llvm::Instruction::SetLE, op1,op2,"le",lblk);
+ pushOperand(SCI,op);
}
template<> void
LLVMGeneratorPass::gen(SelectOp* op)
{
- hlvmAssert(lops.size() >= 3 && "Too few operands for SelectOp");
- llvm::Value* op3 = lops.back(); lops.pop_back();
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
- hlvmAssert(llvm::isa<llvm::BasicBlock>(op2) ==
- llvm::isa<llvm::BasicBlock>(op3));
-
- /// If the first operand is a basic block then it is an expression block, by
- /// definition. We can therefore discard the LLVM basic block and incorporate
- /// its contents into the current block. We also replace "op1" with the
- /// BasicBlock's result which was cached.
- if (llvm::BasicBlock* BB1 = llvm::dyn_cast<llvm::BasicBlock>(op1)) {
- hlvmAssert(!BB1->getTerminator() && "expression block with terminator?");
- // Move the contents of the basic block into the current one
- llvm::BasicBlock::InstListType& IL = lblk->getInstList();
- for (llvm::BasicBlock::iterator I = BB1->begin(), E = BB1->end();
- I != E; ) {
- // be careful with iterator invalidation
- llvm::Instruction* one2move = &(*I);
- ++I;
- // move the instruction from one block to the other
- one2move->removeFromParent();
- IL.push_back(one2move);
- }
- op1 = results[BB1];
- results.erase(BB1);
- BB1->eraseFromParent();
- }
-
- if (llvm::isa<llvm::BasicBlock>(op2)) {
- // Both op2 and op3 are blocks, so we must emit a branch instruction for
- // the select. That will terminate the current block so we need to set up
- // another block to receive the result of the selection. We also need to
- // make sure that the two operand blocks are properly terminated.
- llvm::BasicBlock* BB2 = llvm::cast<llvm::BasicBlock>(op2);
- llvm::BasicBlock* BB3 = llvm::cast<llvm::BasicBlock>(op3);
-
- // Neither block should have a terminator, they are expression blocks
- hlvmAssert(!BB2->getTerminator() && !BB3->getTerminator());
- llvm::AllocaInst* select_result = getBlockResult(BB2,"select_result");
-
- // Set up the branch to terminate the current block
- new llvm::BranchInst(BB2,BB3,op1,lblk);
-
- // Create the exit block
- llvm::BasicBlock* exit = new llvm::BasicBlock("select_exit",lfunc);
-
- // Make the exit block the current block
- lblk = exit;
-
- // Branch to the exit block
- BB2->setName("select_true");
- new llvm::BranchInst(exit,BB2);
-
- // Store the result of the "false" case into the autovar, if we should
- if (select_result)
- new llvm::StoreInst(results[BB3],select_result,BB3);
-
- // Branch to the exit block
- BB3->setName("select_false");
- new llvm::BranchInst(exit,BB3);
-
- // Load the result and put it on the operand stack
- if (select_result)
- saveOperand(new llvm::LoadInst(select_result,"select",exit),op);
- } else {
- // A this point, we can only be left with a first class type since all HLVM
- // operators translate to a first class type. Since the select operator
- // requires first class types, its okay to just use it here.
+ // If none of the operands are blocks then we can use LLVM's select
+ // instruction to just switch out the result
+ if (!llvm::isa<Block>(op->getOperand(0)) &&
+ !llvm::isa<Block>(op->getOperand(1)) &&
+ !llvm::isa<Block>(op->getOperand(2)))
+ {
+ // Since HLVM only places on the operand stack things that are of LLVM
+ // first class type, we are safe to use select operator here.
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
+ llvm::Value* op3 = popOperand(op->getOperand(2));
+ hlvmAssert(op1->getType() == llvm::Type::BoolTy);
hlvmAssert(op2->getType()->isFirstClassType());
hlvmAssert(op3->getType()->isFirstClassType());
- saveOperand(new llvm::SelectInst(op1,op2,op3,"select",lblk),op);
+ pushOperand(new llvm::SelectInst(op1,op2,op3,"select",lblk),op);
+ return;
}
-}
-template<> void
-LLVMGeneratorPass::gen(SwitchOp* op)
-{
- hlvmAssert(lops.size() >= 2 && "Too few operands for SwitchOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ // Using the LLVM SelectInst won't work. We must get each operand as a block
+ // and use a branch instruction instead.
-}
+ // Get the result of the select operator
+ llvm::AllocaInst* select_result = getOperatorResult(op,"select_result");
-template<> void
-LLVMGeneratorPass::gen(WhileOp* op)
-{
- hlvmAssert(lops.size() >= 2 && "Too few operands for WhileOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
+ // Get the condition block
+ llvm::BasicBlock* cond_entry, *cond_exit;
+ llvm::Value* op1 =
+ popOperandAsCondition(op->getOperand(0),"select",cond_entry,cond_exit);
- // Get the body of the while loop
- llvm::BasicBlock* B2 = getBodyBlock(op2,"while_body");
+ // Branch the current block into the condition block
+ new llvm::BranchInst(cond_entry,lblk);
- // If there's a result in the while body, get it now
- llvm::AllocaInst* while_result = getBlockResult(B2,"while_result");
+ // Get the true case
+ llvm::BasicBlock *true_entry, *true_exit;
+ llvm::Value* op2 =
+ popOperandAsBlock(op->getOperand(1),"select_true",true_entry,true_exit);
- // Extract the condition value and make sure its in a block
- llvm::Value* cond = 0;
- llvm::BasicBlock* B1 = getExpressionBlock(op1,cond,"while_cond");
+ if (select_result && op2)
+ new llvm::StoreInst(op2,select_result,true_exit);
- // Terminate the current block with a branch to the condition block
- new llvm::BranchInst(B1,lblk);
+ // Get the false case
+ llvm::BasicBlock *false_entry, *false_exit;
+ llvm::Value* op3 =
+ popOperandAsBlock(op->getOperand(2),"select_false",false_entry,false_exit);
- // Terminate the body with a branch back to the condition block
- new llvm::BranchInst(B1,B2);
+ if (select_result && op3)
+ new llvm::StoreInst(op3,select_result,false_exit);
- // Create a new block for the exit from the while loop
- lblk = new llvm::BasicBlock("while_exit",lfunc);
+ // Create the exit block
+ llvm::BasicBlock* select_exit = newBlock("select_exit");
- // Create a conditional branch to either exit or repeat the loop.
- new llvm::BranchInst(B2,lblk,cond,B1);
+ // Branch the the true and false cases to the exit
+ branchIfNotTerminated(select_exit,true_exit);
+ branchIfNotTerminated(select_exit,false_exit);
- // Deal with the result of the while loop, if it has one
- if (while_result) {
- lops.push_back(new llvm::LoadInst(while_result,"while_result",lblk));
- }
+ // Finally, install the conditional branch
+ new llvm::BranchInst(true_entry,false_entry,op1,cond_exit);
+
+ if (select_result)
+ pushOperand(new llvm::LoadInst(select_result,"select_result",select_exit),op);
}
template<> void
-LLVMGeneratorPass::gen(UnlessOp* op)
+LLVMGeneratorPass::gen(SwitchOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for UnlessOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
-
- // Get the body block from the 2nd operand
- llvm::BasicBlock* B2 = getBodyBlock(op2,"unless_body");
-
- // If there's a result in the unless body, get it now
- llvm::AllocaInst* unless_result = getBlockResult(B2,"unless_result");
-
- // Get the condition expression
- llvm::Value* cond = 0;
- llvm::BasicBlock* B1 = getExpressionBlock(op1,cond,"unless_cond");
-
- // Terminate the current block with a branch to the condition block
- new llvm::BranchInst(B1,lblk);
+ llvm::Value* op1 = popOperand(op->getOperand(0));
+ llvm::Value* op2 = popOperand(op->getOperand(1));
+}
- // Terminate the unless body with a branch back to the condition block
- new llvm::BranchInst(B1,B2);
+template<> void
+LLVMGeneratorPass::gen(WhileOp* op)
+{
+ // Get the result of this while block, if there should be one
+ llvm::AllocaInst* while_result = getOperatorResult(op,"while_result");
- // Create a new block for the exit from the while loop
- lblk = new llvm::BasicBlock("unless_exit",lfunc);
+ // Get the condition block
+ llvm::BasicBlock* cond_entry, *cond_exit;
+ llvm::Value* op1 =
+ popOperandAsCondition(op->getOperand(0),"while",cond_entry,cond_exit);
+
+ // Branch the current block into the condition block
+ new llvm::BranchInst(cond_entry,lblk);
+
+ // Get the while loop's body
+ llvm::BasicBlock *body_entry, *body_exit;
+ llvm::Value* op2 =
+ popOperandAsBlock(op->getOperand(1),"while_body",body_entry,body_exit);
+
+ // Save the result of the while body, if there should be one
+ if (while_result && op2)
+ new llvm::StoreInst(op2,while_result,body_exit);
+
+ // Create the exit block
+ llvm::BasicBlock* while_exit = newBlock("while_exit");
+
+ // Branch the the body block back to the condition branch
+ branchIfNotTerminated(cond_entry,body_exit);
+
+ // Finally, install the conditional branch into the branch block
+ new llvm::BranchInst(body_entry,while_exit,op1,cond_exit);
+
+ // If there's a result, push it now
+ if (while_result)
+ pushOperand(new llvm::LoadInst(while_result,"while_result",while_exit),op);
+
+ // Fix up any break or continue operators
+ resolveBranches(breaks,while_exit);
+ resolveBranches(continues,cond_entry);
+}
- // Create a conditional branch to either exit or repeat the loop.
- new llvm::BranchInst(lblk,B2,cond,B1);
+template<> void
+LLVMGeneratorPass::gen(UnlessOp* op)
+{
+ // Get the result of this unless block, if there should be one
+ llvm::AllocaInst* unless_result = getOperatorResult(op,"unless_result");
- // Deal with the result of the unless loop, if it has one
- if (unless_result) {
- lops.push_back(new llvm::LoadInst(unless_result,"unless_result",lblk));
- }
+ // Get the condition block
+ llvm::BasicBlock* cond_entry, *cond_exit;
+ llvm::Value* op1 =
+ popOperandAsCondition(op->getOperand(0),"unless",cond_entry,cond_exit);
+
+ // Branch the current block into the condition block
+ new llvm::BranchInst(cond_entry,lblk);
+
+ // Get the unless block's body
+ llvm::BasicBlock *body_entry, *body_exit;
+ llvm::Value* op2 =
+ popOperandAsBlock(op->getOperand(1),"unless_body",body_entry,body_exit);
+
+ // Save the result of the unless body, if there should be one
+ if (unless_result && op2)
+ new llvm::StoreInst(op2,unless_result,body_exit);
+
+ // Create the exit block
+ llvm::BasicBlock* unless_exit = newBlock("unless_exit");
+
+ // Branch the the body block back to the condition branch
+ branchIfNotTerminated(cond_entry,body_exit);
+
+ // Finally, install the conditional branch into the branch block
+ new llvm::BranchInst(unless_exit,body_entry,op1,cond_exit);
+
+ // If there's a result, push it now
+ if (unless_result)
+ pushOperand(
+ new llvm::LoadInst(unless_result,"unless_result",unless_exit),op);
+
+ // Fix up any break or continue operators
+ resolveBranches(breaks,unless_exit);
+ resolveBranches(continues,cond_entry);
}
template<> void
LLVMGeneratorPass::gen(UntilOp* op)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for UntilOp");
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
-
- // Get the body of the block
- llvm::BasicBlock* B1 = getBodyBlock(op1,"until_body");
-
- // If there's a result in the until body, get it now
- llvm::AllocaInst* until_result = getBlockResult(B1,"until_result");
-
- // Get the condition expression
- llvm::Value* cond = 0;
- llvm::BasicBlock* B2 = getExpressionBlock(op2,cond,"until_cond");
-
- // Branch the current block into the body of the loop
- new llvm::BranchInst(B1,lblk);
-
- // Terminate the body with a branch forward to the condition block
- new llvm::BranchInst(B2,B1);
-
- // Create a new block for the exit from the loop
- lblk = new llvm::BasicBlock("until_exit",lfunc);
-
- // Create a conditional branch to either exit or repeat the loop.
- new llvm::BranchInst(B1,lblk,cond,B2);
+ // Get the result of this until block, if there should be one
+ llvm::AllocaInst* until_result = getOperatorResult(op,"until_result");
- // Deal with the result of the until loop, if it has one
- if (until_result) {
- lops.push_back(new llvm::LoadInst(until_result,"until_result",lblk));
- }
+ // Get the condition block
+ llvm::BasicBlock* cond_entry, *cond_exit;
+ llvm::Value* op2 =
+ popOperandAsCondition(op->getOperand(1),"until",cond_entry,cond_exit);
+
+ // Get the until block's body
+ llvm::BasicBlock *body_entry, *body_exit;
+ llvm::Value* op1 =
+ popOperandAsBlock(op->getOperand(0),"until_body",body_entry,body_exit);
+
+ // Save the result of the until body, if there should be one
+ if (until_result && op1)
+ new llvm::StoreInst(op1,until_result,body_exit);
+
+ // Branch the current block into the body block
+ new llvm::BranchInst(body_entry,lblk);
+
+ // Branch the body block to the condition block
+ branchIfNotTerminated(cond_entry,body_exit);
+
+ // Create the exit block
+ llvm::BasicBlock* until_exit = newBlock("until_exit");
+
+ // Finally, install the conditional branch into condition block
+ new llvm::BranchInst(until_exit,body_entry,op2,cond_exit);
+
+ // If there's a result, push it now
+ if (until_result)
+ pushOperand(new llvm::LoadInst(until_result,"until_result",until_exit),op);
+
+ // Fix up any break or continue operators
+ resolveBranches(breaks,until_exit);
+ resolveBranches(continues,cond_entry);
}
template<> void
LLVMGeneratorPass::gen(LoopOp* op)
{
- hlvmAssert(lops.size() >= 3 && "Too few operands for LoopOp");
- llvm::Value* op3 = lops.back(); lops.pop_back();
- llvm::Value* op2 = lops.back(); lops.pop_back();
- llvm::Value* op1 = lops.back(); lops.pop_back();
-
- // Get the body of the loop
- llvm::BasicBlock* B2 = getBodyBlock(op2,"loop_body");
-
- // If there's a result in the loop body, get it now
- llvm::AllocaInst* loop_result = getBlockResult(B2,"loop_result");
-
- // Extract the loop start condition expression
- llvm::Value* start_cond = 0;
- llvm::BasicBlock* B1 = getExpressionBlock(op1,start_cond,"loop_start_cond");
-
- // Extract the loop end condition expression
- llvm::Value* end_cond = 0;
- llvm::BasicBlock* B3 = getExpressionBlock(op3,end_cond,"loop_end_cond");
-
- // Terminate the current block with a branch to the start condition block
- new llvm::BranchInst(B1,lblk);
-
- // Terminate the body with a branch to the end_condition block
- new llvm::BranchInst(B3,B2);
-
- // Create a new block for the exit from the while loop
- lblk = new llvm::BasicBlock("loop_exit",lfunc);
+ // Get the result of this loop block, if there should be one
+ llvm::AllocaInst* loop_result = getOperatorResult(op,"loop_result");
- // Terminate the start condition with a conditional branch
- new llvm::BranchInst(B2,lblk,start_cond,B1);
-
- // Terminate the end condition with a conditional branch
- new llvm::BranchInst(B1,lblk,end_cond,B3);
-
- // Deal with the result of the loop, if it has one
- if (loop_result) {
- lops.push_back(new llvm::LoadInst(loop_result,"loop_result",lblk));
- }
+ // Get the start condition block
+ llvm::BasicBlock* start_cond_entry, *start_cond_exit;
+ llvm::Value* op1 =
+ popOperandAsCondition(op->getOperand(0),"loop_start",
+ start_cond_entry,start_cond_exit);
+
+ // Branch the current block into the start condition block
+ new llvm::BranchInst(start_cond_entry,lblk);
+
+ // Get the loop body
+ llvm::BasicBlock *body_entry, *body_exit;
+ llvm::Value* op2 =
+ popOperandAsBlock(op->getOperand(1),"loop_body",body_entry,body_exit);
+
+ // Save the result of the loop body, if there should be one
+ if (loop_result && op2)
+ new llvm::StoreInst(op2,loop_result,body_exit);
+
+ // Get the end condition block
+ llvm::BasicBlock* end_cond_entry, *end_cond_exit;
+ llvm::Value* op3 =
+ popOperandAsCondition(op->getOperand(2),"loop_end",
+ end_cond_entry,end_cond_exit);
+
+ // Branch the loop body to the end condition block
+ branchIfNotTerminated(end_cond_entry,body_exit);
+
+ // Create the exit block
+ llvm::BasicBlock* loop_exit = newBlock("loop_exit");
+
+ // Install the conditional branches for start and end condition blocks
+ new llvm::BranchInst(body_entry,loop_exit,op1,start_cond_exit);
+ new llvm::BranchInst(start_cond_entry,loop_exit,op3,end_cond_exit);
+
+ // If there's a result, push it now
+ if (loop_result)
+ pushOperand(new llvm::LoadInst(loop_result,"loop_result",loop_exit),op);
+
+ // Fix up any break or continue operators
+ resolveBranches(breaks,loop_exit);
+ resolveBranches(continues,end_cond_entry);
}
template<> void
LLVMGeneratorPass::gen(BreakOp* op)
{
+ // Make sure the block result is stored
+ Block* B = llvm::cast<Block>(op->getParent());
+ getBlockResult(B);
+
+ // Just push a place-holder branch onto the breaks list so it can
+ // be fixed up later once we know the destination
+ breaks.push_back(new llvm::BranchInst(lblk,lblk));
}
template<> void
LLVMGeneratorPass::gen(ContinueOp* op)
{
+ // Make sure the block result is stored
+ Block* B = llvm::cast<Block>(op->getParent());
+ getBlockResult(B);
+
+ // Just push a place-holder branch onto the continues list so it can
+ // be fixed up later once we know the destination
+ continues.push_back(new llvm::BranchInst(lblk,lblk));
}
template<> void
LLVMGeneratorPass::gen(ResultOp* r)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for ResultOp");
- llvm::Value* result = lops.back(); lops.pop_back();
- // Save the result value for use in other blocks or as the result of the
- // function
- results[lblk] = result;
+ // Get the result operand
+ llvm::Value* result = popOperand(r->getOperand(0));
+ // Get the block this result applies to
+ hlvm::Block* B = llvm::cast<hlvm::Block>(r->getParent());
+ // Generate a store into the location set up by the block for its result
+ new llvm::StoreInst(result,operands[B],lblk);
}
template<> void
LLVMGeneratorPass::gen(ReturnOp* r)
{
- // If this function returns a result then we need a return value
+ // Initialize the result value. A null Value* indicates no result.
llvm::Value* result = 0;
+
+ // If this function returns a result then we need a return value
if (lfunc->getReturnType() != llvm::Type::VoidTy) {
- hlvmAssert(!results.empty() && "No result for function");
- result = results[lblk];
+ result = operands[function->getBlock()];
const llvm::Type* resultTy = result->getType();
- if (resultTy != lfunc->getReturnType()) {
- result = new llvm::CastInst(result,lfunc->getReturnType(),"result",lblk);
+ if (const llvm::PointerType* PTy =
+ llvm::dyn_cast<llvm::PointerType>(resultTy)) {
+ hlvmAssert(PTy->getElementType() == lfunc->getReturnType());
+ result = new llvm::LoadInst(result,lblk->getName()+"_result",lblk);
+ } else if (resultTy != lfunc->getReturnType()) {
+ result = new llvm::CastInst(result,lfunc->getReturnType(),
+ lblk->getName()+"_result",lblk);
}
hlvmAssert(result && "No result for function");
}
// RetInst is never the operand of another instruction because it is
// a terminator and cannot return a value. Consequently, we don't push it
- // on the lops stack.
+ // on the operand stack.
new llvm::ReturnInst(result,lblk);
}
@@ -1530,37 +1629,50 @@
{
hlvm::Function* hFunc = co->getCalledFunction();
const SignatureType* sigTy = hFunc->getSignature();
+ // Set up the loop
std::vector<llvm::Value*> args;
- hlvmAssert(lops.size() >= sigTy->size()+1 && "Too few operands for CallOp");
- const llvm::Value* arg = lops.back(); lops.pop_back();
- while (!lops.empty() && !llvm::isa<llvm::Function>(arg)) {
- args.push_back(const_cast<llvm::Value*>(arg));
- arg = lops.back();
- lops.pop_back();
- }
- hlvmAssert(sigTy->isVarArgs() || lops.size() == sigTy->size());
- hlvmAssert(!sigTy->isVarArgs() || lops.size() >= sigTy->size());
- hlvmAssert(llvm::isa<llvm::Function>(arg));
+ CallOp::iterator I = co->begin();
+ CallOp::iterator E = co->end();
+
+ // Get the function (first operand)
+ llvm::Value* funcToCall = popOperand(*I++);
+ hlvmAssert(funcToCall && "No function to call?");
+ hlvmAssert(llvm::isa<llvm::Function>(funcToCall));
+
+ // Get the function call operands
+ for ( ; I != E; ++I ) {
+ llvm::Value* arg = popOperand(*I);
+ hlvmAssert(arg && "No argument for CallOp?");
+ args.push_back(arg);
+ }
+
+ // Make sure we have sanity with varargs functions
+ hlvmAssert(sigTy->isVarArgs() || args.size() == sigTy->size());
+ hlvmAssert(!sigTy->isVarArgs() || args.size() >= sigTy->size());
+
+ // convert to function type
llvm::Function* F = const_cast<llvm::Function*>(
- llvm::cast<llvm::Function>(arg));
- saveOperand(new llvm::CallInst(F,args,"call_" + hFunc->getName(),lblk),co);
+ llvm::cast<llvm::Function>(funcToCall));
+
+ // Make the call
+ pushOperand(new llvm::CallInst(F,args,"call_" + hFunc->getName(),lblk),co);
}
template<> void
LLVMGeneratorPass::gen(StoreOp* s)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for StoreOp");
- llvm::Value* value = lops.back(); lops.pop_back();
- llvm::Value* location = lops.back(); lops.pop_back();
- saveOperand(new llvm::StoreInst(value,location,lblk),s);
+ llvm::Value* location = popOperand(s->getOperand(0));
+ llvm::Value* value = popOperand(s->getOperand(1));
+ // We don't push the StoreInst as an operand because it has no value and
+ // therefore cannot be an operand.
+ new llvm::StoreInst(value,location,lblk);
}
template<> void
LLVMGeneratorPass::gen(LoadOp* l)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for LoadOp");
- llvm::Value* location = lops.back(); lops.pop_back();
- saveOperand(new llvm::LoadInst(location,"",lblk),l);
+ llvm::Value* location = popOperand(l->getOperand(0));
+ pushOperand(new llvm::LoadInst(location,location->getName(),lblk),l);
}
template<> void
@@ -1568,115 +1680,107 @@
{
hlvm::Value* referent = const_cast<hlvm::Value*>(r->getReferent());
llvm::Value* v = 0;
- if (llvm::isa<AutoVarOp>(referent))
- {
- AutoVarDictionary::const_iterator I =
+ if (llvm::isa<AutoVarOp>(referent)) {
+ AutoVarMap::const_iterator I =
lvars.find(llvm::cast<AutoVarOp>(referent));
hlvmAssert(I != lvars.end());
v = I->second;
- }
- else if (llvm::isa<ConstantValue>(referent))
- {
+ } else if (llvm::isa<ConstantValue>(referent)) {
const hlvm::ConstantValue* cval = llvm::cast<ConstantValue>(referent);
llvm::Constant* C = getConstant(cval);
hlvmAssert(C && "Can't generate constant?");
v = C;
- }
- else if (llvm::isa<Variable>(referent))
- {
+ } else if (llvm::isa<Variable>(referent)) {
llvm::Value* V = getVariable(llvm::cast<hlvm::Variable>(referent));
hlvmAssert(V && "Variable not found?");
v = V;
- }
- else if (llvm::isa<Function>(referent))
- {
+ } else if (llvm::isa<Function>(referent)) {
llvm::Function* F = getFunction(llvm::cast<hlvm::Function>(referent));
hlvmAssert(F && "Function not found?");
v = F;
- }
- else
+ } else
hlvmDeadCode("Referent not a linkable or autovar?");
- saveOperand(v,r);
+ pushOperand(v,r);
}
template<> void
LLVMGeneratorPass::gen(IndexOp* r)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for IndexOp");
}
template<> void
LLVMGeneratorPass::gen(OpenOp* o)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for OpenOp");
- llvm::Value* strm = lops.back(); lops.pop_back();
+ llvm::Value* strm = popOperand(o->getOperand(0));
std::vector<llvm::Value*> args;
if (const llvm::PointerType* PT =
llvm::dyn_cast<llvm::PointerType>(strm->getType())) {
- const llvm::Type* Ty = PT->getElementType();
- if (Ty == llvm::Type::SByteTy) {
- args.push_back(strm);
- } else if (llvm::isa<llvm::ArrayType>(Ty) &&
- llvm::cast<llvm::ArrayType>(Ty)->getElementType() ==
- llvm::Type::SByteTy) {
- std::vector<llvm::Value*> indices;
- indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
- indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
- llvm::GetElementPtrInst* gep =
- new llvm::GetElementPtrInst(strm,indices,"",lblk);
- args.push_back(gep);
- } else
- hlvmAssert(!"Array element type is not SByteTy");
+ const llvm::Type* Ty = PT->getElementType();
+ if (Ty == llvm::Type::SByteTy) {
+ args.push_back(strm);
+ } else if (llvm::isa<llvm::ArrayType>(Ty) &&
+ llvm::cast<llvm::ArrayType>(Ty)->getElementType() ==
+ llvm::Type::SByteTy) {
+ std::vector<llvm::Value*> indices;
+ indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
+ indices.push_back(llvm::Constant::getNullValue(llvm::Type::UIntTy));
+ llvm::GetElementPtrInst* gep =
+ new llvm::GetElementPtrInst(strm,indices,"",lblk);
+ args.push_back(gep);
+ } else
+ hlvmAssert(!"Array element type is not SByteTy");
} else
hlvmAssert(!"OpenOp parameter is not a pointer");
llvm::CallInst* ci = new
- llvm::CallInst(get_hlvm_stream_open(), args, "", lblk);
- saveOperand(ci,o);
+ llvm::CallInst(get_hlvm_stream_open(), args, "open", lblk);
+ pushOperand(ci,o);
}
template<> void
LLVMGeneratorPass::gen(WriteOp* o)
{
- hlvmAssert(lops.size() >= 2 && "Too few operands for WriteOp");
- llvm::Value* arg2 = lops.back(); lops.pop_back();
- llvm::Value* strm = lops.back(); lops.pop_back();
+ llvm::Value* strm = popOperand(o->getOperand(0));
+ llvm::Value* arg2 = popOperand(o->getOperand(1));
std::vector<llvm::Value*> args;
args.push_back(strm);
args.push_back(arg2);
if (llvm::isa<llvm::PointerType>(arg2->getType()))
- if (llvm::cast<llvm::PointerType>(arg2->getType())->getElementType() ==
- llvm::Type::SByteTy)
- saveOperand(
- new llvm::CallInst(get_hlvm_stream_write_string(), args, "", lblk),o);
+ if (llvm::cast<llvm::PointerType>(arg2->getType())->getElementType() ==
+ llvm::Type::SByteTy)
+ pushOperand(
+ new llvm::CallInst(get_hlvm_stream_write_string(), args, "", lblk),o);
if (arg2->getType() == get_hlvm_text())
- saveOperand(
+ pushOperand(
new llvm::CallInst(get_hlvm_stream_write_text(), args, "", lblk),o);
else if (arg2->getType() == get_hlvm_buffer())
- saveOperand(
- new llvm::CallInst(get_hlvm_stream_write_buffer(), args, "",lblk),o);
+ pushOperand(
+ new llvm::CallInst(get_hlvm_stream_write_buffer(), args, "write",lblk),o);
}
template<> void
LLVMGeneratorPass::gen(ReadOp* o)
{
- hlvmAssert(lops.size() >= 3 && "Too few operands for ReadOp");
+ llvm::Value* strm = popOperand(o->getOperand(0));
+ llvm::Value* arg2 = popOperand(o->getOperand(1));
+ llvm::Value* arg3 = popOperand(o->getOperand(2));
std::vector<llvm::Value*> args;
- args.insert(args.end(),lops.end()-3,lops.end());
- lops.erase(lops.end()-3,lops.end());
+ args.push_back(strm);
+ args.push_back(arg2);
+ args.push_back(arg3);
llvm::CallInst* ci =
- new llvm::CallInst(get_hlvm_stream_read(), args, "", lblk);
- saveOperand(ci,o);
+ new llvm::CallInst(get_hlvm_stream_read(), args, "read", lblk);
+ pushOperand(ci,o);
}
template<> void
LLVMGeneratorPass::gen(CloseOp* o)
{
- hlvmAssert(lops.size() >= 1 && "Too few operands for CloseOp");
+ llvm::Value* strm = popOperand(o->getOperand(0));
std::vector<llvm::Value*> args;
- args.push_back(lops.back()); lops.pop_back();
+ args.push_back(strm);
llvm::CallInst* ci =
new llvm::CallInst(get_hlvm_stream_close(), args, "", lblk);
- saveOperand(ci,o);
+ pushOperand(ci,o);
}
void
@@ -1701,7 +1805,7 @@
std::vector<llvm::Constant*> entry_points_items;
for (std::vector<llvm::Function*>::iterator I = progs.begin(),
- E = progs.end(); I != E; ++I )
+ E = progs.end(); I != E; ++I )
{
const std::string& funcName = (*I)->getName();
// Get a constant for the name of the entry point (char array)
@@ -1786,27 +1890,22 @@
case FunctionID:
{
// Get/Create the function
- lfunc = getFunction(llvm::cast<Function>(n));
- // Clear the LLVM vars
- lvars.clear();
- blocks.clear();
- lops.clear();
- results.clear();
+ function = llvm::cast<hlvm::Function>(n);
+ lfunc = getFunction(function);
+ startNewFunction();
break;
}
case ProgramID:
{
// Create a new function for the program based on the signature
+ function = llvm::cast<hlvm::Program>(n);
lfunc = new llvm::Function(
/*Type=*/ get_hlvm_program_signature(),
/*Linkage=*/llvm::GlobalValue::InternalLinkage,
- /*Name=*/ getLinkageName(llvm::cast<Program>(n)),
+ /*Name=*/ getLinkageName(function),
/*Module=*/ lmod
);
- // Clear LLVM vars
- lvars.clear();
- blocks.clear();
- lops.clear();
+ startNewFunction();
// Save the program so it can be generated into the list of program
// entry points.
progs.push_back(lfunc);
@@ -1815,8 +1914,21 @@
case BlockID:
{
Block* B = llvm::cast<Block>(n);
- lblk = new llvm::BasicBlock(B->getLabel(),lfunc,0);
- blocks.push_back(lblk);
+ std::string name = B->getLabel().empty() ?
+ (blocks.empty()? "entry" : "block") : B->getLabel();
+ enters[B] = pushBlock(name);
+ if (B->getResult()) {
+ const llvm::Type* Ty = getType(B->getType());
+ llvm::AllocaInst* result = new llvm::AllocaInst(
+ /*Ty=*/ Ty,
+ /*ArraySize=*/ llvm::ConstantUInt::get(llvm::Type::UIntTy,1),
+ /*Name=*/ name,
+ /*InsertAtEnd=*/ lblk
+ );
+ // Initialize the autovar to null
+ new llvm::StoreInst(llvm::Constant::getNullValue(Ty),result,lblk);
+ pushOperand(result,B);
+ }
break;
}
default:
@@ -1842,7 +1954,6 @@
case EnumerationTypeID:
case RealTypeID:
case OctetTypeID:
- case VoidTypeID:
case PointerTypeID:
case ArrayTypeID:
case VectorTypeID:
@@ -1869,7 +1980,6 @@
case BOrOpID: gen(llvm::cast<BOrOp>(n)); break;
case BXorOpID: gen(llvm::cast<BXorOp>(n)); break;
case BNorOpID: gen(llvm::cast<BNorOp>(n)); break;
- case NullOpID: gen(llvm::cast<NullOp>(n)); break;
case NotOpID: gen(llvm::cast<NotOp>(n)); break;
case AndOpID: gen(llvm::cast<AndOp>(n)); break;
case OrOpID: gen(llvm::cast<OrOp>(n)); break;
@@ -1906,23 +2016,29 @@
lmod = 0;
break;
case ConstantBooleanID:
+ /* FALL THROUGH */
case ConstantIntegerID:
+ /* FALL THROUGH */
case ConstantRealID:
+ /* FALL THROUGH */
case ConstantStringID:
+ /* FALL THROUGH */
case VariableID:
break;
case ProgramID:
+ /* FALL THROUGH */
case FunctionID:
+ function = 0;
lfunc = 0;
break;
case BlockID:
- lops.push_back(lblk);
- blocks.pop_back();
- if (blocks.empty())
- lblk = 0;
- else
- lblk = blocks.back();
+ {
+ Block* B = llvm::cast<Block>(n);
+ exits[B] = lblk;
+ getBlockResult(B);
+ popBlock(lblk);
break;
+ }
// everything else is an error
default:
@@ -1951,7 +2067,7 @@
}
-void
+bool
hlvm::generateBytecode(AST* tree, std::ostream& output, bool verify)
{
hlvm::PassManager* PM = hlvm::PassManager::create();
@@ -1960,13 +2076,16 @@
PM->runOn(tree);
delete PM;
llvm::Module* mod = genPass.linkModules();
+ bool result = false;
if (!llvm::verifyModule(*mod, llvm::PrintMessageAction)) {
llvm::WriteBytecodeToFile(mod, output, /*compress= */ true);
+ result = true;
}
delete mod;
+ return result;
}
-void
+bool
hlvm::generateAssembly(AST* tree, std::ostream& output, bool verify)
{
hlvm::PassManager* PM = hlvm::PassManager::create();
@@ -1975,10 +2094,13 @@
PM->runOn(tree);
delete PM;
llvm::Module* mod = genPass.linkModules();
+ bool result = false;
if (!llvm::verifyModule(*mod, llvm::PrintMessageAction)) {
llvm::PassManager Passes;
Passes.add(new llvm::PrintModulePass(&output));
Passes.run(*mod);
+ result = true;
}
delete mod;
+ return result;
}
Modified: hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h (original)
+++ hlvm/trunk/hlvm/CodeGen/LLVMGenerator.h Sat Jul 7 19:02:21 2007
@@ -32,17 +32,24 @@
#include <ostream>
+namespace llvm {
+ class Module;
+}
+
namespace hlvm
{
class AST;
/// Convert an Abstract Syntax Tree into LLVM bytecode written on the output
/// stream.
- void generateBytecode(AST* input, std::ostream& output, bool verify = true);
+ bool generateBytecode(AST* input, std::ostream& output, bool verify = true);
/// Convert an Abstract Syntax Tree into LLVM assembly written on the output
/// stream.
- void generateAssembly(AST* input, std::ostream& output, bool verify = true);
+ bool generateAssembly(AST* input, std::ostream& output, bool verify = true);
+
+ /// Convert an Abstract Syntax Tree into an LLVM Module
+ llvm::Module* generateModule(AST* input, bool verify = true);
} // hlvm
#endif
Modified: hlvm/trunk/hlvm/Pass/Validate.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Pass/Validate.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/Pass/Validate.cpp (original)
+++ hlvm/trunk/hlvm/Pass/Validate.cpp Sat Jul 7 19:02:21 2007
@@ -317,12 +317,6 @@
}
template<> inline void
-ValidateImpl::validate(VoidType* n)
-{
- checkType(n,VoidTypeID);
-}
-
-template<> inline void
ValidateImpl::validate(AnyType* n)
{
checkType(n,AnyTypeID);
@@ -630,7 +624,7 @@
if (llvm::isa<ReturnOp>(terminator)) {
if (!result) {
Function* F= n->getContainingFunction();
- if (F->getResultType() != ast->getPrimitiveType(VoidTypeID))
+ if (F->getResultType())
error(terminator,"Missing result in return from function");
}
} else if (result) {
@@ -644,42 +638,36 @@
}
template<> inline void
-ValidateImpl::validate(NullOp* n)
-{
- checkOperator(n,NullOpID,0);
-}
-
-
-template<> inline void
ValidateImpl::validate(ResultOp* n)
{
if (checkOperator(n,ResultOpID,1)) {
- if (!isa<Block>(n->getParent())) {
- error(n, "ResultOp not in a Block");
- return;
- }
- const Function* F = n->getContainingFunction();
- if (!F)
- error(n,"ResultOp not in Function!");
- else {
- const Block* B = n->getContainingBlock();
- if (!B)
- error(n,"ResultOp not in a Block");
- else if (F->getBlock() == B) {
- const SignatureType* SigTy = F->getSignature();
- Operator* res = n->getOperand(0);
- if (res) {
- if (res->getType()) {
- if (res->getType() != SigTy->getResultType())
- error(n,"Result does not agree in type with Function result");
- } else if (SigTy->getResultType() !=
- ast->getPrimitiveType(VoidTypeID)) {
- error(n,"Void function result for non-void function");
+ if (Block* B = dyn_cast<Block>(n->getParent())) {
+ if (Operator* res = n->getOperand(0)) {
+ if (const Operator* existing_result = B->getResult()) {
+ if (existing_result->getType() != res->getType()) {
+ error(n,"ResultOp does not match block result type");
}
} else {
- error(n,"Result operator with no operand");
+ error(n,"Block has no result type, but has ResultOp");
}
+ if (Function* F = n->getContainingFunction()) {
+ if (F->getBlock() == B) {
+ const SignatureType* SigTy = F->getSignature();
+ if (res->getType()) {
+ if (res->getType() != SigTy->getResultType())
+ error(n,"ResultOp does not agree in type with Function result");
+ } else if (SigTy->getResultType()) {
+ error(n,"Void function result for non-void function");
+ }
+ }
+ } else {
+ error(n,"ResultOP not in function?");
+ }
+ } else {
+ error(n,"ResultOp with no operand");
}
+ } else {
+ error(n, "ResultOp not in a Block");
}
}
}
@@ -716,8 +704,9 @@
checkBooleanExpression(n->getOperand(0));
if (checkResult(n->getOperand(1)))
if (checkResult(n->getOperand(2)))
- if (n->getOperand(1)->getType() != n->getOperand(2)->getType())
- error(n,"Second and third operands for SelectOp must have same type");
+ if (!isa<Block>(n->getParent()))
+ if (n->getOperand(1)->getType() != n->getOperand(2)->getType())
+ error(n,"SelectOp operands must have same type");
}
}
@@ -807,11 +796,7 @@
{
if (const PointerType* PT = llvm::dyn_cast<PointerType>(n->getType()))
{
- if (const Type* Ty = PT->getElementType())
- {
- if (!Ty->isSized())
- error(n,"Can't allocate an unsized type");
- } else
+ if (!PT->getElementType())
error(n,"AllocateOp's pointer type has no element type!");
} else
error(n,"AllocateOp's type must be a pointer type");
@@ -825,10 +810,7 @@
{
if (checkOperator(n,DeallocateOpID,1)) {
if (const PointerType* PT = llvm::dyn_cast<PointerType>(n->getType())) {
- if (const Type* Ty = PT->getElementType()) {
- if (!Ty->isSized())
- error(n,"Can't deallocate an unsized type");
- } else
+ if (!PT->getElementType())
error(n,"DeallocateOp's pointer type has no element type!");
} else
error(n,"DeallocateOp expects its first operand to be a pointer type");
@@ -1415,7 +1397,6 @@
case NoTypeID:
hlvmDeadCode("Invalid Node Kind");
break;
- case VoidTypeID: validate(cast<VoidType>(n)); break;
case AnyTypeID: validate(cast<AnyType>(n)); break;
case BooleanTypeID: validate(cast<BooleanType>(n)); break;
case CharacterTypeID: validate(cast<CharacterType>(n)); break;
@@ -1452,7 +1433,6 @@
case CreateContOpID: /*validate(cast<CreateContOp>(n));*/ break;
case CallWithContOpID: /*validate(cast<CallWithContOp>(n));*/ break;
case ThrowOpID: /*validate(cast<ThrowOp>(n));*/ break;
- case NullOpID: validate(cast<NullOp>(n)); break;
case ReturnOpID: validate(cast<ReturnOp>(n)); break;
case ResultOpID: validate(cast<ResultOp>(n)); break;
case ContinueOpID: validate(cast<ContinueOp>(n)); break;
Modified: hlvm/trunk/hlvm/Reader/HLVM.rng
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Reader/HLVM.rng?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/Reader/HLVM.rng (original)
+++ hlvm/trunk/hlvm/Reader/HLVM.rng Sat Jul 7 19:02:21 2007
@@ -659,7 +659,6 @@
<define name="Operators.pat">
<choice>
<ref name="block.elem"/>
- <ref name="noop.elem"/>
<ref name="BooleanOperators.pat"/>
<ref name="UnaryArithmeticOperators.pat"/>
<ref name="BinaryArithmeticOperators.pat"/>
@@ -674,7 +673,6 @@
<ref name="Operators.pat"/>
</define>
-
<define name="BinaryOperator.pat">
<ref name="Documentation.pat"/>
<ref name="Operators.pat"/>
@@ -701,14 +699,18 @@
<attribute name="label"><ref name="Identifier.type"/></attribute>
</optional>
<oneOrMore>
- <ref name="Operators.pat"/>
+ <choice>
+ <ref name="Operators.pat"/>
+ <ref name="result.elem"/>
+ </choice>
</oneOrMore>
</element>
</define>
- <define name="noop.elem">
- <element name="noop">
- <empty/>
+ <define name="result.elem">
+ <element name="result">
+ <ref name="Documentation.pat"/>
+ <ref name="Operators.pat"/>
</element>
</define>
@@ -1056,7 +1058,6 @@
<ref name="break.elem"/>
<ref name="continue.elem"/>
<ref name="ret.elem"/>
- <ref name="result.elem"/>
<ref name="call.elem"/>
</choice>
</define>
@@ -1143,13 +1144,6 @@
</element>
</define>
- <define name="result.elem">
- <element name="result">
- <ref name="Documentation.pat"/>
- <ref name="Operators.pat"/>
- </element>
- </define>
-
<define name="call.elem">
<element name="call">
<oneOrMore>
Modified: hlvm/trunk/hlvm/Reader/XMLReader.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Reader/XMLReader.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/Reader/XMLReader.cpp (original)
+++ hlvm/trunk/hlvm/Reader/XMLReader.cpp Sat Jul 7 19:02:21 2007
@@ -290,7 +290,6 @@
case TKN_u32: result = ast->getPrimitiveType(UInt32TypeID); break;
case TKN_u64: result = ast->getPrimitiveType(UInt64TypeID); break;
case TKN_u8: result = ast->getPrimitiveType(UInt8TypeID); break;
- case TKN_void: result = ast->getPrimitiveType(VoidTypeID); break;
default:
break;
}
@@ -329,7 +328,6 @@
case TKN_u32: result = ast->new_u32(name,loc); break;
case TKN_u64: result = ast->new_u64(name,loc); break;
case TKN_u8: result = ast->new_u8(name,loc); break;
- case TKN_void: result = ast->new_VoidType(name,loc); break;
default: break;
}
return result;
@@ -1088,7 +1086,6 @@
case TKN_bor: op = parseBinaryOp<BOrOp>(cur); break;
case TKN_bxor: op = parseBinaryOp<BXorOp>(cur); break;
case TKN_bnor: op = parseBinaryOp<BNorOp>(cur); break;
- case TKN_noop: op = parseNilaryOp<NullOp>(cur); break;
case TKN_not: op = parseUnaryOp<NotOp>(cur); break;
case TKN_and: op = parseBinaryOp<AndOp>(cur); break;
case TKN_or: op = parseBinaryOp<OrOp>(cur); break;
Modified: hlvm/trunk/hlvm/Writer/XMLWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Writer/XMLWriter.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/hlvm/Writer/XMLWriter.cpp (original)
+++ hlvm/trunk/hlvm/Writer/XMLWriter.cpp Sat Jul 7 19:02:21 2007
@@ -303,17 +303,6 @@
}
template<> void
-XMLWriterImpl::WriterPass::put(VoidType* t)
-{
- startElement("atom");
- writeAttribute("id",t->getName());
- putDoc(t);
- startElement("intrinsic");
- writeAttribute("is","void");
- endElement();
-}
-
-template<> void
XMLWriterImpl::WriterPass::put(OpaqueType* op)
{
startElement("opaque");
@@ -671,13 +660,6 @@
putDoc(op);
}
-
-template<> void
-XMLWriterImpl::WriterPass::put(NullOp* op)
-{
- startElement("noop");
-}
-
template<> void
XMLWriterImpl::WriterPass::put(SelectOp* op)
{
@@ -833,7 +815,6 @@
case EnumerationTypeID: put(cast<EnumerationType>(n)); break;
case RealTypeID: put(cast<RealType>(n)); break;
case OctetTypeID: put(cast<OctetType>(n)); break;
- case VoidTypeID: put(cast<VoidType>(n)); break;
case OpaqueTypeID: put(cast<OpaqueType>(n)); break;
case PointerTypeID: put(cast<PointerType>(n)); break;
case ArrayTypeID: put(cast<ArrayType>(n)); break;
@@ -875,7 +856,6 @@
case GreaterThanOpID: put(cast<GreaterThanOp>(n)); break;
case LessEqualOpID: put(cast<LessEqualOp>(n)); break;
case GreaterEqualOpID: put(cast<GreaterEqualOp>(n)); break;
- case NullOpID: put(cast<NullOp>(n)); break;
case SelectOpID: put(cast<SelectOp>(n)); break;
case SwitchOpID: put(cast<SwitchOp>(n)); break;
case WhileOpID: put(cast<WhileOp>(n)); break;
Added: hlvm/trunk/test/return0/break.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/break.hlx?rev=38325&view=auto
==============================================================================
--- hlvm/trunk/test/return0/break.hlx (added)
+++ hlvm/trunk/test/return0/break.hlx Sat Jul 7 19:02:21 2007
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<hlvm xmlns="http://hlvm.org/src/hlvm/Reader/XML/HLVM.rng" pubid="http://hlvm.org/src/hlvm/test/return0/break.hlx">
+ <bundle id="break">
+ <constant id="0" type="s32">
+ <dec>0</dec>
+ </constant>
+ <constant id="1" type="s32">
+ <dec>1</dec>
+ </constant>
+ <program id="break">
+ <block>
+ <result>
+ <while>
+ <ne><ref id="1"/><ref id="0"/></ne>
+ <block>
+ <select>
+ <ne><ref id="1"/><ref id="0"/></ne>
+ <block><break/></block>
+ <ref id="1"/>
+ </select>
+ <result><ref id="1"/></result>
+ </block>
+ </while>
+ </result>
+ <ret/>
+ </block>
+ </program>
+ </bundle>
+</hlvm>
Modified: hlvm/trunk/test/return0/until.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/until.hlx?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/test/return0/until.hlx (original)
+++ hlvm/trunk/test/return0/until.hlx Sat Jul 7 19:02:21 2007
@@ -12,10 +12,10 @@
<result>
<until>
<block><result><ref id="0"/></result></block>
- <eq>
+ <ne>
<ref id="1"/>
<ref id="0"/>
- </eq>
+ </ne>
</until>
</result>
<ret/>
Modified: hlvm/trunk/test/xml2xml/doc.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/xml2xml/doc.hlx?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/test/xml2xml/doc.hlx (original)
+++ hlvm/trunk/test/xml2xml/doc.hlx Sat Jul 7 19:02:21 2007
@@ -50,10 +50,6 @@
<doc>Obviously this is a boolean</doc>
<intrinsic is="bool"/>
</atom>
- <atom id="20">
- <doc>The void type, zero size</doc>
- <intrinsic is="void"/>
- </atom>
<atom id="3">
<doc>UTF-16 character</doc>
<intrinsic is="char"/>
Modified: hlvm/trunk/test/xml2xml/intrinsics.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/xml2xml/intrinsics.hlx?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/test/xml2xml/intrinsics.hlx (original)
+++ hlvm/trunk/test/xml2xml/intrinsics.hlx Sat Jul 7 19:02:21 2007
@@ -37,9 +37,6 @@
<atom id="2">
<intrinsic is="bool"/>
</atom>
- <atom id="20">
- <intrinsic is="void"/>
- </atom>
<atom id="3">
<intrinsic is="char"/>
</atom>
Modified: hlvm/trunk/tools/hlvm-compiler/hlvm-compiler.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/tools/hlvm-compiler/hlvm-compiler.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/tools/hlvm-compiler/hlvm-compiler.cpp (original)
+++ hlvm/trunk/tools/hlvm-compiler/hlvm-compiler.cpp Sat Jul 7 19:02:21 2007
@@ -50,6 +50,9 @@
static cl::opt<bool> NoValidate("no-validate", cl::init(false),
cl::desc("Don't validate input before generating code"));
+static cl::opt<bool> NoVerify("no-verify", cl::init(false),
+ cl::desc("Don't verify generated LLVM module"));
+
enum GenerationOptions {
GenLLVMBytecode,
GenLLVMAssembly,
@@ -75,7 +78,7 @@
try {
initialize(argc,argv);
cl::ParseCommandLineOptions(argc, argv,
- "hlvm-xml2xml XML->AST->XML translator\n");
+ "hlvm-compile: Compile HLVM AST To Other Forms\n");
std::ostream *Out = &std::cout; // Default to printing to stdout.
@@ -119,12 +122,14 @@
AST* node = rdr->get();
if (node && !NoValidate) {
if (!validate(node))
- return 3;
+ exit(3);
}
if (WhatToGenerate == GenLLVMBytecode) {
- generateBytecode(node,*Out);
+ if (!generateBytecode(node,*Out, !NoVerify))
+ exit(4);
} else if (WhatToGenerate == GenLLVMAssembly) {
- generateAssembly(node,*Out);
+ if (!generateAssembly(node,*Out, !NoVerify))
+ exit(4);
}
delete rdr;
Modified: hlvm/trunk/tools/hlvm-config/hlvm-config.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/tools/hlvm-config/hlvm-config.cpp?rev=38325&r1=38324&r2=38325&view=diff
==============================================================================
--- hlvm/trunk/tools/hlvm-config/hlvm-config.cpp (original)
+++ hlvm/trunk/tools/hlvm-config/hlvm-config.cpp Sat Jul 7 19:02:21 2007
@@ -46,7 +46,6 @@
"Documentable",
"Bundle",
"Import",
- "VoidType",
"BooleanType",
"CharacterType",
"OctetType",
@@ -105,7 +104,6 @@
"NInfOp",
"NaNOp",
"ReferenceOp",
- "NullOp",
"ResultOp",
"ThrowOp",
"NotOp",
More information about the llvm-commits
mailing list