Use explicit ctor
[oota-llvm.git] / lib / AsmParser / llvmAsmParser.y
index 5eed0ebc57e7d7d1797956554de0f69887068951..ee74367d815969f3ee7f13997c6d412024cb1af9 100644 (file)
@@ -10,6 +10,7 @@
 #include "llvm/Module.h"
 #include "llvm/iTerminators.h"
 #include "llvm/iMemory.h"
+#include "llvm/iOperators.h"
 #include "llvm/iPHINode.h"
 #include "Support/STLExtras.h"
 #include "Support/DepthFirstIterator.h"
@@ -43,6 +44,14 @@ string CurFilename;
 
 #define YYERROR_VERBOSE 1
 
+// HACK ALERT: This variable is used to implement the automatic conversion of
+// load/store instructions with indexes into a load/store + getelementptr pair
+// of instructions.  When this compatiblity "Feature" is removed, this should be
+// too.
+//
+static BasicBlock *CurBB;
+
+
 // This contains info used when building the body of a function.  It is
 // destroyed when the function is completed.
 //
@@ -292,15 +301,11 @@ static Value *getValNonImprovising(const Type *Ty, const ValID &D) {
   // Check to make sure that "Ty" is an integral type, and that our 
   // value will fit into the specified type...
   case ValID::ConstSIntVal:    // Is it a constant pool reference??
-    if (Ty == Type::BoolTy) {  // Special handling for boolean data
-      return ConstantBool::get(D.ConstPool64 != 0);
-    } else {
-      if (!ConstantSInt::isValueValidForType(Ty, D.ConstPool64))
-       ThrowException("Signed integral constant '" +
-                      itostr(D.ConstPool64) + "' is invalid for type '" + 
-                      Ty->getDescription() + "'!");
-      return ConstantSInt::get(Ty, D.ConstPool64);
-    }
+    if (!ConstantSInt::isValueValidForType(Ty, D.ConstPool64))
+      ThrowException("Signed integral constant '" +
+                     itostr(D.ConstPool64) + "' is invalid for type '" + 
+                     Ty->getDescription() + "'!");
+    return ConstantSInt::get(Ty, D.ConstPool64);
 
   case ValID::ConstUIntVal:     // Is it an unsigned const pool reference?
     if (!ConstantUInt::isValueValidForType(Ty, D.UConstPool64)) {
@@ -324,6 +329,11 @@ static Value *getValNonImprovising(const Type *Ty, const ValID &D) {
       ThrowException("Cannot create a a non pointer null!");
     return ConstantPointerNull::get(cast<PointerType>(Ty));
     
+  case ValID::ConstantVal:       // Fully resolved constant?
+    if (D.ConstantValue->getType() != Ty)
+      ThrowException("Constant expression type different from required type!");
+    return D.ConstantValue;
+
   default:
     assert(0 && "Unhandled case!");
     return 0;
@@ -670,13 +680,14 @@ Module *RunVMAsmParser(const string &Filename, FILE *F) {
 
 
 %token IMPLEMENTATION TRUE FALSE BEGINTOK ENDTOK DECLARE GLOBAL CONSTANT UNINIT
-%token TO EXCEPT DOTDOTDOT STRING NULL_TOK CONST INTERNAL OPAQUE NOT
+%token TO EXCEPT DOTDOTDOT NULL_TOK CONST INTERNAL OPAQUE NOT
 
 // Basic Block Terminating Operators 
 %token <TermOpVal> RET BR SWITCH
 
 // Binary Operators 
 %type  <BinaryOpVal> BinaryOps  // all the binary operators
+%type  <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
 %token <BinaryOpVal> ADD SUB MUL DIV REM AND OR XOR
 %token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE  // Binary Comarators
 
@@ -711,8 +722,11 @@ EINT64VAL : EUINT64VAL {
 // Operations that are notably excluded from this list include: 
 // RET, BR, & SWITCH because they end basic blocks and are treated specially.
 //
-BinaryOps : ADD | SUB | MUL | DIV | REM | AND | OR | XOR;
-BinaryOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
+ArithmeticOps: ADD | SUB | MUL | DIV | REM;
+LogicalOps   : AND | OR | XOR;
+SetCondOps   : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
+BinaryOps : ArithmeticOps | LogicalOps | SetCondOps;
+
 ShiftOps  : SHL | SHR;
 
 // These are some types that allow classification if we only want a particular 
@@ -759,7 +773,7 @@ UpRTypes : OPAQUE {
   | PrimType {
     $$ = new PATypeHolder($1);
   };
-UpRTypes : ValueRef {                    // Named types are also simple types...
+UpRTypes : SymbolicValueRef {            // Named types are also simple types...
   $$ = new PATypeHolder(getTypeVal($1));
 };
 
@@ -827,7 +841,10 @@ ArgTypeListI : TypeListI
   };
 
 // ConstVal - The various declarations that go into the constant pool.  This
-// includes all forward declarations of types, constants, and functions.
+// production is used ONLY to represent constants that show up AFTER a 'const',
+// 'constant' or 'global' token at global scope.  Constants that can be inlined
+// into other expressions (such as integers and constexprs) are handled by the
+// ResolvedVal, ValueRef and ConstValueRef productions.
 //
 ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
     const ArrayType *ATy = dyn_cast<const ArrayType>($1->get());
@@ -968,8 +985,11 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
     $$ = ConstantPointerRef::get(GV);
     delete $1;            // Free the type handle
   }
-  | ConstExpr {
-    $$ = $1;
+  | Types ConstExpr {
+    if ($1->get() != $2->getType())
+      ThrowException("Mismatched types for constant expression!");
+    $$ = $2;
+    delete $1;
   };
 
 ConstVal : SIntType EINT64VAL {     // integral constants
@@ -993,49 +1013,39 @@ ConstVal : SIntType EINT64VAL {     // integral constants
   };
 
 
-ConstExpr: Types CAST ConstVal {
-    $$ = ConstantExpr::getCast($3, $1->get());
-    delete $1;
+ConstExpr: CAST '(' ConstVal TO Types ')' {
+    $$ = ConstantExpr::getCast($3, $5->get());
+    delete $5;
   }
-  | Types GETELEMENTPTR '(' ConstVal IndexList ')' {
-    if (!isa<PointerType>($4->getType()))
+  | GETELEMENTPTR '(' ConstVal IndexList ')' {
+    if (!isa<PointerType>($3->getType()))
       ThrowException("GetElementPtr requires a pointer operand!");
 
     const Type *IdxTy =
-      GetElementPtrInst::getIndexedType($4->getType(), *$5, true);
+      GetElementPtrInst::getIndexedType($3->getType(), *$4, true);
     if (!IdxTy)
       ThrowException("Index list invalid for constant getelementptr!");
-    if (PointerType::get(IdxTy) != $1->get())
-      ThrowException("Declared type of constant getelementptr is incorrect!");
 
     vector<Constant*> IdxVec;
-    for (unsigned i = 0, e = $5->size(); i != e; ++i)
-      if (Constant *C = dyn_cast<Constant>((*$5)[i]))
+    for (unsigned i = 0, e = $4->size(); i != e; ++i)
+      if (Constant *C = dyn_cast<Constant>((*$4)[i]))
         IdxVec.push_back(C);
       else
         ThrowException("Indices to constant getelementptr must be constants!");
 
-    delete $5;
+    delete $4;
 
-    $$ = ConstantExpr::getGetElementPtr($4, IdxVec);
-    delete $1;
+    $$ = ConstantExpr::getGetElementPtr($3, IdxVec);
   }
-  | Types BinaryOps ConstVal ',' ConstVal {
+  | BinaryOps '(' ConstVal ',' ConstVal ')' {
     if ($3->getType() != $5->getType())
       ThrowException("Binary operator types must match!");
-    if ($1->get() != $3->getType())
-      ThrowException("Return type of binary constant must match arguments!");
-    $$ = ConstantExpr::get($2, $3, $5);
-    delete $1;
+    $$ = ConstantExpr::get($1, $3, $5);
   }
-  | Types ShiftOps ConstVal ',' ConstVal {
-    if ($1->get() != $3->getType())
-      ThrowException("Return type of shift constant must match argument!");
+  | ShiftOps '(' ConstVal ',' ConstVal ')' {
     if ($5->getType() != Type::UByteTy)
       ThrowException("Shift count for shift constant must be unsigned byte!");
-    
-    $$ = ConstantExpr::get($2, $3, $5);
-    delete $1;
+    $$ = ConstantExpr::get($1, $3, $5);
   };
 
 
@@ -1301,15 +1311,17 @@ ConstValueRef : ESINT64VAL {    // A reference to a direct constant
     $$ = ValID::create($1);
   }
   | TRUE {
-    $$ = ValID::create((int64_t)1);
+    $$ = ValID::create(ConstantBool::True);
   } 
   | FALSE {
-    $$ = ValID::create((int64_t)0);
+    $$ = ValID::create(ConstantBool::False);
   }
   | NULL_TOK {
     $$ = ValID::createNull();
   }
-  ;
+  | ConstExpr {
+    $$ = ValID::create($1);
+  };
 
 // SymbolicValueRef - Reference to one of two ways of symbolically refering to
 // another value.
@@ -1330,9 +1342,6 @@ ValueRef : SymbolicValueRef | ConstValueRef;
 // pool references (for things like: 'ret [2 x int] [ int 12, int 42]')
 ResolvedVal : Types ValueRef {
     $$ = getVal(*$1, $2); delete $1;
-  }
-  | ConstExpr {
-    $$ = $1;
   };
 
 BasicBlockList : BasicBlockList BasicBlock {
@@ -1370,7 +1379,7 @@ InstructionList : InstructionList Inst {
     $$ = $1;
   }
   | /* empty */ {
-    $$ = new BasicBlock();
+    $$ = CurBB = new BasicBlock();
   };
 
 BBTerminatorInst : RET ResolvedVal {              // Return with a result...
@@ -1503,12 +1512,28 @@ ValueRefList : ResolvedVal {    // Used for call statements, and memory insts...
 // ValueRefListE - Just like ValueRefList, except that it may also be empty!
 ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
 
-InstVal : BinaryOps Types ValueRef ',' ValueRef {
+InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
+    if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint())
+      ThrowException("Arithmetic operator requires integer or FP operands!");
+    $$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5));
+    if ($$ == 0)
+      ThrowException("binary operator returned null!");
+    delete $2;
+  }
+  | LogicalOps Types ValueRef ',' ValueRef {
+    if (!(*$2)->isIntegral())
+      ThrowException("Logical operator requires integral operands!");
     $$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5));
     if ($$ == 0)
       ThrowException("binary operator returned null!");
     delete $2;
   }
+  | SetCondOps Types ValueRef ',' ValueRef {
+    $$ = new SetCondInst($1, getVal(*$2, $3), getVal(*$2, $5));
+    if ($$ == 0)
+      ThrowException("binary operator returned null!");
+    delete $2;
+  }
   | NOT ResolvedVal {
     std::cerr << "WARNING: Use of eliminated 'not' instruction:"
               << " Replacing with 'xor'.\n";
@@ -1634,10 +1659,22 @@ MemoryInst : MALLOC Types {
     if (!isa<PointerType>($2->get()))
       ThrowException("Can't load from nonpointer type: " +
                     (*$2)->getDescription());
-    if (LoadInst::getIndexedType(*$2, *$4) == 0)
+    if (GetElementPtrInst::getIndexedType(*$2, *$4) == 0)
       ThrowException("Invalid indices for load instruction!");
 
-    $$ = new LoadInst(getVal(*$2, $3), *$4);
+    Value *Src = getVal(*$2, $3);
+    if (!$4->empty()) {
+      std::cerr << "WARNING: Use of index load instruction:"
+                << " replacing with getelementptr/load pair.\n";
+      // Create a getelementptr hack instruction to do the right thing for
+      // compatibility.
+      //
+      Instruction *I = new GetElementPtrInst(Src, *$4);
+      CurBB->getInstList().push_back(I);
+      Src = I;
+    }
+
+    $$ = new LoadInst(Src);
     delete $4;   // Free the vector...
     delete $2;
   }
@@ -1645,13 +1682,26 @@ MemoryInst : MALLOC Types {
     if (!isa<PointerType>($4->get()))
       ThrowException("Can't store to a nonpointer type: " +
                      (*$4)->getDescription());
-    const Type *ElTy = StoreInst::getIndexedType(*$4, *$6);
+    const Type *ElTy = GetElementPtrInst::getIndexedType(*$4, *$6);
     if (ElTy == 0)
       ThrowException("Can't store into that field list!");
     if (ElTy != $2->getType())
       ThrowException("Can't store '" + $2->getType()->getDescription() +
                      "' into space of type '" + ElTy->getDescription() + "'!");
-    $$ = new StoreInst($2, getVal(*$4, $5), *$6);
+
+    Value *Ptr = getVal(*$4, $5);
+    if (!$6->empty()) {
+      std::cerr << "WARNING: Use of index store instruction:"
+                << " replacing with getelementptr/store pair.\n";
+      // Create a getelementptr hack instruction to do the right thing for
+      // compatibility.
+      //
+      Instruction *I = new GetElementPtrInst(Ptr, *$6);
+      CurBB->getInstList().push_back(I);
+      Ptr = I;
+    }
+
+    $$ = new StoreInst($2, Ptr);
     delete $4; delete $6;
   }
   | GETELEMENTPTR Types ValueRef IndexList {