X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAsmParser%2FllvmAsmParser.y;h=51fe7c9cc5c707af04549bba38ae1003124a48d5;hb=b775bbc12156448e12f15762c29ba68bc5d37f1c;hp=7d6a9f7af36d55899eb721c5938d049787db52ef;hpb=703e92fa1b17b64c464abf9c63286a973a226274;p=oota-llvm.git diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 7d6a9f7af36..51fe7c9cc5c 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -18,12 +18,11 @@ #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 "llvm/Support/Streams.h" #include -#include #include #include @@ -39,7 +38,7 @@ // immediately invokes YYERROR. This would be so much cleaner if it was a // recursive descent parser. static bool TriggerError = false; -#define CHECK_FOR_ERROR { if (TriggerError) { TriggerError = false; YYERROR; } } +#define CHECK_FOR_ERROR { if (TriggerError) { TriggerError = false; YYABORT; } } #define GEN_ERROR(msg) { GenerateError(msg); YYERROR; } int yyerror(const char *ErrorMsg); // Forward declarations to prevent "implicit @@ -58,16 +57,14 @@ static Module *ParserResult; // //#define DEBUG_UPREFS 1 #ifdef DEBUG_UPREFS -#define UR_OUT(X) std::cerr << X +#define UR_OUT(X) llvm_cerr << X #else #define UR_OUT(X) #endif #define YYERROR_VERBOSE 1 -static bool ObsoleteVarArgs; static bool NewVarArgs; -static BasicBlock *CurBB; static GlobalVariable *CurGV; @@ -106,6 +103,8 @@ static struct PerModuleInfo { // are resolved when the constant pool has been completely parsed. // ResolveDefinitions(LateResolveValues); + if (TriggerError) + return; // Check to make sure that all global value forward references have been // resolved! @@ -119,13 +118,9 @@ static struct PerModuleInfo { I->first.second.getName() + "\n"; } GenerateError(UndefinedReferences); + return; } - // Look for intrinsic functions and CallInst that need to be upgraded - for (Module::iterator FI = CurrentModule->begin(), - FE = CurrentModule->end(); FI != FE; ) - UpgradeCallsToIntrinsic(FI++); - Values.clear(); // Clear out function local definitions Types.clear(); CurrentModule = 0; @@ -150,9 +145,10 @@ static struct PerModuleInfo { static struct PerFunctionInfo { Function *CurrentFunction; // Pointer to current function being created - std::map Values; // Keep track of #'d definitions + std::map Values; // Keep track of #'d definitions std::map LateResolveValues; - bool isDeclare; // Is this function a forward declararation? + bool isDeclare; // Is this function a forward declararation? + GlobalValue::LinkageTypes Linkage; // Linkage for forward declaration. /// BBForwardRefs - When we see forward references to basic blocks, keep /// track of them here. @@ -163,6 +159,7 @@ static struct PerFunctionInfo { inline PerFunctionInfo() { CurrentFunction = 0; isDeclare = false; + Linkage = GlobalValue::ExternalLinkage; } inline void FunctionStart(Function *M) { @@ -174,9 +171,11 @@ static struct PerFunctionInfo { NumberedBlocks.clear(); // Any forward referenced blocks left? - if (!BBForwardRefs.empty()) + if (!BBForwardRefs.empty()) { GenerateError("Undefined reference to label " + BBForwardRefs.begin()->first->getName()); + return; + } // Resolve all forward references now. ResolveDefinitions(LateResolveValues, &CurModule.LateResolveValues); @@ -184,6 +183,7 @@ static struct PerFunctionInfo { Values.clear(); // Clear out function local definitions CurrentFunction = 0; isDeclare = false; + Linkage = GlobalValue::ExternalLinkage; } } CurFun; // Info for the current function... @@ -219,6 +219,7 @@ static const Type *getTypeVal(const ValID &D, bool DoNotImprovise = false) { break; default: GenerateError("Internal parser error: Invalid symbol type reference!"); + return 0; } // If we reached here, we referenced either a symbol that we don't know about @@ -229,10 +230,13 @@ static const Type *getTypeVal(const ValID &D, bool DoNotImprovise = false) { if (inFunctionScope()) { - if (D.Type == ValID::NameVal) + if (D.Type == ValID::NameVal) { GenerateError("Reference to an undefined type: '" + D.getName() + "'"); - else + return 0; + } else { GenerateError("Reference to an undefined type: #" + itostr(D.Num)); + return 0; + } } std::map::iterator I =CurModule.LateResolveTypes.find(D); @@ -256,9 +260,11 @@ static Value *lookupInSymbolTable(const Type *Ty, const std::string &Name) { // it. Otherwise return null. // static Value *getValNonImprovising(const Type *Ty, const ValID &D) { - if (isa(Ty)) + if (isa(Ty)) { GenerateError("Functions are not values and " "must be referenced as pointers"); + return 0; + } switch (D.Type) { case ValID::NumberVal: { // Is it a numbered definition? @@ -293,32 +299,39 @@ 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 (!ConstantSInt::isValueValidForType(Ty, D.ConstPool64)) + if (!ConstantInt::isValueValidForType(Ty, D.ConstPool64)) { GenerateError("Signed integral constant '" + itostr(D.ConstPool64) + "' is invalid for type '" + Ty->getDescription() + "'!"); - return ConstantSInt::get(Ty, D.ConstPool64); + return 0; + } + return ConstantInt::get(Ty, D.ConstPool64); case ValID::ConstUIntVal: // Is it an unsigned const pool reference? - if (!ConstantUInt::isValueValidForType(Ty, D.UConstPool64)) { - if (!ConstantSInt::isValueValidForType(Ty, D.ConstPool64)) { + if (!ConstantInt::isValueValidForType(Ty, D.UConstPool64)) { + if (!ConstantInt::isValueValidForType(Ty, D.ConstPool64)) { GenerateError("Integral constant '" + utostr(D.UConstPool64) + "' is invalid or out of range!"); + return 0; } else { // This is really a signed reference. Transmogrify. - return ConstantSInt::get(Ty, D.ConstPool64); + return ConstantInt::get(Ty, D.ConstPool64); } } else { - return ConstantUInt::get(Ty, D.UConstPool64); + return ConstantInt::get(Ty, D.UConstPool64); } case ValID::ConstFPVal: // Is it a floating point const pool reference? - if (!ConstantFP::isValueValidForType(Ty, D.ConstPoolFP)) + if (!ConstantFP::isValueValidForType(Ty, D.ConstPoolFP)) { GenerateError("FP constant invalid for type!!"); + return 0; + } return ConstantFP::get(Ty, D.ConstPoolFP); case ValID::ConstNullVal: // Is it a null value? - if (!isa(Ty)) + if (!isa(Ty)) { GenerateError("Cannot create a a non pointer null!"); + return 0; + } return ConstantPointerNull::get(cast(Ty)); case ValID::ConstUndefVal: // Is it an undef value? @@ -328,16 +341,20 @@ static Value *getValNonImprovising(const Type *Ty, const ValID &D) { return Constant::getNullValue(Ty); case ValID::ConstantVal: // Fully resolved constant? - if (D.ConstantValue->getType() != Ty) + if (D.ConstantValue->getType() != Ty) { GenerateError("Constant expression type different from required type!"); + return 0; + } return D.ConstantValue; case ValID::InlineAsmVal: { // Inline asm expression const PointerType *PTy = dyn_cast(Ty); const FunctionType *FTy = PTy ? dyn_cast(PTy->getElementType()) : 0; - if (!FTy || !InlineAsm::Verify(FTy, D.IAD->Constraints)) + if (!FTy || !InlineAsm::Verify(FTy, D.IAD->Constraints)) { GenerateError("Invalid type for asm constraint string!"); + return 0; + } InlineAsm *IA = InlineAsm::get(FTy, D.IAD->AsmString, D.IAD->Constraints, D.IAD->HasSideEffects); D.destroy(); // Free InlineAsmDescriptor. @@ -359,15 +376,20 @@ static Value *getValNonImprovising(const Type *Ty, const ValID &D) { // real thing. // static Value *getVal(const Type *Ty, const ValID &ID) { - if (Ty == Type::LabelTy) + if (Ty == Type::LabelTy) { GenerateError("Cannot use a basic block here"); + return 0; + } // See if the value has already been defined. Value *V = getValNonImprovising(Ty, ID); if (V) return V; + if (TriggerError) return 0; - if (!Ty->isFirstClassType() && !isa(Ty)) + if (!Ty->isFirstClassType() && !isa(Ty)) { GenerateError("Invalid use of a composite type!"); + return 0; + } // If we reached here, we referenced either a symbol that we don't know about // or an id number that hasn't been read yet. We may be referencing something @@ -399,7 +421,9 @@ static BasicBlock *getBBVal(const ValID &ID, bool isDefinition = false) { std::string Name; BasicBlock *BB = 0; switch (ID.Type) { - default: GenerateError("Illegal label reference " + ID.getName()); + default: + GenerateError("Illegal label reference " + ID.getName()); + return 0; case ValID::NumberVal: // Is it a numbered definition? if (unsigned(ID.Num) >= CurFun.NumberedBlocks.size()) CurFun.NumberedBlocks.resize(ID.Num+1); @@ -418,9 +442,11 @@ static BasicBlock *getBBVal(const ValID &ID, bool isDefinition = false) { // If this is the definition of the block, make sure the existing value was // just a forward reference. If it was a forward reference, there will be // an entry for it in the PlaceHolderInfo map. - if (isDefinition && !CurFun.BBForwardRefs.erase(BB)) + if (isDefinition && !CurFun.BBForwardRefs.erase(BB)) { // The existing value was a definition, not a forward reference. GenerateError("Redefinition of label " + ID.getName()); + return 0; + } ID.destroy(); // Free strdup'd memory. return BB; @@ -484,6 +510,8 @@ ResolveDefinitions(std::map &LateResolvers, ValID &DID = PHI->second.first; Value *TheRealValue = getValNonImprovising(LRI->first, DID); + if (TriggerError) + return; if (TheRealValue) { V->replaceAllUsesWith(TheRealValue); delete V; @@ -493,15 +521,18 @@ ResolveDefinitions(std::map &LateResolvers, // resolver table InsertValue(V, *FutureLateResolvers); } else { - if (DID.Type == ValID::NameVal) + if (DID.Type == ValID::NameVal) { GenerateError("Reference to an invalid definition: '" +DID.getName()+ "' of type '" + V->getType()->getDescription() + "'", PHI->second.second); - else + return; + } else { GenerateError("Reference to an invalid definition: #" + itostr(DID.Num) + " of type '" + V->getType()->getDescription() + "'", PHI->second.second); + return; + } } } } @@ -535,14 +566,18 @@ static void setValueName(Value *V, char *NameStr) { std::string Name(NameStr); // Copy string free(NameStr); // Free old string - if (V->getType() == Type::VoidTy) + if (V->getType() == Type::VoidTy) { GenerateError("Can't assign name '" + Name+"' to value with void type!"); + return; + } assert(inFunctionScope() && "Must be in function scope!"); SymbolTable &ST = CurFun.CurrentFunction->getSymbolTable(); - if (ST.lookup(V->getType(), Name)) + if (ST.lookup(V->getType(), Name)) { GenerateError("Redefinition of value named '" + Name + "' in the '" + V->getType()->getDescription() + "' type plane!"); + return; + } // Set the name. V->setName(Name); @@ -555,8 +590,10 @@ static GlobalVariable * ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, bool isConstantGlobal, const Type *Ty, Constant *Initializer) { - if (isa(Ty)) + if (isa(Ty)) { GenerateError("Cannot declare global vars of function type!"); + return 0; + } const PointerType *PTy = PointerType::get(Ty); @@ -615,6 +652,7 @@ ParseGlobalVariable(char *NameStr,GlobalValue::LinkageTypes Linkage, GenerateError("Redefinition of global variable named '" + Name + "' in the '" + Ty->getDescription() + "' type plane!"); + return 0; } } @@ -641,8 +679,10 @@ static bool setTypeName(const Type *T, char *NameStr) { free(NameStr); // Free old string // We don't allow assigning names to void type - if (T == Type::VoidTy) + if (T == Type::VoidTy) { GenerateError("Can't assign name '" + Name + "' to the void type!"); + return false; + } // Set the type name, checking for conflicts as we do so. bool AlreadyExists = CurModule.CurrentModule->addTypeName(Name, T); @@ -765,123 +805,30 @@ static PATypeHolder HandleUpRefs(const Type *ty) { return Ty; } - // common code from the two 'RunVMAsmParser' functions - static Module * RunParser(Module * M) { +static Module* RunParser(Module * M) { llvmAsmlineno = 1; // Reset the current line number... - ObsoleteVarArgs = false; NewVarArgs = false; - CurModule.CurrentModule = M; - yyparse(); // Parse the file, potentially throwing exception + + // Check to make sure the parser succeeded + if (yyparse()) { + if (ParserResult) + delete ParserResult; + return 0; + } + + // Check to make sure that parsing produced a result if (!ParserResult) return 0; + // Reset ParserResult variable while saving its value for the result. 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) - GenerateError("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) - GenerateError("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) - GenerateError("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) - GenerateError("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 @@ -938,13 +885,16 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { bool BoolVal; char *StrVal; // This memory is strdup'd! - llvm::ValID ValIDVal; // strdup'd memory maybe! - - llvm::Instruction::BinaryOps BinaryOpVal; - llvm::Instruction::TermOps TermOpVal; - llvm::Instruction::MemoryOps MemOpVal; - llvm::Instruction::OtherOps OtherOpVal; - llvm::Module::Endianness Endianness; + llvm::ValID ValIDVal; // strdup'd memory maybe! + + llvm::Instruction::BinaryOps BinaryOpVal; + llvm::Instruction::TermOps TermOpVal; + llvm::Instruction::MemoryOps MemOpVal; + llvm::Instruction::CastOps CastOpVal; + llvm::Instruction::OtherOps OtherOpVal; + llvm::Module::Endianness Endianness; + llvm::ICmpInst::Predicate IPredicate; + llvm::FCmpInst::Predicate FPredicate; } %type Module FunctionList @@ -998,10 +948,13 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token IMPLEMENTATION ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK %token DECLARE GLOBAL CONSTANT SECTION VOLATILE -%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING +%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING +%token DLLIMPORT DLLEXPORT EXTERN_WEAK %token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG ALIGN %token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT %token CC_TOK CCC_TOK CSRETCC_TOK FASTCC_TOK COLDCC_TOK +%token X86_STDCALLCC_TOK X86_FASTCALLCC_TOK +%token DATALAYOUT %type OptCallingConv // Basic Block Terminating Operators @@ -1009,17 +962,26 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { // Binary Operators %type ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories -%token ADD SUB MUL DIV REM AND OR XOR -%token SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comarators +%token ADD SUB MUL UDIV SDIV FDIV UREM SREM FREM AND OR XOR +%token SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators +%token ICMP FCMP +%type IPredicates +%type FPredicates +%token EQ NE SLT SGT SLE SGE ULT UGT ULE UGE +%token OEQ ONE OLT OGT OLE OGE ORD UNO UEQ UNE // Memory Instructions %token MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR +// Cast Operators +%type CastOps +%token TRUNC ZEXT SEXT FPTRUNC FPEXT BITCAST +%token UITOFP SITOFP FPTOUI FPTOSI INTTOPTR PTRTOINT + // Other Operators %type ShiftOps -%token PHI_TOK CAST SELECT SHL SHR VAARG +%token PHI_TOK SELECT SHL LSHR ASHR VAARG %token EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR -%token VAARG_old VANEXT_old //OBSOLETE %start Module @@ -1047,11 +1009,31 @@ EINT64VAL : EUINT64VAL { // Operations that are notably excluded from this list include: // RET, BR, & SWITCH because they end basic blocks and are treated specially. // -ArithmeticOps: ADD | SUB | MUL | DIV | REM; +ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | UREM | SREM | FREM; LogicalOps : AND | OR | XOR; SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE; - -ShiftOps : SHL | SHR; +CastOps : TRUNC | ZEXT | SEXT | FPTRUNC | FPEXT | BITCAST | + UITOFP | SITOFP | FPTOUI | FPTOSI | INTTOPTR | PTRTOINT; +ShiftOps : SHL | LSHR | ASHR; +IPredicates + : EQ { $$ = ICmpInst::ICMP_EQ; } | NE { $$ = ICmpInst::ICMP_NE; } + | SLT { $$ = ICmpInst::ICMP_SLT; } | SGT { $$ = ICmpInst::ICMP_SGT; } + | SLE { $$ = ICmpInst::ICMP_SLE; } | SGE { $$ = ICmpInst::ICMP_SGE; } + | ULT { $$ = ICmpInst::ICMP_ULT; } | UGT { $$ = ICmpInst::ICMP_UGT; } + | ULE { $$ = ICmpInst::ICMP_ULE; } | UGE { $$ = ICmpInst::ICMP_UGE; } + ; + +FPredicates + : OEQ { $$ = FCmpInst::FCMP_OEQ; } | ONE { $$ = FCmpInst::FCMP_ONE; } + | OLT { $$ = FCmpInst::FCMP_OLT; } | OGT { $$ = FCmpInst::FCMP_OGT; } + | OLE { $$ = FCmpInst::FCMP_OLE; } | OGE { $$ = FCmpInst::FCMP_OGE; } + | ORD { $$ = FCmpInst::FCMP_ORD; } | UNO { $$ = FCmpInst::FCMP_UNO; } + | UEQ { $$ = FCmpInst::FCMP_UEQ; } | UNE { $$ = FCmpInst::FCMP_UNE; } + | ULT { $$ = FCmpInst::FCMP_ULT; } | UGT { $$ = FCmpInst::FCMP_UGT; } + | ULE { $$ = FCmpInst::FCMP_ULE; } | UGE { $$ = FCmpInst::FCMP_UGE; } + | TRUETOK { $$ = FCmpInst::FCMP_TRUE; } + | FALSETOK { $$ = FCmpInst::FCMP_FALSE; } + ; // These are some types that allow classification if we only want a particular // thing... for example, only a signed, unsigned, or integral type. @@ -1070,18 +1052,23 @@ OptAssign : Name '=' { CHECK_FOR_ERROR }; -OptLinkage : INTERNAL { $$ = GlobalValue::InternalLinkage; } | - LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | - WEAK { $$ = GlobalValue::WeakLinkage; } | - APPENDING { $$ = GlobalValue::AppendingLinkage; } | - /*empty*/ { $$ = GlobalValue::ExternalLinkage; }; - -OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | - CCC_TOK { $$ = CallingConv::C; } | - CSRETCC_TOK { $$ = CallingConv::CSRet; } | - FASTCC_TOK { $$ = CallingConv::Fast; } | - COLDCC_TOK { $$ = CallingConv::Cold; } | - CC_TOK EUINT64VAL { +OptLinkage : INTERNAL { $$ = GlobalValue::InternalLinkage; } | + LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | + WEAK { $$ = GlobalValue::WeakLinkage; } | + APPENDING { $$ = GlobalValue::AppendingLinkage; } | + DLLIMPORT { $$ = GlobalValue::DLLImportLinkage; } | + DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; } | + EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; } | + /*empty*/ { $$ = GlobalValue::ExternalLinkage; }; + +OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | + CCC_TOK { $$ = CallingConv::C; } | + CSRETCC_TOK { $$ = CallingConv::CSRet; } | + FASTCC_TOK { $$ = CallingConv::Fast; } | + COLDCC_TOK { $$ = CallingConv::Cold; } | + X86_STDCALLCC_TOK { $$ = CallingConv::X86_StdCall; } | + X86_FASTCALLCC_TOK { $$ = CallingConv::X86_FastCall; } | + CC_TOK EUINT64VAL { if ((unsigned)$2 != $2) GEN_ERROR("Calling conv too large!"); $$ = $2; @@ -1165,8 +1152,9 @@ UpRTypes : OPAQUE { CHECK_FOR_ERROR }; UpRTypes : SymbolicValueRef { // Named types are also simple types... - $$ = new PATypeHolder(getTypeVal($1)); + const Type* tmp = getTypeVal($1); CHECK_FOR_ERROR + $$ = new PATypeHolder(tmp); }; // Include derived types in the Types production. @@ -1224,6 +1212,8 @@ UpRTypes : '\\' EUINT64VAL { // Type UpReference CHECK_FOR_ERROR } | UpRTypes '*' { // Pointer type? + if (*$1 == Type::LabelTy) + GEN_ERROR("Cannot form a pointer to a basic block"); $$ = new PATypeHolder(HandleUpRefs(PointerType::get(*$1))); delete $1; CHECK_FOR_ERROR @@ -1319,11 +1309,11 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr std::vector Vals; if (ETy == Type::SByteTy) { for (signed char *C = (signed char *)$3; C != (signed char *)EndStr; ++C) - Vals.push_back(ConstantSInt::get(ETy, *C)); + Vals.push_back(ConstantInt::get(ETy, *C)); } else if (ETy == Type::UByteTy) { for (unsigned char *C = (unsigned char *)$3; C != (unsigned char*)EndStr; ++C) - Vals.push_back(ConstantUInt::get(ETy, *C)); + Vals.push_back(ConstantInt::get(ETy, *C)); } else { free($3); GEN_ERROR("Cannot build string arrays of non byte sized elements!"); @@ -1424,6 +1414,7 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr CurFun.CurrentFunction = 0; Value *V = getValNonImprovising(Ty, $2); + CHECK_FOR_ERROR CurFun.CurrentFunction = SavedCurFn; @@ -1482,26 +1473,25 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr $$ = Constant::getNullValue(Ty); delete $1; CHECK_FOR_ERROR - }; - -ConstVal : SIntType EINT64VAL { // integral constants - if (!ConstantSInt::isValueValidForType($1, $2)) + } + | SIntType EINT64VAL { // integral constants + if (!ConstantInt::isValueValidForType($1, $2)) GEN_ERROR("Constant value doesn't fit in type!"); - $$ = ConstantSInt::get($1, $2); + $$ = ConstantInt::get($1, $2); CHECK_FOR_ERROR } | UIntType EUINT64VAL { // integral constants - if (!ConstantUInt::isValueValidForType($1, $2)) + if (!ConstantInt::isValueValidForType($1, $2)) GEN_ERROR("Constant value doesn't fit in type!"); - $$ = ConstantUInt::get($1, $2); + $$ = ConstantInt::get($1, $2); CHECK_FOR_ERROR } | BOOL TRUETOK { // Boolean constants - $$ = ConstantBool::True; + $$ = ConstantBool::getTrue(); CHECK_FOR_ERROR } | BOOL FALSETOK { // Boolean constants - $$ = ConstantBool::False; + $$ = ConstantBool::getFalse(); CHECK_FOR_ERROR } | FPType FPVAL { // Float & Double constants @@ -1512,32 +1502,22 @@ ConstVal : SIntType EINT64VAL { // integral constants }; -ConstExpr: CAST '(' ConstVal TO Types ')' { - if (!$3->getType()->isFirstClassType()) +ConstExpr: CastOps '(' ConstVal TO Types ')' { + Constant *Val = $3; + const Type *Ty = $5->get(); + if (!Val->getType()->isFirstClassType()) GEN_ERROR("cast constant expression from a non-primitive type: '" + - $3->getType()->getDescription() + "'!"); - if (!$5->get()->isFirstClassType()) + Val->getType()->getDescription() + "'!"); + if (!Ty->isFirstClassType()) GEN_ERROR("cast constant expression to a non-primitive type: '" + - $5->get()->getDescription() + "'!"); - $$ = ConstantExpr::getCast($3, $5->get()); + Ty->getDescription() + "'!"); + $$ = ConstantExpr::getCast($1, $3, $5->get()); delete $5; - CHECK_FOR_ERROR } | GETELEMENTPTR '(' ConstVal IndexList ')' { if (!isa($3->getType())) GEN_ERROR("GetElementPtr requires a pointer operand!"); - // LLVM 1.2 and earlier used ubyte struct indices. Convert any ubyte struct - // indices to uint struct indices for compatibility. - generic_gep_type_iterator::iterator> - GTI = gep_type_begin($3->getType(), $4->begin(), $4->end()), - GTE = gep_type_end($3->getType(), $4->begin(), $4->end()); - for (unsigned i = 0, e = $4->size(); i != e && GTI != GTE; ++i, ++GTI) - if (isa(*GTI)) // Only change struct indices - if (ConstantUInt *CUI = dyn_cast((*$4)[i])) - if (CUI->getType() == Type::UByteTy) - (*$4)[i] = ConstantExpr::getCast(CUI, Type::UIntTy); - const Type *IdxTy = GetElementPtrInst::getIndexedType($3->getType(), *$4, true); if (!IdxTy) @@ -1566,24 +1546,8 @@ ConstExpr: CAST '(' ConstVal TO Types ')' { | ArithmeticOps '(' ConstVal ',' ConstVal ')' { if ($3->getType() != $5->getType()) GEN_ERROR("Binary operator types must match!"); - // HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs. - // To retain backward compatibility with these early compilers, we emit a - // cast to the appropriate integer type automatically if we are in the - // broken case. See PR424 for more information. - if (!isa($3->getType())) { - $$ = ConstantExpr::get($1, $3, $5); - } else { - const Type *IntPtrTy = 0; - switch (CurModule.CurrentModule->getPointerSize()) { - case Module::Pointer32: IntPtrTy = Type::IntTy; break; - case Module::Pointer64: IntPtrTy = Type::LongTy; break; - default: GEN_ERROR("invalid pointer binary constant expr!"); - } - $$ = ConstantExpr::get($1, ConstantExpr::getCast($3, IntPtrTy), - ConstantExpr::getCast($5, IntPtrTy)); - $$ = ConstantExpr::getCast($$, $3->getType()); - } - CHECK_FOR_ERROR + CHECK_FOR_ERROR; + $$ = ConstantExpr::get($1, $3, $5); } | LogicalOps '(' ConstVal ',' ConstVal ')' { if ($3->getType() != $5->getType()) @@ -1602,11 +1566,22 @@ ConstExpr: CAST '(' ConstVal TO Types ')' { $$ = ConstantExpr::get($1, $3, $5); CHECK_FOR_ERROR } + | ICMP IPredicates '(' ConstVal ',' ConstVal ')' { + if ($4->getType() != $6->getType()) + GEN_ERROR("icmp operand types must match!"); + $$ = ConstantExpr::getICmp($2, $4, $6); + } + | FCMP FPredicates '(' ConstVal ',' ConstVal ')' { + if ($4->getType() != $6->getType()) + GEN_ERROR("fcmp operand types must match!"); + $$ = ConstantExpr::getFCmp($2, $4, $6); + } | ShiftOps '(' ConstVal ',' ConstVal ')' { if ($5->getType() != Type::UByteTy) GEN_ERROR("Shift count for shift constant must be unsigned byte!"); if (!$3->getType()->isInteger()) GEN_ERROR("Shift constant expression requires integer operand!"); + CHECK_FOR_ERROR; $$ = ConstantExpr::get($1, $3, $5); CHECK_FOR_ERROR } @@ -1656,7 +1631,7 @@ GlobalType : GLOBAL { $$ = false; } | CONSTANT { $$ = true; }; Module : FunctionList { $$ = ParserResult = $1; CurModule.ModuleDone(); - CHECK_FOR_ERROR + CHECK_FOR_ERROR; }; // FunctionList - A list of functions, preceeded by a constant pool. @@ -1706,6 +1681,7 @@ ConstPool : ConstPool OptAssign TYPE TypesV { ResolveTypeTo($2, *$4); if (!setTypeName(*$4, $2) && !$2) { + CHECK_FOR_ERROR // If this is a named type that is not a redefinition, add it to the slot // table. CurModule.Types.push_back(*$4); @@ -1721,17 +1697,35 @@ ConstPool : ConstPool OptAssign TYPE TypesV { CHECK_FOR_ERROR } | ConstPool OptAssign OptLinkage GlobalType ConstVal { - if ($5 == 0) GEN_ERROR("Global value initializer is not a constant!"); + if ($5 == 0) + GEN_ERROR("Global value initializer is not a constant!"); CurGV = ParseGlobalVariable($2, $3, $4, $5->getType(), $5); - } GlobalVarAttributes { - CurGV = 0; CHECK_FOR_ERROR + } GlobalVarAttributes { + CurGV = 0; } | ConstPool OptAssign EXTERNAL GlobalType Types { - CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage, - $4, *$5, 0); + CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage, $4, *$5, 0); + CHECK_FOR_ERROR delete $5; - } GlobalVarAttributes { + } GlobalVarAttributes { + CurGV = 0; + CHECK_FOR_ERROR + } + | ConstPool OptAssign DLLIMPORT GlobalType Types { + CurGV = ParseGlobalVariable($2, GlobalValue::DLLImportLinkage, $4, *$5, 0); + CHECK_FOR_ERROR + delete $5; + } GlobalVarAttributes { + CurGV = 0; + CHECK_FOR_ERROR + } + | ConstPool OptAssign EXTERN_WEAK GlobalType Types { + CurGV = + ParseGlobalVariable($2, GlobalValue::ExternalWeakLinkage, $4, *$5, 0); + CHECK_FOR_ERROR + delete $5; + } GlobalVarAttributes { CurGV = 0; CHECK_FOR_ERROR } @@ -1777,7 +1771,10 @@ TargetDefinition : ENDIAN '=' BigOrLittle { | TRIPLE '=' STRINGCONSTANT { CurModule.CurrentModule->setTargetTriple($3); free($3); - CHECK_FOR_ERROR + } + | DATALAYOUT '=' STRINGCONSTANT { + CurModule.CurrentModule->setDataLayout($3); + free($3); }; LibrariesDefinition : '[' LibList ']'; @@ -1894,14 +1891,21 @@ FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' for (Function::arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end(); AI != AE; ++AI) AI->setName(""); - } else { // Not already defined? Fn = new Function(FT, GlobalValue::ExternalLinkage, FunctionName, CurModule.CurrentModule); + InsertValue(Fn, CurModule.Values); } CurFun.FunctionStart(Fn); + + if (CurFun.isDeclare) { + // If we have declaration, always overwrite linkage. This will allow us to + // correctly handle cases, when pointer to function is passed as argument to + // another function. + Fn->setLinkage(CurFun.Linkage); + } Fn->setCallingConv($1); Fn->setAlignment($8); if ($7) { @@ -1923,6 +1927,7 @@ FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' delete I->first; // Delete the typeholder... setValueName(ArgIt, I->second); // Insert arg into symtab... + CHECK_FOR_ERROR InsertValue(ArgIt); } @@ -1948,11 +1953,15 @@ Function : BasicBlockList END { CHECK_FOR_ERROR }; -FunctionProto : DECLARE { CurFun.isDeclare = true; } FunctionHeaderH { - $$ = CurFun.CurrentFunction; - CurFun.FunctionDone(); - CHECK_FOR_ERROR -}; +FnDeclareLinkage: /*default*/ | + DLLIMPORT { CurFun.Linkage = GlobalValue::DLLImportLinkage; } | + EXTERN_WEAK { CurFun.Linkage = GlobalValue::ExternalWeakLinkage; }; + +FunctionProto : DECLARE { CurFun.isDeclare = true; } FnDeclareLinkage FunctionHeaderH { + $$ = CurFun.CurrentFunction; + CurFun.FunctionDone(); + CHECK_FOR_ERROR + }; //===----------------------------------------------------------------------===// // Rules to match Basic Blocks @@ -1980,11 +1989,11 @@ ConstValueRef : ESINT64VAL { // A reference to a direct constant CHECK_FOR_ERROR } | TRUETOK { - $$ = ValID::create(ConstantBool::True); + $$ = ValID::create(ConstantBool::getTrue()); CHECK_FOR_ERROR } | FALSETOK { - $$ = ValID::create(ConstantBool::False); + $$ = ValID::create(ConstantBool::getFalse()); CHECK_FOR_ERROR } | NULL_TOK { @@ -2078,6 +2087,7 @@ BasicBlockList : BasicBlockList BasicBlock { // BasicBlock : InstructionList OptAssign BBTerminatorInst { setValueName($3, $2); + CHECK_FOR_ERROR InsertValue($3); $1->getInstList().push_back($3); @@ -2087,12 +2097,17 @@ BasicBlock : InstructionList OptAssign BBTerminatorInst { }; InstructionList : InstructionList Inst { + if (CastInst *CI1 = dyn_cast($2)) + if (CastInst *CI2 = dyn_cast(CI1->getOperand(0))) + if (CI2->getParent() == 0) + $1->getInstList().push_back(CI2); $1->getInstList().push_back($2); $$ = $1; CHECK_FOR_ERROR } | /* empty */ { - $$ = CurBB = getBBVal(ValID::create((int)CurFun.NextBBNum++), true); + $$ = getBBVal(ValID::create((int)CurFun.NextBBNum++), true); + CHECK_FOR_ERROR // Make sure to move the basic block to the correct location in the // function, instead of leaving it inserted wherever it was first @@ -2103,7 +2118,8 @@ InstructionList : InstructionList Inst { CHECK_FOR_ERROR } | LABELSTR { - $$ = CurBB = getBBVal(ValID::create($1), true); + $$ = getBBVal(ValID::create($1), true); + CHECK_FOR_ERROR // Make sure to move the basic block to the correct location in the // function, instead of leaving it inserted wherever it was first @@ -2123,15 +2139,25 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... CHECK_FOR_ERROR } | BR LABEL ValueRef { // Unconditional Branch... - $$ = new BranchInst(getBBVal($3)); + BasicBlock* tmpBB = getBBVal($3); CHECK_FOR_ERROR + $$ = new BranchInst(tmpBB); } // Conditional Branch... | BR BOOL ValueRef ',' LABEL ValueRef ',' LABEL ValueRef { - $$ = new BranchInst(getBBVal($6), getBBVal($9), getVal(Type::BoolTy, $3)); + BasicBlock* tmpBBA = getBBVal($6); CHECK_FOR_ERROR + BasicBlock* tmpBBB = getBBVal($9); + CHECK_FOR_ERROR + Value* tmpVal = getVal(Type::BoolTy, $3); + CHECK_FOR_ERROR + $$ = new BranchInst(tmpBBA, tmpBBB, tmpVal); } | SWITCH IntType ValueRef ',' LABEL ValueRef '[' JumpTable ']' { - SwitchInst *S = new SwitchInst(getVal($2, $3), getBBVal($6), $8->size()); + Value* tmpVal = getVal($2, $3); + CHECK_FOR_ERROR + BasicBlock* tmpBB = getBBVal($6); + CHECK_FOR_ERROR + SwitchInst *S = new SwitchInst(tmpVal, tmpBB, $8->size()); $$ = S; std::vector >::iterator I = $8->begin(), @@ -2146,7 +2172,11 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... CHECK_FOR_ERROR } | SWITCH IntType ValueRef ',' LABEL ValueRef '[' ']' { - SwitchInst *S = new SwitchInst(getVal($2, $3), getBBVal($6), 0); + Value* tmpVal = getVal($2, $3); + CHECK_FOR_ERROR + BasicBlock* tmpBB = getBBVal($6); + CHECK_FOR_ERROR + SwitchInst *S = new SwitchInst(tmpVal, tmpBB, 0); $$ = S; CHECK_FOR_ERROR } @@ -2173,9 +2203,11 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... } Value *V = getVal(PFTy, $4); // Get the function we're calling... - + CHECK_FOR_ERROR BasicBlock *Normal = getBBVal($10); + CHECK_FOR_ERROR BasicBlock *Except = getBBVal($13); + CHECK_FOR_ERROR // Create the call node... if (!$6) { // Has no arguments? @@ -2218,26 +2250,31 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... JumpTable : JumpTable IntType ConstValueRef ',' LABEL ValueRef { $$ = $1; Constant *V = cast(getValNonImprovising($2, $3)); + CHECK_FOR_ERROR if (V == 0) GEN_ERROR("May only switch on a constant pool value!"); - $$->push_back(std::make_pair(V, getBBVal($6))); + BasicBlock* tmpBB = getBBVal($6); CHECK_FOR_ERROR + $$->push_back(std::make_pair(V, tmpBB)); } | IntType ConstValueRef ',' LABEL ValueRef { $$ = new std::vector >(); Constant *V = cast(getValNonImprovising($1, $2)); + CHECK_FOR_ERROR if (V == 0) GEN_ERROR("May only switch on a constant pool value!"); - $$->push_back(std::make_pair(V, getBBVal($5))); + BasicBlock* tmpBB = getBBVal($5); CHECK_FOR_ERROR + $$->push_back(std::make_pair(V, tmpBB)); }; Inst : OptAssign InstVal { // Is this definition named?? if so, assign the name... setValueName($2, $1); + CHECK_FOR_ERROR InsertValue($2); $$ = $2; CHECK_FOR_ERROR @@ -2245,22 +2282,26 @@ Inst : OptAssign InstVal { PHIList : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes $$ = new std::list >(); - $$->push_back(std::make_pair(getVal(*$1, $3), getBBVal($5))); - delete $1; + Value* tmpVal = getVal(*$1, $3); + CHECK_FOR_ERROR + BasicBlock* tmpBB = getBBVal($5); CHECK_FOR_ERROR + $$->push_back(std::make_pair(tmpVal, tmpBB)); + delete $1; } | PHIList ',' '[' ValueRef ',' ValueRef ']' { $$ = $1; - $1->push_back(std::make_pair(getVal($1->front().first->getType(), $4), - getBBVal($6))); + Value* tmpVal = getVal($1->front().first->getType(), $4); + CHECK_FOR_ERROR + BasicBlock* tmpBB = getBBVal($6); CHECK_FOR_ERROR + $1->push_back(std::make_pair(tmpVal, tmpBB)); }; ValueRefList : ResolvedVal { // Used for call statements, and memory insts... $$ = new std::vector(); $$->push_back($1); - CHECK_FOR_ERROR } | ValueRefList ',' ResolvedVal { $$ = $1; @@ -2280,20 +2321,24 @@ OptTailCall : TAIL CALL { CHECK_FOR_ERROR }; - - InstVal : ArithmeticOps Types ValueRef ',' ValueRef { if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint() && !isa((*$2).get())) GEN_ERROR( "Arithmetic operator requires integer, FP, or packed operands!"); - if (isa((*$2).get()) && $1 == Instruction::Rem) - GEN_ERROR("Rem not supported on packed types!"); - $$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5)); + if (isa((*$2).get()) && + ($1 == Instruction::URem || + $1 == Instruction::SRem || + $1 == Instruction::FRem)) + GEN_ERROR("U/S/FRem not supported on packed types!"); + Value* val1 = getVal(*$2, $3); + CHECK_FOR_ERROR + Value* val2 = getVal(*$2, $5); + CHECK_FOR_ERROR + $$ = BinaryOperator::create($1, val1, val2); if ($$ == 0) GEN_ERROR("binary operator returned null!"); delete $2; - CHECK_FOR_ERROR } | LogicalOps Types ValueRef ',' ValueRef { if (!(*$2)->isIntegral()) { @@ -2301,25 +2346,53 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { !cast($2->get())->getElementType()->isIntegral()) GEN_ERROR("Logical operator requires integral operands!"); } - $$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5)); + Value* tmpVal1 = getVal(*$2, $3); + CHECK_FOR_ERROR + Value* tmpVal2 = getVal(*$2, $5); + CHECK_FOR_ERROR + $$ = BinaryOperator::create($1, tmpVal1, tmpVal2); if ($$ == 0) GEN_ERROR("binary operator returned null!"); delete $2; - CHECK_FOR_ERROR } | SetCondOps Types ValueRef ',' ValueRef { if(isa((*$2).get())) { GEN_ERROR( "PackedTypes currently not supported in setcc instructions!"); } - $$ = new SetCondInst($1, getVal(*$2, $3), getVal(*$2, $5)); + Value* tmpVal1 = getVal(*$2, $3); + CHECK_FOR_ERROR + Value* tmpVal2 = getVal(*$2, $5); + CHECK_FOR_ERROR + $$ = new SetCondInst($1, tmpVal1, tmpVal2); if ($$ == 0) GEN_ERROR("binary operator returned null!"); delete $2; + } + | ICMP IPredicates Types ValueRef ',' ValueRef { + if (isa((*$3).get())) + GEN_ERROR("Packed types not supported by icmp instruction"); + Value* tmpVal1 = getVal(*$3, $4); CHECK_FOR_ERROR + Value* tmpVal2 = getVal(*$3, $6); + CHECK_FOR_ERROR + $$ = CmpInst::create($1, $2, tmpVal1, tmpVal2); + if ($$ == 0) + GEN_ERROR("icmp operator returned null!"); + } + | FCMP FPredicates Types ValueRef ',' ValueRef { + if (isa((*$3).get())) + GEN_ERROR("Packed types not supported by fcmp instruction"); + Value* tmpVal1 = getVal(*$3, $4); + CHECK_FOR_ERROR + Value* tmpVal2 = getVal(*$3, $6); + CHECK_FOR_ERROR + $$ = CmpInst::create($1, $2, tmpVal1, tmpVal2); + if ($$ == 0) + GEN_ERROR("fcmp operator returned null!"); } | NOT ResolvedVal { - std::cerr << "WARNING: Use of eliminated 'not' instruction:" + llvm_cerr << "WARNING: Use of eliminated 'not' instruction:" << " Replacing with 'xor'.\n"; Value *Ones = ConstantIntegral::getAllOnesValue($2->getType()); @@ -2336,16 +2409,20 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { GEN_ERROR("Shift amount must be ubyte!"); if (!$2->getType()->isInteger()) GEN_ERROR("Shift constant expression requires integer operand!"); + CHECK_FOR_ERROR; $$ = new ShiftInst($1, $2, $4); CHECK_FOR_ERROR } - | CAST ResolvedVal TO Types { - if (!$4->get()->isFirstClassType()) - GEN_ERROR("cast instruction to a non-primitive type: '" + - $4->get()->getDescription() + "'!"); - $$ = new CastInst($2, *$4); + | CastOps ResolvedVal TO Types { + Value* Val = $2; + const Type* Ty = $4->get(); + if (!Val->getType()->isFirstClassType()) + GEN_ERROR("cast from a non-primitive type: '" + + Val->getType()->getDescription() + "'!"); + if (!Ty->isFirstClassType()) + GEN_ERROR("cast to a non-primitive type: '" + Ty->getDescription() +"'!"); + $$ = CastInst::create($1, $2, $4->get()); delete $4; - CHECK_FOR_ERROR } | SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal { if ($2->getType() != Type::BoolTy) @@ -2361,49 +2438,6 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { delete $4; CHECK_FOR_ERROR } - | 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; - CHECK_FOR_ERROR - } - | 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; - CHECK_FOR_ERROR - } | EXTRACTELEMENT ResolvedVal ',' ResolvedVal { if (!ExtractElementInst::isValidOperands($2, $4)) GEN_ERROR("Invalid extractelement operands!"); @@ -2438,8 +2472,8 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { CHECK_FOR_ERROR } | OptTailCall OptCallingConv TypesV ValueRef '(' ValueRefListE ')' { - const PointerType *PFTy; - const FunctionType *Ty; + const PointerType *PFTy = 0; + const FunctionType *Ty = 0; if (!(PFTy = dyn_cast($3->get())) || !(Ty = dyn_cast(PFTy->getElementType()))) { @@ -2462,6 +2496,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { } Value *V = getVal(PFTy, $4); // Get the function we're calling... + CHECK_FOR_ERROR // Create the call node... if (!$6) { // Has no arguments? @@ -2527,9 +2562,10 @@ MemoryInst : MALLOC Types OptCAlign { CHECK_FOR_ERROR } | MALLOC Types ',' UINT ValueRef OptCAlign { - $$ = new MallocInst(*$2, getVal($4, $5), $6); - delete $2; + Value* tmpVal = getVal($4, $5); CHECK_FOR_ERROR + $$ = new MallocInst(*$2, tmpVal, $6); + delete $2; } | ALLOCA Types OptCAlign { $$ = new AllocaInst(*$2, 0, $3); @@ -2537,9 +2573,10 @@ MemoryInst : MALLOC Types OptCAlign { CHECK_FOR_ERROR } | ALLOCA Types ',' UINT ValueRef OptCAlign { - $$ = new AllocaInst(*$2, getVal($4, $5), $6); - delete $2; + Value* tmpVal = getVal($4, $5); CHECK_FOR_ERROR + $$ = new AllocaInst(*$2, tmpVal, $6); + delete $2; } | FREE ResolvedVal { if (!isa($2->getType())) @@ -2556,9 +2593,10 @@ MemoryInst : MALLOC Types OptCAlign { if (!cast($3->get())->getElementType()->isFirstClassType()) GEN_ERROR("Can't load from pointer of non-first-class type: " + (*$3)->getDescription()); - $$ = new LoadInst(getVal(*$3, $4), "", $1); - delete $3; + Value* tmpVal = getVal(*$3, $4); CHECK_FOR_ERROR + $$ = new LoadInst(tmpVal, "", $1); + delete $3; } | OptVolatile STORE ResolvedVal ',' Types ValueRef { const PointerType *PT = dyn_cast($5->get()); @@ -2570,31 +2608,23 @@ MemoryInst : MALLOC Types OptCAlign { GEN_ERROR("Can't store '" + $3->getType()->getDescription() + "' into space of type '" + ElTy->getDescription() + "'!"); - $$ = new StoreInst($3, getVal(*$5, $6), $1); - delete $5; + Value* tmpVal = getVal(*$5, $6); CHECK_FOR_ERROR + $$ = new StoreInst($3, tmpVal, $1); + delete $5; } | GETELEMENTPTR Types ValueRef IndexList { if (!isa($2->get())) GEN_ERROR("getelementptr insn requires pointer operand!"); - // LLVM 1.2 and earlier used ubyte struct indices. Convert any ubyte struct - // indices to uint struct indices for compatibility. - generic_gep_type_iterator::iterator> - GTI = gep_type_begin($2->get(), $4->begin(), $4->end()), - GTE = gep_type_end($2->get(), $4->begin(), $4->end()); - for (unsigned i = 0, e = $4->size(); i != e && GTI != GTE; ++i, ++GTI) - if (isa(*GTI)) // Only change struct indices - if (ConstantUInt *CUI = dyn_cast((*$4)[i])) - if (CUI->getType() == Type::UByteTy) - (*$4)[i] = ConstantExpr::getCast(CUI, Type::UIntTy); - if (!GetElementPtrInst::getIndexedType(*$2, *$4, true)) GEN_ERROR("Invalid getelementptr indices for type '" + (*$2)->getDescription()+ "'!"); - $$ = new GetElementPtrInst(getVal(*$2, $3), *$4); - delete $2; delete $4; + Value* tmpVal = getVal(*$2, $3); CHECK_FOR_ERROR + $$ = new GetElementPtrInst(tmpVal, *$4); + delete $2; + delete $4; };