For PR411:
[oota-llvm.git] / lib / AsmParser / llvmAsmParser.y
index 84e064ea5c7a6bfdd1ff99cfc5d1b4d2fb75f70b..67d20fed804e9151416989147969baa2e8607b8e 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/Instructions.h"
 #include "llvm/Module.h"
 #include "llvm/SymbolTable.h"
+#include "llvm/Assembly/AutoUpgrade.h"
 #include "llvm/Support/GetElementPtrTypeIterator.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/MathExtras.h"
@@ -50,7 +51,8 @@ static Module *ParserResult;
 
 static bool ObsoleteVarArgs;
 static bool NewVarArgs;
-static BasicBlock* CurBB;
+static BasicBlock *CurBB;
+static GlobalVariable *CurGV;
 
 
 // This contains info used when building the body of a function.  It is
@@ -103,12 +105,16 @@ static struct PerModuleInfo {
       ThrowException(UndefinedReferences);
     }
 
+    // Rename any overloaded intrinsic functions.
+    for (Module::iterator FI = CurrentModule->begin(), FE =
+         CurrentModule->end(); FI != FE; ++FI)
+      UpgradeIntrinsicFunction(&(*FI));
+
     Values.clear();         // Clear out function local definitions
     Types.clear();
     CurrentModule = 0;
   }
 
-
   // GetForwardRefForGlobal - Check to see if there is a forward reference
   // for this global.  If so, remove it from the GlobalRefs map and return it.
   // If not, just return null.
@@ -302,6 +308,9 @@ static Value *getValNonImprovising(const Type *Ty, const ValID &D) {
   case ValID::ConstUndefVal:      // Is it an undef value?
     return UndefValue::get(Ty);
 
+  case ValID::ConstZeroVal:      // Is it a zero value?
+    return Constant::getNullValue(Ty);
+    
   case ValID::ConstantVal:       // Fully resolved constant?
     if (D.ConstantValue->getType() != Ty)
       ThrowException("Constant expression type different from required type!");
@@ -515,12 +524,10 @@ static void setValueName(Value *V, char *NameStr) {
 
 /// ParseGlobalVariable - Handle parsing of a global.  If Initializer is null,
 /// this is a declaration, otherwise it is a definition.
-static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
-                                bool isConstantGlobal, const Type *Ty,
-                                Constant *Initializer, unsigned Align) {
-  if (Align != 0 && !isPowerOf2_32(Align))
-    ThrowException("Global alignment must be a power of two!");
-  
+static GlobalVariable *
+ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
+                    bool isConstantGlobal, const Type *Ty,
+                    Constant *Initializer) {
   if (isa<FunctionType>(Ty))
     ThrowException("Cannot declare global vars of function type!");
 
@@ -550,9 +557,8 @@ static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
     GV->setInitializer(Initializer);
     GV->setLinkage(Linkage);
     GV->setConstant(isConstantGlobal);
-    GV->setAlignment(Align);
     InsertValue(GV, CurModule.Values);
-    return;
+    return GV;
   }
 
   // If this global has a name, check to see if there is already a definition
@@ -577,8 +583,7 @@ static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
         if (isConstantGlobal)
           EGV->setConstant(true);
         EGV->setLinkage(Linkage);
-        EGV->setAlignment(Align);
-        return;
+        return EGV;
       }
 
       ThrowException("Redefinition of global variable named '" + Name +
@@ -590,8 +595,8 @@ static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
   GlobalVariable *GV =
     new GlobalVariable(Ty, isConstantGlobal, Linkage, Initializer, Name,
                        CurModule.CurrentModule);
-  GV->setAlignment(Align);
   InsertValue(GV, CurModule.Values);
+  return GV;
 }
 
 // setTypeName - Set the specified type to the name given.  The name may be
@@ -956,9 +961,10 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 %token <StrVal> VAR_ID LABELSTR STRINGCONSTANT
 %type  <StrVal> Name OptName OptAssign
 %type  <UIntVal> OptAlign OptCAlign
+%type <StrVal> OptSection SectionString
 
 %token IMPLEMENTATION ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK
-%token DECLARE GLOBAL CONSTANT VOLATILE
+%token DECLARE GLOBAL CONSTANT SECTION VOLATILE
 %token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK  APPENDING
 %token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG ALIGN
 %token DEPLIBS CALL TAIL
@@ -978,7 +984,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 
 // Other Operators
 %type  <OtherOpVal> ShiftOps
-%token <OtherOpVal> PHI_TOK CAST SELECT SHL SHR VAARG
+%token <OtherOpVal> PHI_TOK CAST SELECT SHL SHR VAARG EXTRACTELEMENT
 %token VAARG_old VANEXT_old //OBSOLETE
 
 
@@ -1045,9 +1051,43 @@ OptCallingConv : /*empty*/      { $$ = CallingConv::C; } |
 // OptAlign/OptCAlign - An optional alignment, and an optional alignment with
 // a comma before it.
 OptAlign : /*empty*/        { $$ = 0; } |
-           ALIGN EUINT64VAL { $$ = $2; };
+           ALIGN EUINT64VAL {
+  $$ = $2;
+  if ($$ != 0 && !isPowerOf2_32($$))
+    ThrowException("Alignment must be a power of two!");
+};
 OptCAlign : /*empty*/            { $$ = 0; } |
-            ',' ALIGN EUINT64VAL { $$ = $3; };
+            ',' ALIGN EUINT64VAL {
+  $$ = $3;
+  if ($$ != 0 && !isPowerOf2_32($$))
+    ThrowException("Alignment must be a power of two!");
+};
+
+
+SectionString : SECTION STRINGCONSTANT {
+  for (unsigned i = 0, e = strlen($2); i != e; ++i)
+    if ($2[i] == '"' || $2[i] == '\\')
+      ThrowException("Invalid character in section name!");
+  $$ = $2;
+};
+
+OptSection : /*empty*/ { $$ = 0; } |
+             SectionString { $$ = $1; };
+
+// GlobalVarAttributes - Used to pass the attributes string on a global.  CurGV
+// is set to be the global we are processing.
+//
+GlobalVarAttributes : /* empty */ {} |
+                     ',' GlobalVarAttribute GlobalVarAttributes {};
+GlobalVarAttribute : SectionString {
+    CurGV->setSection($1);
+    free($1);
+  } 
+  | ALIGN EUINT64VAL {
+    if ($2 != 0 && !isPowerOf2_32($2))
+      ThrowException("Alignment must be a power of two!");
+    CurGV->setAlignment($2);
+  };
 
 //===----------------------------------------------------------------------===//
 // Types includes all predefined types... except void, because it can only be
@@ -1466,8 +1506,11 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
   | LogicalOps '(' ConstVal ',' ConstVal ')' {
     if ($3->getType() != $5->getType())
       ThrowException("Logical operator types must match!");
-    if (!$3->getType()->isIntegral())
-      ThrowException("Logical operands must have integral types!");
+    if (!$3->getType()->isIntegral()) {
+      if (!isa<PackedType>($3->getType()) || 
+          !cast<PackedType>($3->getType())->getElementType()->isIntegral())
+        ThrowException("Logical operator requires integral operands!");
+    }
     $$ = ConstantExpr::get($1, $3, $5);
   }
   | SetCondOps '(' ConstVal ',' ConstVal ')' {
@@ -1481,9 +1524,16 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
     if (!$3->getType()->isInteger())
       ThrowException("Shift constant expression requires integer operand!");
     $$ = ConstantExpr::get($1, $3, $5);
+  }
+  | EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' {
+        if (!isa<PackedType>($3->getType()))
+      ThrowException("First operand of extractelement must be "
+                     "packed type!");
+    if ($5->getType() != Type::UIntTy)
+      ThrowException("Second operand of extractelement must be uint!");
+    $$ = ConstantExpr::getExtractElement($3, $5);
   };
 
-
 // ConstVector - A list of comma separated constants.
 ConstVector : ConstVector ',' ConstVal {
     ($$ = $1)->push_back($3);
@@ -1557,13 +1607,18 @@ ConstPool : ConstPool OptAssign TYPE TypesV {
   }
   | ConstPool FunctionProto {       // Function prototypes can be in const pool
   }
-  | ConstPool OptAssign OptLinkage GlobalType ConstVal OptCAlign {
+  | ConstPool OptAssign OptLinkage GlobalType ConstVal {
     if ($5 == 0) ThrowException("Global value initializer is not a constant!");
-    ParseGlobalVariable($2, $3, $4, $5->getType(), $5, $6);
+    CurGV = ParseGlobalVariable($2, $3, $4, $5->getType(), $5);
+                                                       } GlobalVarAttributes {
+    CurGV = 0;
   }
-  | ConstPool OptAssign EXTERNAL GlobalType Types OptCAlign {
-    ParseGlobalVariable($2, GlobalValue::ExternalLinkage, $4, *$5, 0, $6);
+  | ConstPool OptAssign EXTERNAL GlobalType Types {
+    CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage,
+                                             $4, *$5, 0);
     delete $5;
+                                                   } GlobalVarAttributes {
+    CurGV = 0;
   }
   | ConstPool TARGET TargetDefinition { 
   }
@@ -1647,15 +1702,14 @@ ArgList : ArgListH {
     $$ = 0;
   };
 
-FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' OptAlign {
+FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' 
+                  OptSection OptAlign {
   UnEscapeLexed($3);
   std::string FunctionName($3);
   free($3);  // Free strdup'd memory!
   
   if (!(*$2)->isFirstClassType() && *$2 != Type::VoidTy)
     ThrowException("LLVM functions cannot return aggregate types!");
-  if ($7 != 0 && !isPowerOf2_32($7))
-    ThrowException("Function alignment must be a power of two!");
 
   std::vector<const Type*> ParamTypeList;
   if ($5) {   // If there are arguments...
@@ -1707,7 +1761,11 @@ FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' OptAlign {
 
   CurFun.FunctionStart(Fn);
   Fn->setCallingConv($1);
-  Fn->setAlignment($7);
+  Fn->setAlignment($8);
+  if ($7) {
+    Fn->setSection($7);
+    free($7);
+  }
 
   // Add all of the arguments we parsed to the function...
   if ($5) {                     // Is null if empty...
@@ -1776,6 +1834,9 @@ ConstValueRef : ESINT64VAL {    // A reference to a direct constant
   | UNDEF {
     $$ = ValID::createUndef();
   }
+  | ZEROINITIALIZER {     // A vector zero constant.
+    $$ = ValID::createZeroInit();
+  }
   | '<' ConstVector '>' { // Nonempty unsized packed vector
     const Type *ETy = (*$2)[0]->getType();
     int NumElements = $2->size(); 
@@ -2033,8 +2094,11 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     delete $2;
   }
   | LogicalOps Types ValueRef ',' ValueRef {
-    if (!(*$2)->isIntegral())
-      ThrowException("Logical operator requires integral operands!");
+    if (!(*$2)->isIntegral()) {
+      if (!isa<PackedType>($2->get()) ||
+          !cast<PackedType>($2->get())->getElementType()->isIntegral())
+        ThrowException("Logical operator requires integral operands!");
+    }
     $$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5));
     if ($$ == 0)
       ThrowException("binary operator returned null!");
@@ -2129,6 +2193,14 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     $$ = new LoadInst(foo);
     delete $4;
   }
+  | EXTRACTELEMENT ResolvedVal ',' ResolvedVal {
+    if (!isa<PackedType>($2->getType()))
+      ThrowException("First operand of extractelement must be a "
+                     "packed type val!");
+    if ($4->getType() != Type::UIntTy)
+      ThrowException("Second operand of extractelement must be a uint!");
+    $$ = new ExtractElementInst($2, $4);
+  }
   | PHI_TOK PHIList {
     const Type *Ty = $2->front().first->getType();
     if (!Ty->isFirstClassType())
@@ -2222,30 +2294,18 @@ OptVolatile : VOLATILE {
 
 
 MemoryInst : MALLOC Types OptCAlign {
-    if ($3 != 0 && !isPowerOf2_32($3))
-      ThrowException("Alignment amount '" + utostr($3) +
-                     "' is not a power of 2!");
     $$ = new MallocInst(*$2, 0, $3);
     delete $2;
   }
   | MALLOC Types ',' UINT ValueRef OptCAlign {
-    if ($6 != 0 && !isPowerOf2_32($6))
-      ThrowException("Alignment amount '" + utostr($6) +
-                     "' is not a power of 2!");
     $$ = new MallocInst(*$2, getVal($4, $5), $6);
     delete $2;
   }
   | ALLOCA Types OptCAlign {
-    if ($3 != 0 && !isPowerOf2_32($3))
-      ThrowException("Alignment amount '" + utostr($3) +
-                     "' is not a power of 2!");
     $$ = new AllocaInst(*$2, 0, $3);
     delete $2;
   }
   | ALLOCA Types ',' UINT ValueRef OptCAlign {
-    if ($6 != 0 && !isPowerOf2_32($6))
-      ThrowException("Alignment amount '" + utostr($6) +
-                     "' is not a power of 2!");
     $$ = new AllocaInst(*$2, getVal($4, $5), $6);
     delete $2;
   }