[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