add a token
[oota-llvm.git] / lib / AsmParser / llvmAsmParser.y
index f59475cd13011c146412103de4b3ad5714bf0f9a..31b286b87edf65ae04f60ca5dd2842131fcff6a6 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/SymbolTable.h"
 #include "llvm/Support/GetElementPtrTypeIterator.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/MathExtras.h"
 #include <algorithm>
 #include <iostream>
 #include <list>
@@ -48,6 +49,7 @@ static Module *ParserResult;
 #define YYERROR_VERBOSE 1
 
 static bool ObsoleteVarArgs;
+static bool NewVarArgs;
 static BasicBlock* CurBB;
 
 
@@ -515,7 +517,11 @@ static void setValueName(Value *V, char *NameStr) {
 /// this is a declaration, otherwise it is a definition.
 static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
                                 bool isConstantGlobal, const Type *Ty,
-                                Constant *Initializer) {
+                                Constant *Initializer, char *Section,
+                                unsigned Align) {
+  if (Align != 0 && !isPowerOf2_32(Align))
+    ThrowException("Global alignment must be a power of two!");
+  
   if (isa<FunctionType>(Ty))
     ThrowException("Cannot declare global vars of function type!");
 
@@ -545,6 +551,11 @@ static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
     GV->setInitializer(Initializer);
     GV->setLinkage(Linkage);
     GV->setConstant(isConstantGlobal);
+    GV->setAlignment(Align);
+    if (Section) {
+      free(Section);
+      GV->setSection(Section);
+    }
     InsertValue(GV, CurModule.Values);
     return;
   }
@@ -571,6 +582,11 @@ static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
         if (isConstantGlobal)
           EGV->setConstant(true);
         EGV->setLinkage(Linkage);
+        EGV->setAlignment(Align);
+        if (Section) {
+          free(Section);
+          EGV->setSection(Section);
+        }
         return;
       }
 
@@ -583,6 +599,11 @@ static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage,
   GlobalVariable *GV =
     new GlobalVariable(Ty, isConstantGlobal, Linkage, Initializer, Name,
                        CurModule.CurrentModule);
+  GV->setAlignment(Align);
+  if (Section) {
+    free(Section);
+    GV->setSection(Section);
+  }
   InsertValue(GV, CurModule.Values);
 }
 
@@ -728,6 +749,7 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
 
   llvmAsmlineno = 1;      // Reset the current line number...
   ObsoleteVarArgs = false;
+  NewVarArgs = false;
 
   CurModule.CurrentModule = M;
   yyparse();       // Parse the file, potentially throwing exception
@@ -735,9 +757,24 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
   Module *Result = ParserResult;
   ParserResult = 0;
 
+  //Not all functions use vaarg, so make a second check for ObsoleteVarArgs
+  {
+    Function* F;
+    if ((F = Result->getNamedFunction("llvm.va_start"))
+        && F->getFunctionType()->getNumParams() == 0)
+      ObsoleteVarArgs = true;
+    if((F = Result->getNamedFunction("llvm.va_copy"))
+       && F->getFunctionType()->getNumParams() == 1)
+      ObsoleteVarArgs = true;
+  }
+
+  if (ObsoleteVarArgs && NewVarArgs)
+    ThrowException("This file is corrupt: it uses both new and old style varargs");
+
   if(ObsoleteVarArgs) {
     if(Function* F = Result->getNamedFunction("llvm.va_start")) {
-      assert(F->arg_size() == 0 && "Obsolete va_start takes 0 argument!");
+      if (F->arg_size() != 0)
+        ThrowException("Obsolete va_start takes 0 argument!");
       
       //foo = va_start()
       // ->
@@ -749,7 +786,7 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
       const Type* ArgTy = F->getFunctionType()->getReturnType();
       const Type* ArgTyPtr = PointerType::get(ArgTy);
       Function* NF = Result->getOrInsertFunction("llvm.va_start", 
-                                                 RetTy, ArgTyPtr, 0);
+                                                 RetTy, ArgTyPtr, (Type *)0);
 
       while (!F->use_empty()) {
         CallInst* CI = cast<CallInst>(F->use_back());
@@ -763,7 +800,9 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
     }
     
     if(Function* F = Result->getNamedFunction("llvm.va_end")) {
-      assert(F->arg_size() == 1 && "Obsolete va_end takes 1 argument!");
+      if(F->arg_size() != 1)
+        ThrowException("Obsolete va_end takes 1 argument!");
+
       //vaend foo
       // ->
       //bar = alloca 1 of typeof(foo)
@@ -772,11 +811,12 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
       const Type* ArgTy = F->getFunctionType()->getParamType(0);
       const Type* ArgTyPtr = PointerType::get(ArgTy);
       Function* NF = Result->getOrInsertFunction("llvm.va_end", 
-                                                 RetTy, ArgTyPtr, 0);
+                                                 RetTy, ArgTyPtr, (Type *)0);
 
       while (!F->use_empty()) {
         CallInst* CI = cast<CallInst>(F->use_back());
         AllocaInst* bar = new AllocaInst(ArgTy, 0, "vaend.fix.1", CI);
+        new StoreInst(CI->getOperand(1), bar, CI);
         new CallInst(NF, bar, "", CI);
         CI->getParent()->getInstList().erase(CI);
       }
@@ -784,24 +824,30 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
     }
 
     if(Function* F = Result->getNamedFunction("llvm.va_copy")) {
-      assert(F->arg_size() == 1 && "Obsolete va_copy takes 1 argument!");
+      if(F->arg_size() != 1)
+        ThrowException("Obsolete va_copy takes 1 argument!");
       //foo = vacopy(bar)
       // ->
       //a = alloca 1 of typeof(foo)
-      //vacopy(a, bar)
+      //b = alloca 1 of typeof(foo)
+      //store bar -> b
+      //vacopy(a, b)
       //foo = load a
       
       const Type* RetTy = Type::getPrimitiveType(Type::VoidTyID);
       const Type* ArgTy = F->getFunctionType()->getReturnType();
       const Type* ArgTyPtr = PointerType::get(ArgTy);
       Function* NF = Result->getOrInsertFunction("llvm.va_copy", 
-                                                 RetTy, ArgTyPtr, ArgTy, 0);
+                                                 RetTy, ArgTyPtr, ArgTyPtr,
+                                                 (Type *)0);
 
       while (!F->use_empty()) {
         CallInst* CI = cast<CallInst>(F->use_back());
         AllocaInst* a = new AllocaInst(ArgTy, 0, "vacopy.fix.1", CI);
-        new CallInst(NF, a, CI->getOperand(1), "", CI);
-        Value* foo = new LoadInst(a, "vacopy.fix.2", CI);
+        AllocaInst* b = new AllocaInst(ArgTy, 0, "vacopy.fix.2", CI);
+        new StoreInst(CI->getOperand(1), b, CI);
+        new CallInst(NF, a, b, "", CI);
+        Value* foo = new LoadInst(a, "vacopy.fix.3", CI);
         CI->replaceAllUsesWith(foo);
         CI->getParent()->getInstList().erase(CI);
       }
@@ -922,12 +968,13 @@ 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 OptCSection 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
+%token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG ALIGN
 %token DEPLIBS CALL TAIL
 %token CC_TOK CCC_TOK FASTCC_TOK COLDCC_TOK
 %type <UIntVal> OptCallingConv
@@ -1009,6 +1056,26 @@ OptCallingConv : /*empty*/      { $$ = CallingConv::C; } |
                    $$ = $2;
                  };
 
+// OptAlign/OptCAlign - An optional alignment, and an optional alignment with
+// a comma before it.
+OptAlign : /*empty*/        { $$ = 0; } |
+           ALIGN EUINT64VAL { $$ = $2; };
+OptCAlign : /*empty*/            { $$ = 0; } |
+            ',' ALIGN EUINT64VAL { $$ = $3; };
+
+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; };
+OptCSection : /*empty*/ { $$ = 0; } |
+             ',' SectionString { $$ = $2; };
+
+
 //===----------------------------------------------------------------------===//
 // Types includes all predefined types... except void, because it can only be
 // used in specific contexts (function returning void for example).  To have
@@ -1067,12 +1134,12 @@ UpRTypes : '\\' EUINT64VAL {                   // Type UpReference
   }
   | '<' EUINT64VAL 'x' UpRTypes '>' {          // Packed array type?
      const llvm::Type* ElemTy = $4->get();
-     if ((unsigned)$2 != $2) {
+     if ((unsigned)$2 != $2)
         ThrowException("Unsigned result not equal to signed result");
-     }
-     if(!ElemTy->isPrimitiveType()) {
+     if (!ElemTy->isPrimitiveType())
         ThrowException("Elemental type of a PackedType must be primitive");
-     }
+     if (!isPowerOf2_32($2))
+       ThrowException("Vector length should be a power of 2!");
      $$ = new PATypeHolder(HandleUpRefs(PackedType::get(*$4, (unsigned)$2)));
      delete $4;
   }
@@ -1517,12 +1584,12 @@ ConstPool : ConstPool OptAssign TYPE TypesV {
   }
   | ConstPool FunctionProto {       // Function prototypes can be in const pool
   }
-  | ConstPool OptAssign OptLinkage GlobalType ConstVal {
+  | ConstPool OptAssign OptLinkage GlobalType ConstVal OptCSection OptCAlign {
     if ($5 == 0) ThrowException("Global value initializer is not a constant!");
-    ParseGlobalVariable($2, $3, $4, $5->getType(), $5);
+    ParseGlobalVariable($2, $3, $4, $5->getType(), $5, $6, $7);
   }
-  | ConstPool OptAssign EXTERNAL GlobalType Types {
-    ParseGlobalVariable($2, GlobalValue::ExternalLinkage, $4, *$5, 0);
+  | ConstPool OptAssign EXTERNAL GlobalType Types OptCSection OptCAlign {
+    ParseGlobalVariable($2, GlobalValue::ExternalLinkage, $4, *$5, 0, $6, $7);
     delete $5;
   }
   | ConstPool TARGET TargetDefinition { 
@@ -1607,13 +1674,16 @@ ArgList : ArgListH {
     $$ = 0;
   };
 
-FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' {
+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 ($8 != 0 && !isPowerOf2_32($8))
+    ThrowException("Function alignment must be a power of two!");
 
   std::vector<const Type*> ParamTypeList;
   if ($5) {   // If there are arguments...
@@ -1665,6 +1735,11 @@ FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' {
 
   CurFun.FunctionStart(Fn);
   Fn->setCallingConv($1);
+  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...
@@ -2041,6 +2116,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     $$ = new SelectInst($2, $4, $6);
   }
   | VAARG ResolvedVal ',' Types {
+    NewVarArgs = true;
     $$ = new VAArgInst($2, *$4);
     delete $4;
   }
@@ -2048,7 +2124,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     ObsoleteVarArgs = true;
     const Type* ArgTy = $2->getType();
     Function* NF = CurModule.CurrentModule->
-      getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, 0);
+      getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, (Type *)0);
 
     //b = vaarg a, t -> 
     //foo = alloca 1 of t
@@ -2067,7 +2143,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     ObsoleteVarArgs = true;
     const Type* ArgTy = $2->getType();
     Function* NF = CurModule.CurrentModule->
-      getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, 0);
+      getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, (Type *)0);
 
     //b = vanext a, t ->
     //foo = alloca 1 of t
@@ -2177,20 +2253,32 @@ OptVolatile : VOLATILE {
 
 
 
-MemoryInst : MALLOC Types {
-    $$ = new MallocInst(*$2);
+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 {
-    $$ = new MallocInst(*$2, getVal($4, $5));
+  | 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 {
-    $$ = new AllocaInst(*$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 {
-    $$ = new AllocaInst(*$2, getVal($4, $5));
+  | 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;
   }
   | FREE ResolvedVal {