diff options
author | Chris Lattner <sabre@nondot.org> | 2003-10-18 05:53:13 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2003-10-18 05:53:13 +0000 |
commit | 99e7ab72c8909469141358552ece13d701d17274 (patch) | |
tree | a4ae61d60cbc33bf65861fb839c585de8f23bea3 /lib/AsmParser/llvmAsmParser.y | |
parent | 8d1a81d524e3c2a79ffb60c847e486f8536c2e6d (diff) | |
download | external_llvm-99e7ab72c8909469141358552ece13d701d17274.zip external_llvm-99e7ab72c8909469141358552ece13d701d17274.tar.gz external_llvm-99e7ab72c8909469141358552ece13d701d17274.tar.bz2 |
New revised variable argument handling support
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9219 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AsmParser/llvmAsmParser.y')
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y | 107 |
1 files changed, 104 insertions, 3 deletions
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index b14d6a7..efb9d3e 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -37,6 +37,14 @@ std::string CurFilename; #define YYERROR_VERBOSE 1 +// HACK ALERT: This variable is used to implement the automatic conversion of +// variable argument instructions from their old to new forms. When this +// compatiblity "Feature" is removed, this should be too. +// +static BasicBlock *CurBB; +static bool ObsoleteVarArgs; + + // This contains info used when building the body of a function. It is // destroyed when the function is completed. // @@ -595,11 +603,76 @@ Module *RunVMAsmParser(const std::string &Filename, FILE *F) { llvmAsmin = F; CurFilename = Filename; llvmAsmlineno = 1; // Reset the current line number... + ObsoleteVarArgs = false; // Allocate a new module to read CurModule.CurrentModule = new Module(Filename); yyparse(); // Parse the file. + Module *Result = ParserResult; + + // Check to see if they called va_start but not va_arg.. + if (!ObsoleteVarArgs) + if (Function *F = Result->getNamedFunction("llvm.va_start")) + if (F->asize() == 1) { + std::cerr << "WARNING: this file uses obsolete features. " + << "Assemble and disassemble to update it.\n"; + ObsoleteVarArgs = true; + } + + + if (ObsoleteVarArgs) { + // If the user is making use of obsolete varargs intrinsics, adjust them for + // the user. + if (Function *F = Result->getNamedFunction("llvm.va_start")) { + assert(F->asize() == 1 && "Obsolete va_start takes 1 argument!"); + + const Type *RetTy = F->getFunctionType()->getParamType(0); + RetTy = cast<PointerType>(RetTy)->getElementType(); + Function *NF = Result->getOrInsertFunction("llvm.va_start", RetTy, 0); + + while (!F->use_empty()) { + CallInst *CI = cast<CallInst>(F->use_back()); + Value *V = new CallInst(NF, "", CI); + new StoreInst(V, CI->getOperand(1), CI); + CI->getParent()->getInstList().erase(CI); + } + Result->getFunctionList().erase(F); + } + + if (Function *F = Result->getNamedFunction("llvm.va_end")) { + assert(F->asize() == 1 && "Obsolete va_end takes 1 argument!"); + const Type *ArgTy = F->getFunctionType()->getParamType(0); + ArgTy = cast<PointerType>(ArgTy)->getElementType(); + Function *NF = Result->getOrInsertFunction("llvm.va_end", Type::VoidTy, + ArgTy, 0); + + while (!F->use_empty()) { + CallInst *CI = cast<CallInst>(F->use_back()); + Value *V = new LoadInst(CI->getOperand(1), "", CI); + new CallInst(NF, V, "", CI); + CI->getParent()->getInstList().erase(CI); + } + Result->getFunctionList().erase(F); + } + + if (Function *F = Result->getNamedFunction("llvm.va_copy")) { + assert(F->asize() == 2 && "Obsolete va_copy takes 2 argument!"); + const Type *ArgTy = F->getFunctionType()->getParamType(0); + ArgTy = cast<PointerType>(ArgTy)->getElementType(); + Function *NF = Result->getOrInsertFunction("llvm.va_copy", ArgTy, + ArgTy, 0); + + while (!F->use_empty()) { + CallInst *CI = cast<CallInst>(F->use_back()); + Value *V = new CallInst(NF, CI->getOperand(2), "", CI); + new StoreInst(V, CI->getOperand(1), CI); + CI->getParent()->getInstList().erase(CI); + } + Result->getFunctionList().erase(F); + } + } + llvmAsmin = stdin; // F is about to go away, don't use it anymore... ParserResult = 0; @@ -712,7 +785,8 @@ Module *RunVMAsmParser(const std::string &Filename, FILE *F) { // Other Operators %type <OtherOpVal> ShiftOps -%token <OtherOpVal> PHI CALL CAST SHL SHR VA_ARG +%token <OtherOpVal> PHI CALL CAST SHL SHR VAARG VANEXT +%token VA_ARG // FIXME: OBSOLETE %start Module %% @@ -1452,7 +1526,7 @@ InstructionList : InstructionList Inst { $$ = $1; } | /* empty */ { - $$ = new BasicBlock(); + $$ = CurBB = new BasicBlock(); }; BBTerminatorInst : RET ResolvedVal { // Return with a result... @@ -1643,7 +1717,34 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { delete $4; } | VA_ARG ResolvedVal ',' Types { - $$ = new VarArgInst($2, *$4); + // FIXME: This is emulation code for an obsolete syntax. This should be + // removed at some point. + if (!ObsoleteVarArgs) { + std::cerr << "WARNING: this file uses obsolete features. " + << "Assemble and disassemble to update it.\n"; + ObsoleteVarArgs = true; + } + + // First, load the valist... + Instruction *CurVAList = new LoadInst($2, ""); + CurBB->getInstList().push_back(CurVAList); + + // Emit the vaarg instruction. + $$ = new VAArgInst(CurVAList, *$4); + + // Now we must advance the pointer and update it in memory. + Instruction *TheVANext = new VANextInst(CurVAList, *$4); + CurBB->getInstList().push_back(TheVANext); + + CurBB->getInstList().push_back(new StoreInst(TheVANext, $2)); + delete $4; + } + | VAARG ResolvedVal ',' Types { + $$ = new VAArgInst($2, *$4); + delete $4; + } + | VANEXT ResolvedVal ',' Types { + $$ = new VANextInst($2, *$4); delete $4; } | PHI PHIList { |