Added support for parsing expressions constructed from constant values.
(Major new non-terminal is ConstExpr.)

Add YYERROR_VERBOSE and print additional information on errors.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2894 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index 4b9f36f..c81ac34 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -45,6 +45,8 @@
 #define UR_OUT(X)
 #endif
 
+#define YYERROR_VERBOSE 1
+
 // This contains info used when building the body of a function.  It is
 // destroyed when the function is completed.
 //
@@ -94,7 +96,7 @@
   }
 
 
-  // DeclareNewGlobalValue - Called every type a new GV has been defined.  This
+  // DeclareNewGlobalValue - Called every time a new GV has been defined.  This
   // is used to remove things from the forward declaration map, resolving them
   // to the correct thing as needed.
   //
@@ -108,22 +110,22 @@
       I->first.second.destroy();  // Free string memory if neccesary
       
       // Loop over all of the uses of the GlobalValue.  The only thing they are
-      // allowed to be at this point is ConstantPointerRef's.
+      // allowed to be is ConstantPointerRef's.
       assert(OldGV->use_size() == 1 && "Only one reference should exist!");
       while (!OldGV->use_empty()) {
-	User *U = OldGV->use_back();  // Must be a ConstantPointerRef...
-	ConstantPointerRef *CPPR = cast<ConstantPointerRef>(U);
-	assert(CPPR->getValue() == OldGV && "Something isn't happy");
-	
-	// Change the const pool reference to point to the real global variable
-	// now.  This should drop a use from the OldGV.
-	CPPR->mutateReference(GV);
+        User *U = OldGV->use_back();  // Must be a ConstantPointerRef...
+        ConstantPointerRef *CPR = cast<ConstantPointerRef>(U);
+        assert(CPR->getValue() == OldGV && "Something isn't happy");
+        
+        // Change the const pool reference to point to the real global variable
+        // now.  This should drop a use from the OldGV.
+        CPR->mutateReferences(OldGV, GV);
       }
-    
-      // Remove GV from the module...
+      
+      // Remove OldGV from the module...
       CurrentModule->getGlobalList().remove(OldGV);
       delete OldGV;                        // Delete the old placeholder
-
+      
       // Remove the map entry for the global now that it has been created...
       GlobalRefs.erase(I);
     }
@@ -223,7 +225,7 @@
     return cast<const Type>(N);
   }
   default:
-    ThrowException("Invalid symbol type reference!");
+    ThrowException("Internal parser error: Invalid symbol type reference!");
   }
 
   // If we reached here, we referenced either a symbol that we don't know about
@@ -633,7 +635,7 @@
 %type <BasicBlockVal> BasicBlock InstructionList
 %type <TermInstVal>   BBTerminatorInst
 %type <InstVal>       Inst InstVal MemoryInst
-%type <ConstVal>      ConstVal
+%type <ConstVal>      ConstVal ConstExpr
 %type <ConstVector>   ConstVector
 %type <ArgList>       ArgList ArgListH
 %type <ArgVal>        ArgVal
@@ -687,7 +689,7 @@
 %token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE  // Binary Comarators
 
 // Memory Instructions
-%token <MemoryOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
+%token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
 
 // Other Operators
 %type  <OtherOpVal> ShiftOps
@@ -833,7 +835,6 @@
     $$ = new list<PATypeHolder>();
   };
 
-
 // ConstVal - The various declarations that go into the constant pool.  This
 // includes all forward declarations of types, constants, and functions.
 //
@@ -962,9 +963,40 @@
     GlobalValue *GV = cast<GlobalValue>(V);
     $$ = ConstantPointerRef::get(GV);
     delete $1;            // Free the type handle
+  }
+  | ConstExpr {
+    $$ = $1;
   };
 
 
+ConstExpr: Types CAST ConstVal {
+    ConstantExpr* CPE = ConstantExpr::get($2, $3, $1->get());
+    if (CPE == 0) ThrowException("constant expression builder returned null!");
+    $$ = CPE;
+  }
+  | Types GETELEMENTPTR '(' ConstVal IndexList ')' {
+    ConstantExpr* CPE = ConstantExpr::get($2, $4, *$5, $1->get());
+    if (CPE == 0) ThrowException("constant expression builder returned null!");
+    $$ = CPE;
+  }
+  | Types UnaryOps ConstVal {
+    ConstantExpr* CPE = ConstantExpr::get($2, $3, $1->get());
+    if (CPE == 0) ThrowException("constant expression builder returned null!");
+    $$ = CPE;
+  }
+  | Types BinaryOps ConstVal ',' ConstVal {
+    ConstantExpr* CPE = ConstantExpr::get($2, $3, $5, $1->get());
+    if (CPE == 0) ThrowException("constant expression builder returned null!");
+    $$ = CPE;
+  }
+  | Types ShiftOps ConstVal ',' ConstVal {
+    ConstantExpr* CPE = ConstantExpr::get($2, $3, $5, $1->get());
+    if (CPE == 0) ThrowException("constant expression builder returned null!");
+    $$ = CPE;
+  }
+  ;
+
+
 ConstVal : SIntType EINT64VAL {     // integral constants
     if (!ConstantSInt::isValueValidForType($1, $2))
       ThrowException("Constant value doesn't fit in type!");
@@ -1067,7 +1099,7 @@
     Constant *Initializer = $5;
     if (Initializer == 0)
       ThrowException("Global value initializer is not a constant!");
-	 
+    
     GlobalVariable *GV = new GlobalVariable(Ty, $4, $3, Initializer);
     if (!setValueName(GV, $2)) {   // If not redefining...
       CurModule.CurrentModule->getGlobalList().push_back(GV);
@@ -1249,7 +1281,8 @@
   }
   | NULL_TOK {
     $$ = ValID::createNull();
-  };
+  }
+  ;
 
 // SymbolicValueRef - Reference to one of two ways of symbolically refering to
 // another value.
@@ -1270,9 +1303,11 @@
 // 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 {
     ($$ = $1)->getBasicBlockList().push_back($2);
   }
@@ -1591,6 +1626,13 @@
 
 %%
 int yyerror(const char *ErrorMsg) {
-  ThrowException(string("Parse error: ") + ErrorMsg);
+  string where  = string((CurFilename == "-")? string("<stdin>") : CurFilename)
+                  + ":" + utostr((unsigned) llvmAsmlineno) + ": ";
+  string errMsg = string(ErrorMsg) + string("\n") + where + " while reading ";
+  if (yychar == YYEMPTY)
+    errMsg += "end-of-file.";
+  else
+    errMsg += "token: '" + string(llvmAsmtext, llvmAsmleng) + "'";
+  ThrowException(errMsg);
   return 0;
 }