X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAsmParser%2FllvmAsmParser.y;h=67d20fed804e9151416989147969baa2e8607b8e;hb=0b118206bf3411722707f2e5cab8fd2eedcd50d6;hp=c459a0eec0e4c9516327a86af3f1942a4cfcde41;hpb=5a2a3826ef13690fb2258c449fb233102f4beb86;p=oota-llvm.git diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index c459a0eec0e..67d20fed804 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -17,8 +17,10 @@ #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" #include #include #include @@ -47,6 +49,12 @@ static Module *ParserResult; #define YYERROR_VERBOSE 1 +static bool ObsoleteVarArgs; +static bool NewVarArgs; +static BasicBlock *CurBB; +static GlobalVariable *CurGV; + + // This contains info used when building the body of a function. It is // destroyed when the function is completed. // @@ -97,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. @@ -296,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!"); @@ -509,9 +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) { +static GlobalVariable * +ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, + bool isConstantGlobal, const Type *Ty, + Constant *Initializer) { if (isa(Ty)) ThrowException("Cannot declare global vars of function type!"); @@ -542,7 +558,7 @@ static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, GV->setLinkage(Linkage); GV->setConstant(isConstantGlobal); InsertValue(GV, CurModule.Values); - return; + return GV; } // If this global has a name, check to see if there is already a definition @@ -567,7 +583,7 @@ static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, if (isConstantGlobal) EGV->setConstant(true); EGV->setLinkage(Linkage); - return; + return EGV; } ThrowException("Redefinition of global variable named '" + Name + @@ -580,6 +596,7 @@ static void ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, new GlobalVariable(Ty, isConstantGlobal, Linkage, Initializer, Name, CurModule.CurrentModule); InsertValue(GV, CurModule.Values); + return GV; } // setTypeName - Set the specified type to the name given. The name may be @@ -719,26 +736,141 @@ static PATypeHolder HandleUpRefs(const Type *ty) { } -//===----------------------------------------------------------------------===// -// RunVMAsmParser - Define an interface to this parser -//===----------------------------------------------------------------------===// -// -Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) { - llvmAsmin = F; - CurFilename = Filename; - llvmAsmlineno = 1; // Reset the current line number... +// common code from the two 'RunVMAsmParser' functions + static Module * RunParser(Module * M) { - // Allocate a new module to read - CurModule.CurrentModule = new Module(Filename); + llvmAsmlineno = 1; // Reset the current line number... + ObsoleteVarArgs = false; + NewVarArgs = false; + CurModule.CurrentModule = M; yyparse(); // Parse the file, potentially throwing exception Module *Result = ParserResult; - - llvmAsmin = stdin; // F is about to go away, don't use it anymore... 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")) { + if (F->arg_size() != 0) + ThrowException("Obsolete va_start takes 0 argument!"); + + //foo = va_start() + // -> + //bar = alloca typeof(foo) + //va_start(bar) + //foo = load bar + + 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_start", + RetTy, ArgTyPtr, (Type *)0); + + while (!F->use_empty()) { + CallInst* CI = cast(F->use_back()); + AllocaInst* bar = new AllocaInst(ArgTy, 0, "vastart.fix.1", CI); + new CallInst(NF, bar, "", CI); + Value* foo = new LoadInst(bar, "vastart.fix.2", CI); + CI->replaceAllUsesWith(foo); + CI->getParent()->getInstList().erase(CI); + } + Result->getFunctionList().erase(F); + } + + if(Function* F = Result->getNamedFunction("llvm.va_end")) { + if(F->arg_size() != 1) + ThrowException("Obsolete va_end takes 1 argument!"); + + //vaend foo + // -> + //bar = alloca 1 of typeof(foo) + //vaend bar + const Type* RetTy = Type::getPrimitiveType(Type::VoidTyID); + const Type* ArgTy = F->getFunctionType()->getParamType(0); + const Type* ArgTyPtr = PointerType::get(ArgTy); + Function* NF = Result->getOrInsertFunction("llvm.va_end", + RetTy, ArgTyPtr, (Type *)0); + + while (!F->use_empty()) { + CallInst* CI = cast(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); + } + Result->getFunctionList().erase(F); + } + + if(Function* F = Result->getNamedFunction("llvm.va_copy")) { + if(F->arg_size() != 1) + ThrowException("Obsolete va_copy takes 1 argument!"); + //foo = vacopy(bar) + // -> + //a = alloca 1 of typeof(foo) + //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, ArgTyPtr, + (Type *)0); + + while (!F->use_empty()) { + CallInst* CI = cast(F->use_back()); + AllocaInst* a = new AllocaInst(ArgTy, 0, "vacopy.fix.1", 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); + } + Result->getFunctionList().erase(F); + } + } + return Result; + + } + +//===----------------------------------------------------------------------===// +// RunVMAsmParser - Define an interface to this parser +//===----------------------------------------------------------------------===// +// +Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) { + set_scan_file(F); + + CurFilename = Filename; + return RunParser(new Module(CurFilename)); +} + +Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { + set_scan_string(AsmString); + + CurFilename = "from_memory"; + if (M == NULL) { + return RunParser(new Module (CurFilename)); + } else { + return RunParser(M); + } } %} @@ -828,12 +960,13 @@ Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) { %token VAR_ID LABELSTR STRINGCONSTANT %type Name OptName OptAssign - +%type OptAlign OptCAlign +%type 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 +%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 OptCallingConv @@ -851,7 +984,8 @@ Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) { // Other Operators %type ShiftOps -%token PHI_TOK CAST SELECT SHL SHR VAARG VANEXT +%token PHI_TOK CAST SELECT SHL SHR VAARG EXTRACTELEMENT +%token VAARG_old VANEXT_old //OBSOLETE %start Module @@ -914,6 +1048,47 @@ 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; + if ($$ != 0 && !isPowerOf2_32($$)) + ThrowException("Alignment must be a power of two!"); +}; +OptCAlign : /*empty*/ { $$ = 0; } | + ',' 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 // used in specific contexts (function returning void for example). To have @@ -972,12 +1147,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; } @@ -1331,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($3->getType()) || + !cast($3->getType())->getElementType()->isIntegral()) + ThrowException("Logical operator requires integral operands!"); + } $$ = ConstantExpr::get($1, $3, $5); } | SetCondOps '(' ConstVal ',' ConstVal ')' { @@ -1346,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($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); @@ -1424,11 +1609,16 @@ ConstPool : ConstPool OptAssign TYPE TypesV { } | ConstPool OptAssign OptLinkage GlobalType ConstVal { if ($5 == 0) ThrowException("Global value initializer is not a constant!"); - ParseGlobalVariable($2, $3, $4, $5->getType(), $5); + CurGV = ParseGlobalVariable($2, $3, $4, $5->getType(), $5); + } GlobalVarAttributes { + CurGV = 0; } | ConstPool OptAssign EXTERNAL GlobalType Types { - ParseGlobalVariable($2, GlobalValue::ExternalLinkage, $4, *$5, 0); + CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage, + $4, *$5, 0); delete $5; + } GlobalVarAttributes { + CurGV = 0; } | ConstPool TARGET TargetDefinition { } @@ -1512,7 +1702,8 @@ 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! @@ -1570,6 +1761,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... @@ -1638,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(); @@ -1712,7 +1911,7 @@ InstructionList : InstructionList Inst { $$ = $1; } | /* empty */ { - $$ = getBBVal(ValID::create((int)CurFun.NextBBNum++), true); + $$ = CurBB = getBBVal(ValID::create((int)CurFun.NextBBNum++), true); // Make sure to move the basic block to the correct location in the // function, instead of leaving it inserted wherever it was first @@ -1722,7 +1921,7 @@ InstructionList : InstructionList Inst { BBL.splice(BBL.end(), BBL, $$); } | LABELSTR { - $$ = getBBVal(ValID::create($1), true); + $$ = CurBB = getBBVal(ValID::create($1), true); // Make sure to move the basic block to the correct location in the // function, instead of leaving it inserted wherever it was first @@ -1895,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($2->get()) || + !cast($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!"); @@ -1946,13 +2148,59 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { $$ = new SelectInst($2, $4, $6); } | VAARG ResolvedVal ',' Types { + NewVarArgs = true; $$ = new VAArgInst($2, *$4); delete $4; } - | VANEXT ResolvedVal ',' Types { - $$ = new VANextInst($2, *$4); + | VAARG_old ResolvedVal ',' Types { + ObsoleteVarArgs = true; + const Type* ArgTy = $2->getType(); + Function* NF = CurModule.CurrentModule-> + getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, (Type *)0); + + //b = vaarg a, t -> + //foo = alloca 1 of t + //bar = vacopy a + //store bar -> foo + //b = vaarg foo, t + AllocaInst* foo = new AllocaInst(ArgTy, 0, "vaarg.fix"); + CurBB->getInstList().push_back(foo); + CallInst* bar = new CallInst(NF, $2); + CurBB->getInstList().push_back(bar); + CurBB->getInstList().push_back(new StoreInst(bar, foo)); + $$ = new VAArgInst(foo, *$4); delete $4; } + | VANEXT_old ResolvedVal ',' Types { + ObsoleteVarArgs = true; + const Type* ArgTy = $2->getType(); + Function* NF = CurModule.CurrentModule-> + getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, (Type *)0); + + //b = vanext a, t -> + //foo = alloca 1 of t + //bar = vacopy a + //store bar -> foo + //tmp = vaarg foo, t + //b = load foo + AllocaInst* foo = new AllocaInst(ArgTy, 0, "vanext.fix"); + CurBB->getInstList().push_back(foo); + CallInst* bar = new CallInst(NF, $2); + CurBB->getInstList().push_back(bar); + CurBB->getInstList().push_back(new StoreInst(bar, foo)); + Instruction* tmp = new VAArgInst(foo, *$4); + CurBB->getInstList().push_back(tmp); + $$ = new LoadInst(foo); + delete $4; + } + | EXTRACTELEMENT ResolvedVal ',' ResolvedVal { + if (!isa($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()) @@ -2045,20 +2293,20 @@ OptVolatile : VOLATILE { -MemoryInst : MALLOC Types { - $$ = new MallocInst(*$2); +MemoryInst : MALLOC Types OptCAlign { + $$ = new MallocInst(*$2, 0, $3); delete $2; } - | MALLOC Types ',' UINT ValueRef { - $$ = new MallocInst(*$2, getVal($4, $5)); + | MALLOC Types ',' UINT ValueRef OptCAlign { + $$ = new MallocInst(*$2, getVal($4, $5), $6); delete $2; } - | ALLOCA Types { - $$ = new AllocaInst(*$2); + | ALLOCA Types OptCAlign { + $$ = new AllocaInst(*$2, 0, $3); delete $2; } - | ALLOCA Types ',' UINT ValueRef { - $$ = new AllocaInst(*$2, getVal($4, $5)); + | ALLOCA Types ',' UINT ValueRef OptCAlign { + $$ = new AllocaInst(*$2, getVal($4, $5), $6); delete $2; } | FREE ResolvedVal {