[llvm-commits] [hlvm] r38306 - in /hlvm/trunk: hlvm/AST/ hlvm/CodeGen/ hlvm/Pass/ hlvm/Reader/ hlvm/Writer/ test/invalid/ test/return0/ test/xml2xml/

Reid Spencer reid at x10sys.com
Sat Jul 7 17:02:10 PDT 2007


Author: reid
Date: Sat Jul  7 19:02:10 2007
New Revision: 38306

URL: http://llvm.org/viewvc/llvm-project?rev=38306&view=rev
Log:
This patch gets 4 kinds of loop operators working. It also resolves numerous
issues about blocks, their results, getting correct LLVM operands, etc. A 
number of new test cases were added to ensure its all working correctly.

Added:
    hlvm/trunk/test/invalid/funcresult.hlx
    hlvm/trunk/test/return0/loop.hlx
    hlvm/trunk/test/return0/noresult.hlx
    hlvm/trunk/test/return0/resultoverride.hlx
    hlvm/trunk/test/return0/unless.hlx
    hlvm/trunk/test/return0/until.hlx
    hlvm/trunk/test/return0/unused.hlx
    hlvm/trunk/test/return0/while.hlx
    hlvm/trunk/test/xml2xml/unless.hlx
    hlvm/trunk/test/xml2xml/until.hlx
    hlvm/trunk/test/xml2xml/while.hlx
Modified:
    hlvm/trunk/hlvm/AST/AST.cpp
    hlvm/trunk/hlvm/AST/Block.h
    hlvm/trunk/hlvm/AST/ControlFlow.cpp
    hlvm/trunk/hlvm/AST/ControlFlow.h
    hlvm/trunk/hlvm/AST/Node.h
    hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp
    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/arithmetic.hlx
    hlvm/trunk/test/return0/bitwise.hlx
    hlvm/trunk/test/return0/boolean.hlx
    hlvm/trunk/test/return0/call.hlx
    hlvm/trunk/test/return0/complement.hlx
    hlvm/trunk/test/return0/return0.hlx
    hlvm/trunk/test/return0/select.hlx
    hlvm/trunk/test/xml2xml/break.hlx
    hlvm/trunk/test/xml2xml/continue.hlx
    hlvm/trunk/test/xml2xml/loop.hlx

Modified: hlvm/trunk/hlvm/AST/AST.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/AST.cpp?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/AST.cpp (original)
+++ hlvm/trunk/hlvm/AST/AST.cpp Sat Jul  7 19:02:10 2007
@@ -1005,6 +1005,21 @@
   return new_TernaryOp<SelectOp>(op2->getType(),op1,op2,op3,loc);
 }
 
+template WhileOp*
+AST::new_BinaryOp<WhileOp>(const Type* Ty, Operator* op1, Operator* op2, const Locator* loc);
+template WhileOp*
+AST::new_BinaryOp<WhileOp>(Operator* op1, Operator* op2,const Locator* loc);
+
+template UnlessOp*
+AST::new_BinaryOp<UnlessOp>(const Type* Ty, Operator* op1, Operator* op2, const Locator* loc);
+template UnlessOp*
+AST::new_BinaryOp<UnlessOp>(Operator* op1, Operator* op2,const Locator* loc);
+
+template UntilOp*
+AST::new_BinaryOp<UntilOp>(const Type* Ty, Operator* op1, Operator* op2, const Locator* loc);
+template UntilOp*
+AST::new_BinaryOp<UntilOp>(Operator* op1, Operator* op2,const Locator* loc);
+
 template LoopOp*
 AST::new_TernaryOp<LoopOp>(const Type* Ty, Operator*op1,Operator*op2,Operator*op3,const Locator* loc);
 

Modified: hlvm/trunk/hlvm/AST/Block.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Block.h?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/Block.h (original)
+++ hlvm/trunk/hlvm/AST/Block.h Sat Jul  7 19:02:10 2007
@@ -61,7 +61,7 @@
     virtual const Type* getType() const { return this->back()->getType(); }
     const std::string& getLabel() const { return label; }
     AutoVarOp* getAutoVar(const std::string& name) const; 
-    const Type* getResultType() const { return result->getType(); }
+    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=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/ControlFlow.cpp (original)
+++ hlvm/trunk/hlvm/AST/ControlFlow.cpp Sat Jul  7 19:02:10 2007
@@ -40,7 +40,67 @@
 NullOp::~NullOp() {}
 SelectOp::~SelectOp() {}
 SwitchOp::~SwitchOp() {}
+WhileOp::~WhileOp() {}
+const Type* 
+WhileOp::getType() const
+{
+  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();
+  }
+}
+
+UnlessOp::~UnlessOp() {}
+const Type* 
+UnlessOp::getType() const
+{
+  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();
+  }
+}
+
+UntilOp::~UntilOp() {}
+const Type* 
+UntilOp::getType() const
+{
+  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();
+  }
+}
+
 LoopOp::~LoopOp() {}
+
+const Type* 
+LoopOp::getType() const
+{
+  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();
+  }
+}
+
 ReturnOp::~ReturnOp() { }
 BreakOp::~BreakOp() {}
 ContinueOp::~ContinueOp() {}

Modified: hlvm/trunk/hlvm/AST/ControlFlow.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/ControlFlow.h?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/ControlFlow.h (original)
+++ hlvm/trunk/hlvm/AST/ControlFlow.h Sat Jul  7 19:02:10 2007
@@ -122,6 +122,94 @@
   friend class AST;
 };
 
+/// This class prvoides an Abstract Syntax Tree node that represents a loop
+/// construct with two operands. The first operand is a boolean expression 
+/// that is tested before each iteration. If the expression evaluates to false,
+/// the loop terminates. The second operand is the expression or block to be 
+/// executed on each iteration. This is similar to a "while" loop in other 
+/// languages, hence the name. If the second operand declares a result, then
+/// the value of that result on the final iteration is the value of the loop.
+/// Otherwise the WhileOp may not be used as a value (has type void).
+/// @brief AST While Loop Operator Node
+class WhileOp : public BinaryOperator
+{
+  /// @name Constructors
+  /// @{
+  protected:
+    WhileOp() : BinaryOperator(WhileOpID) {}
+    virtual ~WhileOp();
+
+  /// @}
+  /// @name Accessors
+  /// @{
+  public:
+    virtual const Type* getType() const;
+    static inline bool classof(const WhileOp*) { return true; }
+    static inline bool classof(const Node* N) { return N->is(WhileOpID); }
+
+  /// @}
+  friend class AST;
+};
+
+/// This class prvoides an Abstract Syntax Tree node that represents a loop
+/// construct with two operands. The first operand is a boolean expression 
+/// that is tested before each iteration. If the expression evaluates to true, 
+/// the loop terminates. The second operand is the expression or block to be 
+/// executed on each iteration. This is similar to a "while" loop in other 
+/// languages, except the logic of the control expression is inverted. If the 
+/// second operand declares a result, then the value of that result on the 
+/// final iteration is the value of the loop.  Otherwise the UnlessOp may 
+/// not be used as a value (has type void).
+/// @brief AST Unless Loop Operator Node
+class UnlessOp : public BinaryOperator
+{
+  /// @name Constructors
+  /// @{
+  protected:
+    UnlessOp() : BinaryOperator(UnlessOpID) {}
+    virtual ~UnlessOp();
+
+  /// @}
+  /// @name Accessors
+  /// @{
+  public:
+    virtual const Type* getType() const;
+    static inline bool classof(const UnlessOp*) { return true; }
+    static inline bool classof(const Node* N) { return N->is(UnlessOpID); }
+
+  /// @}
+  friend class AST;
+};
+
+/// This class prvoides an Abstract Syntax Tree node that represents a loop
+/// construct with two operands. The second operand is a boolean expression 
+/// that is tested after each iteration. If the expression evaluates to true, 
+/// the loop terminates. The first operand is the expression or block to be 
+/// executed on each iteration. This is similar to a "do" loop in other 
+/// languages. If the first operand declares a result, then the value of that 
+/// result on the final iteration is the value of the loop.  Otherwise the 
+/// UntilOp may not be used as a value (has type void).
+/// @brief AST Unless Loop Operator Node
+class UntilOp : public BinaryOperator
+{
+  /// @name Constructors
+  /// @{
+  protected:
+    UntilOp() : BinaryOperator(UntilOpID) {}
+    virtual ~UntilOp();
+
+  /// @}
+  /// @name Accessors
+  /// @{
+  public:
+    virtual const Type* getType() const;
+    static inline bool classof(const UntilOp*) { return true; }
+    static inline bool classof(const Node* N) { return N->is(UntilOpID); }
+
+  /// @}
+  friend class AST;
+};
+
 /// This class provides an Abstract Syntax Tree node that represents a
 /// generalized loop construct for HLVM. The LoopOp takes three operands, as
 /// follows:
@@ -131,9 +219,7 @@
 ///    loop. This is the main body of the loop
 /// -# a boolean expression to be evaluated after each iteration ends that 
 ///    controls loop termination
-/// Either or both of the control expressions can be a NoOp operator in which
-/// case the test is not performed. If both control expressions are NoOp, the 
-/// loop is infinite.
+/// This construct is similar to combining a WhileOp with an UntilOp.
 /// @brief AST Loop Operator Node
 class LoopOp : public TernaryOperator
 {
@@ -147,6 +233,7 @@
   /// @name Accessors
   /// @{
   public:
+    virtual const Type* getType() const;
     static inline bool classof(const LoopOp*) { return true; }
     static inline bool classof(const Node* N) { return N->is(LoopOpID); }
 

Modified: hlvm/trunk/hlvm/AST/Node.h
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/AST/Node.h?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/AST/Node.h (original)
+++ hlvm/trunk/hlvm/AST/Node.h Sat Jul  7 19:02:10 2007
@@ -244,6 +244,11 @@
   ReallocateOpID,          ///< The Reallocate Memory Operator 
   StoreOpID,               ///< The Store Operator (store a value to a location)
 
+  // Binary Control Flow Operators
+  WhileOpID,               ///< While expression is true loop
+  UnlessOpID,              ///< Unless expression is true loop
+  UntilOpID,               ///< Do block until expression is true loop
+
   // Other Binary Operators
   OpenOpID,                ///< Open a stream from a URL
   ReadOpID,                ///< Read from a stream

Modified: hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp (original)
+++ hlvm/trunk/hlvm/CodeGen/LLVMGenerator.cpp Sat Jul  7 19:02:10 2007
@@ -77,7 +77,7 @@
   typedef std::vector<llvm::Module*> ModuleList;
   typedef std::vector<llvm::Value*> OperandList;
   typedef std::vector<llvm::BasicBlock*> BlockStack;
-  typedef std::map<llvm::BasicBlock*,llvm::Value*> ResultDictionary;
+  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*> 
@@ -89,7 +89,7 @@
   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
-  ResultDictionary results;  ///< Dictionary of LLVM blocks to result values
+  ResultsDictionary results; ///< Dictionary of LLVM blocks to result values
   VariableDictionary gvars;  ///< Dictionary of HLVM -> LLVM gvars
   AutoVarDictionary lvars;   ///< Dictionary of HLVM -> LLVM auto vars
   llvm::TypeSymbolTable ltypes; ///< The cached LLVM types we've generated
@@ -147,6 +147,12 @@
   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);
 
   /// Accessors for HLVM Runtime Library things
   inline llvm::Type*         get_hlvm_size();
@@ -706,6 +712,90 @@
   return Load;
 }
 
+void 
+LLVMGeneratorPass::saveOperand(llvm::Value* v, const Operator* op)
+{
+  if (op)
+    if (!llvm::isa<Block>(op->getParent()))
+      lops.push_back(v);
+}
+
+bool 
+LLVMGeneratorPass::hasResult(llvm::BasicBlock* B) const
+{
+  if (B) {
+    ResultsDictionary::const_iterator I = results.find(B);
+    return I != results.end();
+  }
+  return false;
+}
+
+llvm::AllocaInst* 
+LLVMGeneratorPass::getBlockResult(llvm::BasicBlock* B, const char* name)
+{
+  if (hasResult(B)) {
+    const llvm::Type* Ty = results[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);
+    // Store the value on each iteration
+    new llvm::StoreInst(results[B],result,B);
+    return result;
+  }
+  return 0;
+}
+
+llvm::BasicBlock* 
+LLVMGeneratorPass::getBodyBlock(llvm::Value* V, const std::string& name)
+{
+  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;
+}
+
+llvm::BasicBlock*
+LLVMGeneratorPass::getExpressionBlock(
+  llvm::Value* V, llvm::Value*& cond, const std::string& name)
+{
+  // 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);
+  }
+  hlvmAssert(cond->getType() == llvm::Type::BoolTy);
+  return B;
+}
+
 template<> void
 LLVMGeneratorPass::gen(AutoVarOp* av)
 {
@@ -752,7 +842,7 @@
     }
     llvm::Value* store = new llvm::StoreInst(C,alloca,"",lblk);
   }
-  lops.push_back(alloca);
+  saveOperand(alloca,av);
   lvars[av] = alloca;
 }
 
@@ -767,7 +857,7 @@
               "Can't negate non-numeric");
   llvm::BinaryOperator* neg = 
     llvm::BinaryOperator::createNeg(operand,"neg",lblk);
-  lops.push_back(neg);
+  saveOperand(neg,op);
 }
 
 template<> void
@@ -782,7 +872,7 @@
     llvm::ConstantIntegral::getAllOnesValue(lType);
   llvm::BinaryOperator* cmpl = llvm::BinaryOperator::create(
       llvm::Instruction::Xor,operand,allOnes,"cmpl",lblk);
-  lops.push_back(cmpl);
+  saveOperand(cmpl,op);
 }
 
 template<> void
@@ -791,16 +881,22 @@
   hlvmAssert(lops.size() >= 1 && "Too few operands for PreIncrOp");
   llvm::Value* operand = lops.back(); lops.pop_back();
   const llvm::Type* lType = operand->getType();
+  hlvmAssert(llvm::isa<llvm::PointerType>(lType));
+  const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
+  lType = PT->getElementType();
+  llvm::LoadInst* load = new llvm::LoadInst(operand,"preincr",lblk);
   if (lType->isFloatingPoint()) {
     llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
     llvm::BinaryOperator* add = llvm::BinaryOperator::create(
-      llvm::Instruction::Add, operand, one, "preincr", lblk);
-    lops.push_back(add);
+      llvm::Instruction::Add, load, one, "preincr", lblk);
+    new llvm::StoreInst(add,operand,"preincr",lblk);
+    saveOperand(add,op);
   } else if (lType->isInteger()) {
     llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
     llvm::BinaryOperator* add = llvm::BinaryOperator::create(
-      llvm::Instruction::Add, operand, one, "preincr", lblk);
-    lops.push_back(add);
+      llvm::Instruction::Add, load, one, "preincr", lblk);
+    new llvm::StoreInst(add,operand,"preincr",lblk);
+    saveOperand(add,op);
   } else {
     hlvmAssert(!"PreIncrOp on non-numeric");
   }
@@ -812,16 +908,22 @@
   hlvmAssert(lops.size() >= 1 && "Too few operands for PreDecrOp");
   llvm::Value* operand = lops.back(); lops.pop_back();
   const llvm::Type* lType = operand->getType();
+  hlvmAssert(llvm::isa<llvm::PointerType>(lType));
+  const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
+  lType = PT->getElementType();
+  llvm::LoadInst* load = new llvm::LoadInst(operand,"predecr",lblk);
   if (lType->isFloatingPoint()) {
     llvm::ConstantFP* one = llvm::ConstantFP::get(lType,1.0);
     llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
-      llvm::Instruction::Sub, operand, one, "predecr", lblk);
-    lops.push_back(sub);
+      llvm::Instruction::Sub, load, one, "predecr", lblk);
+    new llvm::StoreInst(sub,operand,"predecr",lblk);
+    saveOperand(sub,op);
   } else if (lType->isInteger()) {
     llvm::ConstantInt* one = llvm::ConstantInt::get(lType,1);
     llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
-      llvm::Instruction::Sub, operand, one, "predecr", lblk);
-    lops.push_back(sub);
+      llvm::Instruction::Sub, load, one, "predecr", lblk);
+    new llvm::StoreInst(sub,operand,"predecr",lblk);
+    saveOperand(sub,op);
   } else {
     hlvmAssert(!"PreIncrOp on non-numeric");
   }
@@ -831,12 +933,54 @@
 LLVMGeneratorPass::gen(PostIncrOp* op)
 {
   hlvmAssert(lops.size() >= 1 && "Too few operands for PostIncrOp");
+  llvm::Value* operand = lops.back(); lops.pop_back();
+  const llvm::Type* lType = operand->getType();
+  hlvmAssert(llvm::isa<llvm::PointerType>(lType));
+  const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
+  lType = PT->getElementType();
+  llvm::LoadInst* load = new llvm::LoadInst(operand,"postincr",lblk);
+  if (lType->isFloatingPoint()) {
+    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);
+  } 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);
+  } else {
+    hlvmAssert(!"PostDecrOp on non-numeric");
+  }
 }
 
 template<> void
 LLVMGeneratorPass::gen(PostDecrOp* op)
 {
   hlvmAssert(lops.size() >= 1 && "Too few operands for PostDecrOp");
+  llvm::Value* operand = lops.back(); lops.pop_back();
+  const llvm::Type* lType = operand->getType();
+  hlvmAssert(llvm::isa<llvm::PointerType>(lType));
+  const llvm::PointerType* PT = llvm::cast<llvm::PointerType>(lType);
+  lType = PT->getElementType();
+  llvm::LoadInst* load = new llvm::LoadInst(operand,"postincr",lblk);
+  if (lType->isFloatingPoint()) {
+    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);
+  } 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);
+  } else {
+    hlvmAssert(!"PostDecrOp on non-numeric");
+  }
 }
 
 template<> void
@@ -849,7 +993,7 @@
   op2 = ptr2Value(op2);
   llvm::BinaryOperator* add = llvm::BinaryOperator::create(
     llvm::Instruction::Add, op1, op2, "add", lblk);
-  lops.push_back(add);
+  saveOperand(add,op);
 }
 
 template<> void
@@ -862,7 +1006,7 @@
   op2 = ptr2Value(op2);
   llvm::BinaryOperator* sub = llvm::BinaryOperator::create(
     llvm::Instruction::Sub, op1, op2, "add", lblk);
-  lops.push_back(sub);
+  saveOperand(sub,op);
 }
 
 template<> void
@@ -875,7 +1019,7 @@
   op2 = ptr2Value(op2);
   llvm::BinaryOperator* mul = llvm::BinaryOperator::create(
     llvm::Instruction::Mul, op1, op2, "mul", lblk);
-  lops.push_back(mul);
+  saveOperand(mul,op);
 }
 
 template<> void
@@ -888,7 +1032,7 @@
   op2 = ptr2Value(op2);
   llvm::BinaryOperator* div = llvm::BinaryOperator::create(
     llvm::Instruction::Div, op1, op2, "div", lblk);
-  lops.push_back(div);
+  saveOperand(div,op);
 }
 
 template<> void
@@ -901,7 +1045,7 @@
   op2 = ptr2Value(op2);
   llvm::BinaryOperator* rem = llvm::BinaryOperator::create(
     llvm::Instruction::Rem, op1, op2, "mod", lblk);
-  lops.push_back(rem);
+  saveOperand(rem,op);
 }
 
 template<> void
@@ -914,7 +1058,7 @@
   op2 = ptr2Value(op2);
   llvm::BinaryOperator* band = llvm::BinaryOperator::create(
     llvm::Instruction::And, op1, op2, "band", lblk);
-  lops.push_back(band);
+  saveOperand(band,op);
 }
 
 template<> void
@@ -927,7 +1071,7 @@
   op2 = ptr2Value(op2);
   llvm::BinaryOperator* bor = llvm::BinaryOperator::create(
     llvm::Instruction::Or, op1, op2, "bor", lblk);
-  lops.push_back(bor);
+  saveOperand(bor,op);
 }
 
 template<> void
@@ -940,7 +1084,7 @@
   op2 = ptr2Value(op2);
   llvm::BinaryOperator* Xor = llvm::BinaryOperator::create(
     llvm::Instruction::Xor, op1, op2, "bxor", lblk);
-  lops.push_back(Xor);
+  saveOperand(Xor,op);
 }
 
 template<> void
@@ -954,7 +1098,7 @@
   llvm::BinaryOperator* bor = llvm::BinaryOperator::create(
     llvm::Instruction::Or, op1, op2, "bnor", lblk);
   llvm::BinaryOperator* nor = llvm::BinaryOperator::createNot(bor,"bnor",lblk);
-  lops.push_back(nor);
+  saveOperand(nor,op);
 }
 
 template<> void
@@ -971,7 +1115,7 @@
   op1 = ptr2Value(op1);
   llvm::Value* b1 = toBoolean(op1);
   llvm::BinaryOperator* Not = llvm::BinaryOperator::createNot(b1,"not",lblk);
-  lops.push_back(Not);
+  saveOperand(Not,op);
 }
 
 template<> void
@@ -986,7 +1130,7 @@
   llvm::Value* b2 = toBoolean(op2);
   llvm::BinaryOperator* And = llvm::BinaryOperator::create(
     llvm::Instruction::And, b1, b2, "and", lblk);
-  lops.push_back(And);
+  saveOperand(And,op);
 }
 
 template<> void
@@ -1001,7 +1145,7 @@
   llvm::Value* b2 = toBoolean(op2);
   llvm::BinaryOperator* Or = llvm::BinaryOperator::create(
     llvm::Instruction::Or, b1, b2, "or", lblk);
-  lops.push_back(Or);
+  saveOperand(Or,op);
 }
 
 template<> void
@@ -1017,7 +1161,7 @@
   llvm::BinaryOperator* Or = llvm::BinaryOperator::create(
     llvm::Instruction::Or, b1, b2, "nor", lblk);
   llvm::BinaryOperator* Nor = llvm::BinaryOperator::createNot(Or,"nor",lblk);
-  lops.push_back(Nor);
+  saveOperand(Nor,op);
 }
 
 template<> void
@@ -1032,7 +1176,7 @@
   llvm::Value* b2 = toBoolean(op2);
   llvm::BinaryOperator* Xor = llvm::BinaryOperator::create(
     llvm::Instruction::Xor, b1, b2, "xor", lblk);
-  lops.push_back(Xor);
+  saveOperand(Xor,op);
 }
 
 template<> void
@@ -1045,7 +1189,7 @@
   op2 = ptr2Value(op2);
   llvm::SetCondInst* SCI = 
     new llvm::SetCondInst(llvm::Instruction::SetEQ, op1,op2,"eq",lblk);
-  lops.push_back(SCI);
+  saveOperand(SCI,op);
 }
 
 template<> void
@@ -1058,7 +1202,7 @@
   op2 = ptr2Value(op2);
   llvm::SetCondInst* SCI = 
     new llvm::SetCondInst(llvm::Instruction::SetNE, op1,op2,"ne",lblk);
-  lops.push_back(SCI);
+  saveOperand(SCI,op);
 }
 
 template<> void
@@ -1069,7 +1213,7 @@
   llvm::Value* op1 = lops.back(); lops.pop_back();
   llvm::SetCondInst* SCI = 
     new llvm::SetCondInst(llvm::Instruction::SetLT, op1,op2,"lt",lblk);
-  lops.push_back(SCI);
+  saveOperand(SCI,op);
 }
 
 template<> void
@@ -1080,7 +1224,7 @@
   llvm::Value* op1 = lops.back(); lops.pop_back();
   llvm::SetCondInst* SCI = 
     new llvm::SetCondInst(llvm::Instruction::SetGT, op1,op2,"gt",lblk);
-  lops.push_back(SCI);
+  saveOperand(SCI,op);
 }
 
 template<> void
@@ -1091,7 +1235,7 @@
   llvm::Value* op1 = lops.back(); lops.pop_back();
   llvm::SetCondInst* SCI = 
     new llvm::SetCondInst(llvm::Instruction::SetGE, op1,op2,"ge",lblk);
-  lops.push_back(SCI);
+  saveOperand(SCI,op);
 }
 
 template<> void
@@ -1102,7 +1246,7 @@
   llvm::Value* op1 = lops.back(); lops.pop_back();
   llvm::SetCondInst* SCI = 
     new llvm::SetCondInst(llvm::Instruction::SetLE, op1,op2,"le",lblk);
-  lops.push_back(SCI);
+  saveOperand(SCI,op);
 }
 
 template<> void
@@ -1112,7 +1256,6 @@
   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(op2->getType() == op2->getType());
   hlvmAssert(llvm::isa<llvm::BasicBlock>(op2) == 
              llvm::isa<llvm::BasicBlock>(op3));
 
@@ -1145,40 +1288,42 @@
     // 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());
-    // Create an auto variable to hold the result of the select.
-    llvm::AllocaInst* select_result = new llvm::AllocaInst(
-      /*Ty=*/ results[BB2]->getType(),
-      /*ArraySize=*/ llvm::ConstantUInt::get(llvm::Type::UIntTy,1),
-      /*Name=*/ "select_result",
-      /*InsertAtEnd=*/ lblk
-    );
+    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;
-    // Store the result of the "true" case into the autovar
-    new llvm::StoreInst(results[BB2],select_result,BB2);
+
     // Branch to the exit block
     BB2->setName("select_true");
     new llvm::BranchInst(exit,BB2);
-    // Store the result of the "false" case into the autovar
-    new llvm::StoreInst(results[BB3],select_result,BB3);
+
+    // 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
-    lops.push_back(new llvm::LoadInst(select_result,"select",exit));
+    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.
     hlvmAssert(op2->getType()->isFirstClassType());
     hlvmAssert(op3->getType()->isFirstClassType());
-    lops.push_back(new llvm::SelectInst(op1,op2,op3,"select",lblk));
+    saveOperand(new llvm::SelectInst(op1,op2,op3,"select",lblk),op);
   }
 }
 
@@ -1192,6 +1337,111 @@
 }
 
 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 body of the while loop
+  llvm::BasicBlock* B2 = getBodyBlock(op2,"while_body"); 
+
+  // If there's a result in the while body, get it now
+  llvm::AllocaInst* while_result = getBlockResult(B2,"while_result");
+
+  // Extract the condition value and make sure its in a block
+  llvm::Value* cond = 0;
+  llvm::BasicBlock* B1 = getExpressionBlock(op1,cond,"while_cond");
+
+  // Terminate the current block with a branch to the condition block
+  new llvm::BranchInst(B1,lblk);
+
+  // Terminate the body with a branch back to the condition block
+  new llvm::BranchInst(B1,B2);
+
+  // Create a new block for the exit from the while loop
+  lblk = new llvm::BasicBlock("while_exit",lfunc);
+
+  // Create a conditional branch to either exit or repeat the loop.
+  new llvm::BranchInst(B2,lblk,cond,B1);
+
+  // 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));
+  }
+}
+
+template<> void
+LLVMGeneratorPass::gen(UnlessOp* 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);
+
+  // Terminate the unless body with a branch back to the condition block
+  new llvm::BranchInst(B1,B2);
+
+  // Create a new block for the exit from the while loop
+  lblk = new llvm::BasicBlock("unless_exit",lfunc);
+
+  // Create a conditional branch to either exit or repeat the loop.
+  new llvm::BranchInst(lblk,B2,cond,B1);
+
+  // 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));
+  }
+}
+
+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);
+
+  // 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));
+  }
+}
+
+template<> void
 LLVMGeneratorPass::gen(LoopOp* op)
 {
   hlvmAssert(lops.size() >= 3 && "Too few operands for LoopOp");
@@ -1199,6 +1449,39 @@
   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);
+
+  // 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));
+  }
 }
 
 template<> void
@@ -1260,7 +1543,7 @@
   hlvmAssert(llvm::isa<llvm::Function>(arg));
   llvm::Function* F = const_cast<llvm::Function*>(
       llvm::cast<llvm::Function>(arg));
-  lops.push_back(new llvm::CallInst(F,args,"call_" + hFunc->getName(),lblk));
+  saveOperand(new llvm::CallInst(F,args,"call_" + hFunc->getName(),lblk),co);
 }
 
 template<> void
@@ -1269,15 +1552,15 @@
   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();
-  lops.push_back(new llvm::StoreInst(value,location,lblk));
+  saveOperand(new llvm::StoreInst(value,location,lblk),s);
 }
 
 template<> void
-LLVMGeneratorPass::gen(LoadOp* s)
+LLVMGeneratorPass::gen(LoadOp* l)
 {
   hlvmAssert(lops.size() >= 1 && "Too few operands for LoadOp");
   llvm::Value* location = lops.back(); lops.pop_back();
-  lops.push_back(new llvm::LoadInst(location,"",lblk));
+  saveOperand(new llvm::LoadInst(location,"",lblk),l);
 }
 
 template<> void
@@ -1313,7 +1596,7 @@
   }
   else
     hlvmDeadCode("Referent not a linkable or autovar?");
-  lops.push_back(v);
+  saveOperand(v,r);
 }
 
 template<> void
@@ -1348,7 +1631,7 @@
     hlvmAssert(!"OpenOp parameter is not a pointer");
   llvm::CallInst* ci = new 
     llvm::CallInst(get_hlvm_stream_open(), args, "", lblk);
-  lops.push_back(ci);
+  saveOperand(ci,o);
 }
 
 template<> void
@@ -1363,14 +1646,14 @@
   if (llvm::isa<llvm::PointerType>(arg2->getType()))
     if (llvm::cast<llvm::PointerType>(arg2->getType())->getElementType() ==
         llvm::Type::SByteTy)
-      lops.push_back(
-        new llvm::CallInst(get_hlvm_stream_write_string(), args, "", lblk));
+      saveOperand(
+        new llvm::CallInst(get_hlvm_stream_write_string(), args, "", lblk),o);
   if (arg2->getType() == get_hlvm_text())
-    lops.push_back(
-      new llvm::CallInst(get_hlvm_stream_write_text(), args, "", lblk));
+    saveOperand(
+      new llvm::CallInst(get_hlvm_stream_write_text(), args, "", lblk),o);
   else if (arg2->getType() == get_hlvm_buffer())
-    lops.push_back(
-      new llvm::CallInst(get_hlvm_stream_write_buffer(), args, "",lblk));
+    saveOperand(
+      new llvm::CallInst(get_hlvm_stream_write_buffer(), args, "",lblk),o);
 }
 
 template<> void
@@ -1382,7 +1665,7 @@
   lops.erase(lops.end()-3,lops.end());
   llvm::CallInst* ci = 
     new llvm::CallInst(get_hlvm_stream_read(), args, "", lblk);
-  lops.push_back(ci);
+  saveOperand(ci,o);
 }
 
 template<> void
@@ -1393,7 +1676,7 @@
   args.push_back(lops.back()); lops.pop_back();
   llvm::CallInst* ci = 
     new llvm::CallInst(get_hlvm_stream_close(), args, "", lblk);
-  lops.push_back(ci);
+  saveOperand(ci,o);
 }
 
 void 
@@ -1600,6 +1883,9 @@
       case LessEqualOpID:           gen(llvm::cast<LessEqualOp>(n)); break;
       case SelectOpID:              gen(llvm::cast<SelectOp>(n)); break;
       case SwitchOpID:              gen(llvm::cast<SwitchOp>(n)); break;
+      case WhileOpID:               gen(llvm::cast<WhileOp>(n)); break;
+      case UnlessOpID:              gen(llvm::cast<UnlessOp>(n)); break;
+      case UntilOpID:               gen(llvm::cast<UntilOp>(n)); break;
       case LoopOpID:                gen(llvm::cast<LoopOp>(n)); break;
       case BreakOpID:               gen(llvm::cast<BreakOp>(n)); break;
       case ContinueOpID:            gen(llvm::cast<ContinueOp>(n)); break;

Modified: hlvm/trunk/hlvm/Pass/Validate.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Pass/Validate.cpp?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/Pass/Validate.cpp (original)
+++ hlvm/trunk/hlvm/Pass/Validate.cpp Sat Jul  7 19:02:10 2007
@@ -67,7 +67,7 @@
     inline bool checkUniformContainer(UniformContainerType* T, NodeIDs id);
     inline bool checkDisparateContainer(DisparateContainerType* T, NodeIDs id);
     inline bool checkLinkable(Linkable* LI, NodeIDs id);
-    inline bool checkExpressionBlock(const Block* B);
+    inline bool checkExpressionBlock(const Block* B,bool optional = false);
 
     template <class NodeClass>
     inline void validate(NodeClass* C);
@@ -148,10 +148,6 @@
     error(v,"Bad ID for a Value");
     result = false;
   }
-  if (v->getType() == 0) {
-    error(v,"Value with no type");
-    result = false;
-  }
   return result;
 }
 
@@ -251,14 +247,21 @@
 }
 
 bool 
-ValidateImpl::checkExpressionBlock(const Block* B)
+ValidateImpl::checkExpressionBlock(const Block* B, bool optional)
 {
   bool result = true;
   if (!B->getResult()) {
-    error(B,"Expression block without result");
-    result = false;
+    if (optional) {
+      if (!isa<Block>(B->getParent()->getParent())) {
+        error(B,"Block has no result, but its use expects a result");
+        result = false;
+      }
+    } else {
+      error(B,"Expression block without result");
+      result = false;
+    }
   }
-  if (B->isTerminated()) {
+  if (!optional && B->isTerminated()) {
     error(B,"Expression blocks cannot have terminators");
     result = false;
   }
@@ -548,8 +551,6 @@
       } else if (result) {
         if (n == n->getContainingFunction()->getBlock())
           error(result,"Function's main block has result but no return");
-      } else {
-        error(n,"Block does not contain a result or terminator");
       }
     }
 }
@@ -565,6 +566,10 @@
 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!");
@@ -573,10 +578,19 @@
       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->getType() != SigTy->getResultType())
-            error(n,"Operand does not agree in type with Function result");
+        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");
+          }
+        } else {
+          error(n,"Result operator with no operand");
+        }
       }
     }
   }
@@ -627,9 +641,54 @@
       error(n,"SelectOp requires operands 2 and 3 to both be blocks or "
               "neither be blocks");
     if (isa<Block>(Op2))
-      checkExpressionBlock(cast<Block>(Op2));
+      checkExpressionBlock(cast<Block>(Op2),true);
     if (isa<Block>(Op3))
-      checkExpressionBlock(cast<Block>(Op3));
+      checkExpressionBlock(cast<Block>(Op3),true);
+  }
+}
+
+template<> inline void
+ValidateImpl::validate(WhileOp* n)
+{
+  if (checkOperator(n,WhileOpID,2)) {
+    const Operator* Op1 = n->getOperand(0);
+    const Operator* Op2 = n->getOperand(1);
+    if (!isa<BooleanType>(Op1->getType()))
+      error(n,"WhileOp expects first operand to be type boolean");
+    if (const Block* B1 = dyn_cast<Block>(Op1))
+      checkExpressionBlock(B1);
+    if (const Block* B2 = dyn_cast<Block>(Op2))
+      checkExpressionBlock(B2,true);
+  }
+}
+
+template<> inline void
+ValidateImpl::validate(UnlessOp* n)
+{
+  if (checkOperator(n,UnlessOpID,2)) {
+    const Operator* Op1 = n->getOperand(0);
+    const Operator* Op2 = n->getOperand(1);
+    if (!isa<BooleanType>(Op1->getType()))
+      error(n,"WhileOp expects first operand to be type boolean");
+    if (const Block* B1 = dyn_cast<Block>(Op1))
+      checkExpressionBlock(B1);
+    if (const Block* B2 = dyn_cast<Block>(Op2))
+      checkExpressionBlock(B2,true);
+  }
+}
+
+template<> inline void
+ValidateImpl::validate(UntilOp* n)
+{
+  if (checkOperator(n,UntilOpID,2)) {
+    const Operator* Op1 = n->getOperand(0);
+    const Operator* Op2 = n->getOperand(1);
+    if (!isa<BooleanType>(Op2->getType()))
+      error(n,"WhileOp expects second operand to be type boolean");
+    if (const Block* B1 = dyn_cast<Block>(Op1))
+      checkExpressionBlock(B1,true);
+    if (const Block* B2 = dyn_cast<Block>(Op2))
+      checkExpressionBlock(B2);
   }
 }
 
@@ -642,14 +701,17 @@
     const Operator* Op3 = n->getOperand(2);
     const Type* Ty1 = Op1->getType();
     const Type* Ty3 = Op3->getType();
-    if (!isa<BooleanType>(Ty1) && !isa<VoidType>(Ty1))
-      error(n,"LoopOp expects first operand to be type boolean or void");
-    if (!isa<BooleanType>(Ty3) && !isa<VoidType>(Ty3))
-      error(n,"LoopOp expects third operand to be type boolean or void");
+    if (!isa<BooleanType>(Ty1))
+      error(n,"LoopOp expects first operand to be type boolean");
+    if (!isa<BooleanType>(Ty3))
+      error(n,"LoopOp expects third operand to be type boolean");
     if (isa<Block>(Op1))
       checkExpressionBlock(cast<Block>(Op1));
     if (isa<Block>(Op3))
       checkExpressionBlock(cast<Block>(Op3));
+    if (const Block* B = dyn_cast<Block>(Op2))
+      checkExpressionBlock(B,true);
+
   }
 }
 
@@ -1346,6 +1408,9 @@
     case ContinueOpID:           validate(cast<ContinueOp>(n)); break;
     case BreakOpID:              validate(cast<BreakOp>(n)); break;
     case SelectOpID:             validate(cast<SelectOp>(n)); break;
+    case WhileOpID:              validate(cast<WhileOp>(n)); break;
+    case UnlessOpID:             validate(cast<UnlessOp>(n)); break;
+    case UntilOpID:              validate(cast<UntilOp>(n)); break;
     case LoopOpID:               validate(cast<LoopOp>(n)); break;
     case SwitchOpID:             validate(cast<SwitchOp>(n)); break;
     case LoadOpID:               validate(cast<LoadOp>(n)); break;

Modified: hlvm/trunk/hlvm/Reader/HLVM.rng
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Reader/HLVM.rng?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/Reader/HLVM.rng (original)
+++ hlvm/trunk/hlvm/Reader/HLVM.rng Sat Jul  7 19:02:10 2007
@@ -1049,6 +1049,9 @@
     <choice>
       <ref name="select.elem"/>
       <ref name="switch.elem"/>
+      <ref name="while.elem"/>
+      <ref name="unless.elem"/>
+      <ref name="until.elem"/>
       <ref name="loop.elem"/>
       <ref name="break.elem"/>
       <ref name="continue.elem"/>
@@ -1079,6 +1082,30 @@
     </element>
   </define>
 
+  <define name="while.elem">
+    <element name="while">
+      <ref name="Documentation.pat"/>
+      <ref name="Operators.pat"/>  <!-- Pre-Loop Test -->
+      <ref name="Operators.pat"/>  <!-- Loop Body -->
+    </element>
+  </define>
+
+  <define name="unless.elem">
+    <element name="unless">
+      <ref name="Documentation.pat"/>
+      <ref name="Operators.pat"/>  <!-- Pre-Loop Test -->
+      <ref name="Operators.pat"/>  <!-- Loop Body -->
+    </element>
+  </define>
+
+  <define name="until.elem">
+    <element name="until">
+      <ref name="Documentation.pat"/>
+      <ref name="Operators.pat"/>  <!-- Loop Body -->
+      <ref name="Operators.pat"/>  <!-- Post-Loop Test -->
+    </element>
+  </define>
+
   <define name="loop.elem">
     <element name="loop">
       <ref name="Documentation.pat"/>

Modified: hlvm/trunk/hlvm/Reader/XMLReader.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Reader/XMLReader.cpp?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/Reader/XMLReader.cpp (original)
+++ hlvm/trunk/hlvm/Reader/XMLReader.cpp Sat Jul  7 19:02:10 2007
@@ -1099,6 +1099,9 @@
       case TKN_le:           op = parseBinaryOp<LessEqualOp>(cur); break;
       case TKN_select:       op = parseTernaryOp<SelectOp>(cur); break;
       case TKN_switch:       op = parseMultiOp<SwitchOp>(cur); break;
+      case TKN_while:        op = parseBinaryOp<WhileOp>(cur); break;
+      case TKN_unless:       op = parseBinaryOp<UnlessOp>(cur); break;
+      case TKN_until:        op = parseBinaryOp<UntilOp>(cur); break;
       case TKN_loop:         op = parseTernaryOp<LoopOp>(cur); break;
       case TKN_break:        op = parseNilaryOp<BreakOp>(cur); break;
       case TKN_continue:     op = parseNilaryOp<ContinueOp>(cur); break;

Modified: hlvm/trunk/hlvm/Writer/XMLWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/hlvm/Writer/XMLWriter.cpp?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/hlvm/Writer/XMLWriter.cpp (original)
+++ hlvm/trunk/hlvm/Writer/XMLWriter.cpp Sat Jul  7 19:02:10 2007
@@ -693,6 +693,27 @@
 }
 
 template<> void
+XMLWriterImpl::WriterPass::put(WhileOp* op) 
+{
+  startElement("while");
+  putDoc(op);
+}
+
+template<> void
+XMLWriterImpl::WriterPass::put(UnlessOp* op) 
+{
+  startElement("unless");
+  putDoc(op);
+}
+
+template<> void
+XMLWriterImpl::WriterPass::put(UntilOp* op) 
+{
+  startElement("until");
+  putDoc(op);
+}
+
+template<> void
 XMLWriterImpl::WriterPass::put(LoopOp* op) 
 {
   startElement("loop");
@@ -855,6 +876,9 @@
       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;
+      case UnlessOpID:           put(cast<UnlessOp>(n)); break;
+      case UntilOpID:            put(cast<UntilOp>(n)); break;
       case LoopOpID:             put(cast<LoopOp>(n)); break;
       case BreakOpID:            put(cast<BreakOp>(n)); break;
       case ContinueOpID:         put(cast<ContinueOp>(n)); break;

Added: hlvm/trunk/test/invalid/funcresult.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/invalid/funcresult.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/invalid/funcresult.hlx (added)
+++ hlvm/trunk/test/invalid/funcresult.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,16 @@
+<?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/xml2xml/funcresult.hlx">
+  <bundle id="funcresult">
+    <constant id="1" type="u32">
+      <dec>1</dec>
+    </constant>
+    <program id="funcresult">
+      <block>
+        <result>
+          <ref id="1"/>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Modified: hlvm/trunk/test/return0/arithmetic.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/arithmetic.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/return0/arithmetic.hlx (original)
+++ hlvm/trunk/test/return0/arithmetic.hlx Sat Jul  7 19:02:10 2007
@@ -1,5 +1,5 @@
 <?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/xml2xml/arithmetic.hlx">
+<hlvm xmlns="http://hlvm.org/src/hlvm/Reader/XML/HLVM.rng" pubid="http://hlvm.org/src/hlvm/test/return0/arithmetic.hlx">
   <bundle id="arithmetic">
     <constant id="42" type="s32"><dec>42</dec></constant>
     <constant id="7" type="s32"><dec>7</dec></constant>

Modified: hlvm/trunk/test/return0/bitwise.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/bitwise.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/return0/bitwise.hlx (original)
+++ hlvm/trunk/test/return0/bitwise.hlx Sat Jul  7 19:02:10 2007
@@ -1,5 +1,5 @@
 <?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/xml2xml/bitwise.hlx">
+<hlvm xmlns="http://hlvm.org/src/hlvm/Reader/XML/HLVM.rng" pubid="http://hlvm.org/src/hlvm/test/return0/bitwise.hlx">
   <bundle id="bitwise">
     <constant id="0f0f0f0f" type="s32"><hex>0f0f0f0f</hex></constant>
     <constant id="08080808" type="s32"><hex>08080808</hex></constant>

Modified: hlvm/trunk/test/return0/boolean.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/boolean.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/return0/boolean.hlx (original)
+++ hlvm/trunk/test/return0/boolean.hlx Sat Jul  7 19:02:10 2007
@@ -1,5 +1,5 @@
 <?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/xml2xml/boolean.hlx">
+<hlvm xmlns="http://hlvm.org/src/hlvm/Reader/XML/HLVM.rng" pubid="http://hlvm.org/src/hlvm/test/return0/boolean.hlx">
   <bundle id="boolean">
     <constant id="true" type="bool"><true/></constant>
     <constant id="false" type="bool"><false/></constant>

Modified: hlvm/trunk/test/return0/call.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/call.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/return0/call.hlx (original)
+++ hlvm/trunk/test/return0/call.hlx Sat Jul  7 19:02:10 2007
@@ -1,5 +1,5 @@
 <?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/xml2xml/call.hlx">
+<hlvm xmlns="http://hlvm.org/src/hlvm/Reader/XML/HLVM.rng" pubid="http://hlvm.org/src/hlvm/test/return0/call.hlx">
   <bundle id="call">
     <constant id="zero" type="s32"><dec>0</dec></constant>
     <signature id="zero_func" result="s32"/>

Modified: hlvm/trunk/test/return0/complement.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/complement.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/return0/complement.hlx (original)
+++ hlvm/trunk/test/return0/complement.hlx Sat Jul  7 19:02:10 2007
@@ -1,5 +1,5 @@
 <?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/xml2xml/complement.hlx">
+<hlvm xmlns="http://hlvm.org/src/hlvm/Reader/XML/HLVM.rng" pubid="http://hlvm.org/src/hlvm/test/return0/complement.hlx">
   <bundle id="complement">
     <program id="complement">
       <block>

Added: hlvm/trunk/test/return0/loop.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/loop.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/return0/loop.hlx (added)
+++ hlvm/trunk/test/return0/loop.hlx Sat Jul  7 19:02:10 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/loop.hlx">
+  <bundle id="loop">
+    <constant id="0" type="s32">
+      <dec>0</dec>
+    </constant>
+    <constant id="1" type="s32">
+      <dec>1</dec>
+    </constant>
+    <program id="loop">
+      <block>
+        <result>
+          <loop>
+            <ne>
+              <ref id="1"/>
+              <ref id="0"/>
+            </ne>
+            <block><result><ref id="0"/></result></block>
+            <eq>
+              <ref id="1"/>
+              <ref id="0"/>
+            </eq>
+          </loop>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Added: hlvm/trunk/test/return0/noresult.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/noresult.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/return0/noresult.hlx (added)
+++ hlvm/trunk/test/return0/noresult.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,27 @@
+<?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/noresult.hlx">
+  <bundle id="noresult">
+    <constant id="0" type="s32">
+      <dec>0</dec>
+    </constant>
+    <constant id="1" type="s32">
+      <dec>1</dec>
+    </constant>
+    <program id="noresult">
+      <block>
+        <select>
+          <ne>
+            <ref id="1"/>
+            <ref id="0"/>
+          </ne>
+          <block><ref id="0"/></block>
+          <block><ref id="1"/></block>
+        </select>
+        <result>
+          <ref id="0"/>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Added: hlvm/trunk/test/return0/resultoverride.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/resultoverride.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/return0/resultoverride.hlx (added)
+++ hlvm/trunk/test/return0/resultoverride.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,18 @@
+<?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/resultoverride.hlx">
+  <bundle id="resultoverride">
+    <constant id="0" type="s32"><dec>0</dec></constant>
+    <constant id="1" type="s32"><dec>1</dec></constant>
+    <program id="resultoverride">
+      <block>
+        <result>
+          <ref id="1"/>
+        </result>
+        <result>
+          <ref id="0"/>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Modified: hlvm/trunk/test/return0/return0.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/return0.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/return0/return0.hlx (original)
+++ hlvm/trunk/test/return0/return0.hlx Sat Jul  7 19:02:10 2007
@@ -1,5 +1,5 @@
 <?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/xml2xml/return0.hlx">
+<hlvm xmlns="http://hlvm.org/src/hlvm/Reader/XML/HLVM.rng" pubid="http://hlvm.org/src/hlvm/test/return0/return0.hlx">
   <bundle id="return0">
     <constant id="zero" type="s32"><dec>0</dec></constant>
     <program id="return0">

Modified: hlvm/trunk/test/return0/select.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/select.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/return0/select.hlx (original)
+++ hlvm/trunk/test/return0/select.hlx Sat Jul  7 19:02:10 2007
@@ -1,5 +1,5 @@
 <?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/xml2xml/select.hlx">
+<hlvm xmlns="http://hlvm.org/src/hlvm/Reader/XML/HLVM.rng" pubid="http://hlvm.org/src/hlvm/test/return0/select.hlx">
   <bundle id="select">
     <constant id="0" type="s32"><dec>0</dec></constant>
     <constant id="21" type="s32"><dec>21</dec></constant>

Added: hlvm/trunk/test/return0/unless.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/unless.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/return0/unless.hlx (added)
+++ hlvm/trunk/test/return0/unless.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,25 @@
+<?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/unless.hlx">
+  <bundle id="unless">
+    <constant id="0" type="s32">
+      <dec>0</dec>
+    </constant>
+    <constant id="1" type="s32">
+      <dec>1</dec>
+    </constant>
+    <program id="unless">
+      <block>
+        <result>
+          <unless>
+            <ne>
+              <ref id="1"/>
+              <ref id="0"/>
+            </ne>
+            <block><result><ref id="0"/></result></block>
+          </unless>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Added: hlvm/trunk/test/return0/until.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/until.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/return0/until.hlx (added)
+++ hlvm/trunk/test/return0/until.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,25 @@
+<?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/until.hlx">
+  <bundle id="until">
+    <constant id="0" type="s32">
+      <dec>0</dec>
+    </constant>
+    <constant id="1" type="s32">
+      <dec>1</dec>
+    </constant>
+    <program id="until">
+      <block>
+        <result>
+          <until>
+            <block><result><ref id="0"/></result></block>
+            <eq>
+              <ref id="1"/>
+              <ref id="0"/>
+            </eq>
+          </until>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Added: hlvm/trunk/test/return0/unused.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/unused.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/return0/unused.hlx (added)
+++ hlvm/trunk/test/return0/unused.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,27 @@
+<?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/unused.hlx">
+  <bundle id="unused">
+    <constant id="0" type="s32">
+      <dec>0</dec>
+    </constant>
+    <constant id="1" type="s32">
+      <dec>1</dec>
+    </constant>
+    <program id="unused">
+      <block>
+        <select>
+          <ne>
+            <ref id="1"/>
+            <ref id="0"/>
+          </ne>
+          <block><result><ref id="0"/></result></block>
+          <block><result><ref id="1"/></result></block>
+        </select>
+        <result>
+          <ref id="0"/>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Added: hlvm/trunk/test/return0/while.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/return0/while.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/return0/while.hlx (added)
+++ hlvm/trunk/test/return0/while.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,25 @@
+<?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/while.hlx">
+  <bundle id="while">
+    <constant id="0" type="s32">
+      <dec>0</dec>
+    </constant>
+    <constant id="1" type="s32">
+      <dec>1</dec>
+    </constant>
+    <program id="while">
+      <block>
+        <result>
+          <while>
+            <eq>
+              <ref id="1"/>
+              <ref id="0"/>
+            </eq>
+            <block><result><ref id="0"/></result></block>
+          </while>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Modified: hlvm/trunk/test/xml2xml/break.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/xml2xml/break.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/xml2xml/break.hlx (original)
+++ hlvm/trunk/test/xml2xml/break.hlx Sat Jul  7 19:02:10 2007
@@ -1,17 +1,20 @@
 <?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/xml2xml/return.hlx">
   <bundle id="return">
+    <constant id="true" type="bool">
+      <true/>
+    </constant>
     <constant id="result" type="s32">
       <dec>0</dec>
     </constant>
     <program id="return">
       <block>
         <loop>
-          <noop/>
+          <ref id="true"/>
           <block>
             <break/>
           </block>
-          <noop/>
+          <ref id="true"/>
         </loop>
         <result>
           <ref id="result"/>

Modified: hlvm/trunk/test/xml2xml/continue.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/xml2xml/continue.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/xml2xml/continue.hlx (original)
+++ hlvm/trunk/test/xml2xml/continue.hlx Sat Jul  7 19:02:10 2007
@@ -1,17 +1,20 @@
 <?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/xml2xml/return.hlx">
   <bundle id="return">
+    <constant id="true" type="bool">
+      <true/>
+    </constant>
     <constant id="result" type="s32">
       <dec>0</dec>
     </constant>
     <program id="return">
       <block>
         <loop>
-          <noop/>
+          <ref id="true"/>
           <block>
             <continue/>
           </block>
-          <noop/>
+          <ref id="true"/>
         </loop>
         <result>
           <ref id="result"/>

Modified: hlvm/trunk/test/xml2xml/loop.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/xml2xml/loop.hlx?rev=38306&r1=38305&r2=38306&view=diff

==============================================================================
--- hlvm/trunk/test/xml2xml/loop.hlx (original)
+++ hlvm/trunk/test/xml2xml/loop.hlx Sat Jul  7 19:02:10 2007
@@ -1,6 +1,9 @@
 <?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/xml2xml/loop.hlx">
   <bundle id="loop">
+    <constant id="true" type="bool">
+      <true/>
+    </constant>
     <constant id="0" type="s32">
       <dec>0</dec>
     </constant>
@@ -16,7 +19,7 @@
               <ref id="0"/>
             </ne>
             <ref id="0"/>
-            <noop/>
+            <ref id="true"/>
           </loop>
         </result>
         <ret/>

Added: hlvm/trunk/test/xml2xml/unless.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/xml2xml/unless.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/xml2xml/unless.hlx (added)
+++ hlvm/trunk/test/xml2xml/unless.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,26 @@
+<?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/xml2xml/unless.hlx">
+  <bundle id="unless">
+    <constant id="0" type="s32">
+      <dec>0</dec>
+    </constant>
+    <constant id="1" type="s32">
+      <dec>1</dec>
+    </constant>
+    <program id="unless">
+      <block>
+        <unless>
+          <ne>
+            <ref id="1"/>
+            <ref id="0"/>
+          </ne>
+          <ref id="0"/>
+        </unless>
+        <result>
+          <ref id="0"/>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Added: hlvm/trunk/test/xml2xml/until.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/xml2xml/until.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/xml2xml/until.hlx (added)
+++ hlvm/trunk/test/xml2xml/until.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,26 @@
+<?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/xml2xml/until.hlx">
+  <bundle id="until">
+    <constant id="0" type="s32">
+      <dec>0</dec>
+    </constant>
+    <constant id="1" type="s32">
+      <dec>1</dec>
+    </constant>
+    <program id="until">
+      <block>
+        <until>
+          <ref id="0"/>
+          <ne>
+            <ref id="1"/>
+            <ref id="0"/>
+          </ne>
+        </until>
+        <result>
+          <ref id="0"/>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>

Added: hlvm/trunk/test/xml2xml/while.hlx
URL: http://llvm.org/viewvc/llvm-project/hlvm/trunk/test/xml2xml/while.hlx?rev=38306&view=auto

==============================================================================
--- hlvm/trunk/test/xml2xml/while.hlx (added)
+++ hlvm/trunk/test/xml2xml/while.hlx Sat Jul  7 19:02:10 2007
@@ -0,0 +1,26 @@
+<?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/xml2xml/while.hlx">
+  <bundle id="while">
+    <constant id="0" type="s32">
+      <dec>0</dec>
+    </constant>
+    <constant id="1" type="s32">
+      <dec>1</dec>
+    </constant>
+    <program id="while">
+      <block>
+        <while>
+          <ne>
+            <ref id="1"/>
+            <ref id="0"/>
+          </ne>
+          <ref id="0"/>
+        </while>
+        <result>
+          <ref id="0"/>
+        </result>
+        <ret/>
+      </block>
+    </program>
+  </bundle>
+</hlvm>





More information about the llvm-commits mailing list