diff --git a/lib/Analysis/DataStructure/Local.cpp b/lib/Analysis/DataStructure/Local.cpp index 106f3a10345..dfd34297f3f 100644 --- a/lib/Analysis/DataStructure/Local.cpp +++ b/lib/Analysis/DataStructure/Local.cpp @@ -119,7 +119,6 @@ namespace { void visitInstruction(Instruction &I); void visitCallSite(CallSite CS); - void visitVANextInst(VANextInst &I); void visitVAArgInst(VAArgInst &I); void MergeConstantInitIntoNode(DSNodeHandle &NH, Constant *C); @@ -475,11 +474,8 @@ void GraphBuilder::visitReturnInst(ReturnInst &RI) { RetNode->mergeWith(getValueDest(*RI.getOperand(0))); } -void GraphBuilder::visitVANextInst(VANextInst &I) { - getValueDest(*I.getOperand(0)).mergeWith(getValueDest(I)); -} - void GraphBuilder::visitVAArgInst(VAArgInst &I) { + //FIXME: also updates the argument DSNodeHandle Ptr = getValueDest(*I.getOperand(0)); if (Ptr.isNull()) return; diff --git a/lib/Analysis/IPA/Andersens.cpp b/lib/Analysis/IPA/Andersens.cpp index 8362be596ba..c33a3254aa7 100644 --- a/lib/Analysis/IPA/Andersens.cpp +++ b/lib/Analysis/IPA/Andersens.cpp @@ -330,7 +330,6 @@ namespace { void visitCastInst(CastInst &CI); void visitSetCondInst(SetCondInst &SCI) {} // NOOP! void visitSelectInst(SelectInst &SI); - void visitVANext(VANextInst &I); void visitVAArg(VAArgInst &I); void visitInstruction(Instruction &I); }; @@ -867,10 +866,6 @@ void Andersens::visitSelectInst(SelectInst &SI) { } } -void Andersens::visitVANext(VANextInst &I) { - // FIXME: Implement - assert(0 && "vanext not handled yet!"); -} void Andersens::visitVAArg(VAArgInst &I) { assert(0 && "vaarg not handled yet!"); } diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l index 062e00c4197..f9866f2bbcd 100644 --- a/lib/AsmParser/Lexer.l +++ b/lib/AsmParser/Lexer.l @@ -253,9 +253,9 @@ cast { RET_TOK(OtherOpVal, Cast, CAST); } select { RET_TOK(OtherOpVal, Select, SELECT); } shl { RET_TOK(OtherOpVal, Shl, SHL); } shr { RET_TOK(OtherOpVal, Shr, SHR); } -vanext { RET_TOK(OtherOpVal, VANext, VANEXT); } -vaarg { RET_TOK(OtherOpVal, VAArg , VAARG); } - +vanext { return VANEXT_old; } +vaarg { return VAARG_old; } +va_arg { RET_TOK(OtherOpVal, VAArg , VAARG); } ret { RET_TOK(TermOpVal, Ret, RET); } br { RET_TOK(TermOpVal, Br, BR); } switch { RET_TOK(TermOpVal, Switch, SWITCH); } diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index d73b008416a..f59475cd130 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -47,6 +47,10 @@ static Module *ParserResult; #define YYERROR_VERBOSE 1 +static bool ObsoleteVarArgs; +static BasicBlock* CurBB; + + // This contains info used when building the body of a function. It is // destroyed when the function is completed. // @@ -723,6 +727,7 @@ static PATypeHolder HandleUpRefs(const Type *ty) { static Module * RunParser(Module * M) { llvmAsmlineno = 1; // Reset the current line number... + ObsoleteVarArgs = false; CurModule.CurrentModule = M; yyparse(); // Parse the file, potentially throwing exception @@ -730,6 +735,80 @@ static PATypeHolder HandleUpRefs(const Type *ty) { Module *Result = ParserResult; ParserResult = 0; + if(ObsoleteVarArgs) { + if(Function* F = Result->getNamedFunction("llvm.va_start")) { + assert(F->arg_size() == 0 && "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, 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")) { + assert(F->arg_size() == 1 && "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, 0); + + while (!F->use_empty()) { + CallInst* CI = cast(F->use_back()); + AllocaInst* bar = new AllocaInst(ArgTy, 0, "vaend.fix.1", CI); + new CallInst(NF, bar, "", CI); + CI->getParent()->getInstList().erase(CI); + } + Result->getFunctionList().erase(F); + } + + if(Function* F = Result->getNamedFunction("llvm.va_copy")) { + assert(F->arg_size() == 1 && "Obsolete va_copy takes 1 argument!"); + //foo = vacopy(bar) + // -> + //a = alloca 1 of typeof(foo) + //vacopy(a, bar) + //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); + + while (!F->use_empty()) { + CallInst* CI = cast(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); + CI->replaceAllUsesWith(foo); + CI->getParent()->getInstList().erase(CI); + } + Result->getFunctionList().erase(F); + } + } + return Result; } @@ -866,7 +945,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { // Other Operators %type ShiftOps -%token PHI_TOK CAST SELECT SHL SHR VAARG VANEXT +%token PHI_TOK CAST SELECT SHL SHR VAARG +%token VAARG_old VANEXT_old //OBSOLETE %start Module @@ -1727,7 +1807,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 @@ -1737,7 +1817,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 @@ -1964,8 +2044,45 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { $$ = 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, 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, 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; } | PHI_TOK PHIList { diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index 7e5bed69897..d730ca256a1 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -658,10 +658,43 @@ void BytecodeReader::ParseInstruction(std::vector &Oprnds, Result = new VAArgInst(getValue(iType, Oprnds[0]), getSanitizedType(Oprnds[1])); break; - case Instruction::VANext: - Result = new VANextInst(getValue(iType, Oprnds[0]), - getSanitizedType(Oprnds[1])); + case 32: { //VANext_old + const Type* ArgTy = getValue(iType, Oprnds[0])->getType(); + Function* NF = TheModule->getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, 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"); + BB->getInstList().push_back(foo); + CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0])); + BB->getInstList().push_back(bar); + BB->getInstList().push_back(new StoreInst(bar, foo)); + Instruction* tmp = new VAArgInst(foo, getSanitizedType(Oprnds[1])); + BB->getInstList().push_back(tmp); + Result = new LoadInst(foo); break; + } + case 33: { //VAArg_old + const Type* ArgTy = getValue(iType, Oprnds[0])->getType(); + Function* NF = TheModule->getOrInsertFunction("llvm.va_copy", ArgTy, ArgTy, 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"); + BB->getInstList().push_back(foo); + CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0])); + BB->getInstList().push_back(bar); + BB->getInstList().push_back(new StoreInst(bar, foo)); + Result = new VAArgInst(foo, getSanitizedType(Oprnds[1])); + break; + } case Instruction::Cast: Result = new CastInst(getValue(iType, Oprnds[0]), getSanitizedType(Oprnds[1])); diff --git a/lib/Bytecode/Reader/ReaderWrappers.cpp b/lib/Bytecode/Reader/ReaderWrappers.cpp index 68239362094..8d1f3849861 100644 --- a/lib/Bytecode/Reader/ReaderWrappers.cpp +++ b/lib/Bytecode/Reader/ReaderWrappers.cpp @@ -148,6 +148,100 @@ BytecodeStdinReader::BytecodeStdinReader( BytecodeHandler* H ) ParseBytecode(FileBuf, FileData.size(), ""); } +//===----------------------------------------------------------------------===// +// Varargs transmogrification code... +// + +// CheckVarargs - This is used to automatically translate old-style varargs to +// new style varargs for backwards compatibility. +static ModuleProvider* CheckVarargs(ModuleProvider* MP) { + Module* M = MP->getModule(); + + // check to see if va_start takes arguements... + Function* F = M->getNamedFunction("llvm.va_start"); + if(F == 0) return MP; //No varargs use, just return. + + if (F->getFunctionType()->getNumParams() == 1) + return MP; // Modern varargs processing, just return. + + // If we get to this point, we know that we have an old-style module. + // Materialize the whole thing to perform the rewriting. + MP->materializeModule(); + + if(Function* F = M->getNamedFunction("llvm.va_start")) { + assert(F->arg_size() == 0 && "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 = M->getOrInsertFunction("llvm.va_start", + RetTy, ArgTyPtr, 0); + + for(Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E;) + if (CallInst* CI = dyn_cast(*I++)) { + 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); + } + F->setName(""); + } + + if(Function* F = M->getNamedFunction("llvm.va_end")) { + assert(F->arg_size() == 1 && "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 = M->getOrInsertFunction("llvm.va_end", + RetTy, ArgTyPtr, 0); + + for(Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E;) + if (CallInst* CI = dyn_cast(*I++)) { + AllocaInst* bar = new AllocaInst(ArgTy, 0, "vaend.fix.1", CI); + new CallInst(NF, bar, "", CI); + CI->getParent()->getInstList().erase(CI); + } + F->setName(""); + } + + if(Function* F = M->getNamedFunction("llvm.va_copy")) { + assert(F->arg_size() == 1 && "Obsolete va_copy takes 1 argument!"); + //foo = vacopy(bar) + // -> + //a = alloca 1 of typeof(foo) + //vacopy(a, bar) + //foo = load a + + const Type* RetTy = Type::getPrimitiveType(Type::VoidTyID); + const Type* ArgTy = F->getFunctionType()->getReturnType(); + const Type* ArgTyPtr = PointerType::get(ArgTy); + Function* NF = M->getOrInsertFunction("llvm.va_copy", + RetTy, ArgTyPtr, ArgTy, 0); + + for(Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E;) + if (CallInst* CI = dyn_cast(*I++)) { + 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); + CI->replaceAllUsesWith(foo); + CI->getParent()->getInstList().erase(CI); + } + F->setName(""); + } + return MP; +} + //===----------------------------------------------------------------------===// // Wrapper functions //===----------------------------------------------------------------------===// @@ -159,7 +253,8 @@ llvm::getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length, const std::string &ModuleID, BytecodeHandler* H ) { - return new BytecodeBufferReader(Buffer, Length, ModuleID, H); + return CheckVarargs( + new BytecodeBufferReader(Buffer, Length, ModuleID, H)); } /// ParseBytecodeBuffer - Parse a given bytecode buffer @@ -182,9 +277,9 @@ Module *llvm::ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length, ModuleProvider *llvm::getBytecodeModuleProvider(const std::string &Filename, BytecodeHandler* H) { if (Filename != std::string("-")) // Read from a file... - return new BytecodeFileReader(Filename,H); + return CheckVarargs(new BytecodeFileReader(Filename,H)); else // Read from stdin - return new BytecodeStdinReader(H); + return CheckVarargs(new BytecodeStdinReader(H)); } /// ParseBytecodeFile - Parse the given bytecode file diff --git a/lib/Bytecode/Writer/SlotCalculator.cpp b/lib/Bytecode/Writer/SlotCalculator.cpp index fbeb50c03ae..c6aba09fe51 100644 --- a/lib/Bytecode/Writer/SlotCalculator.cpp +++ b/lib/Bytecode/Writer/SlotCalculator.cpp @@ -187,8 +187,6 @@ void SlotCalculator::processModule() { !isa(I->getOperand(op))) getOrCreateSlot(I->getOperand(op)); getOrCreateSlot(I->getType()); - if (const VANextInst *VAN = dyn_cast(&*I)) - getOrCreateSlot(VAN->getArgType()); } processSymbolTableConstants(&F->getSymbolTable()); } @@ -320,8 +318,6 @@ void SlotCalculator::incorporateFunction(const Function *F) { getOrCreateSlot(BB); for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) { getOrCreateSlot(I); - if (const VANextInst *VAN = dyn_cast(I)) - getOrCreateSlot(VAN->getArgType()); } } @@ -472,8 +468,6 @@ void SlotCalculator::buildCompactionTable(const Function *F) { for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) if (isa(I->getOperand(op))) getOrCreateCompactionTableSlot(I->getOperand(op)); - if (const VANextInst *VAN = dyn_cast(&*I)) - getOrCreateCompactionTableSlot(VAN->getArgType()); } // Do the types in the symbol table diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp index fb5a1aa6031..90cfa96462a 100644 --- a/lib/Bytecode/Writer/Writer.cpp +++ b/lib/Bytecode/Writer/Writer.cpp @@ -439,7 +439,7 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I, output_typeid(Type); // Result type unsigned NumArgs = I->getNumOperands(); - output_vbr(NumArgs + (isa(I) || isa(I) || + output_vbr(NumArgs + (isa(I) || isa(I) || Opcode == 56 || Opcode == 58)); if (!isa(&I)) { @@ -453,10 +453,6 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I, int Slot = Table.getSlot(I->getType()); assert(Slot != -1 && "Cast return type unknown?"); output_typeid((unsigned)Slot); - } else if (const VANextInst *VAI = dyn_cast(I)) { - int Slot = Table.getSlot(VAI->getArgType()); - assert(Slot != -1 && "VarArg argument type unknown?"); - output_typeid((unsigned)Slot); } else if (Opcode == 56) { // Invoke escape sequence output_vbr(cast(I)->getCallingConv()); } else if (Opcode == 58) { // Call escape sequence @@ -704,11 +700,6 @@ void BytecodeWriter::outputInstruction(const Instruction &I) { assert(Slots[1] != ~0U && "Cast return type unknown?"); if (Slots[1] > MaxOpSlot) MaxOpSlot = Slots[1]; NumOperands++; - } else if (const VANextInst *VANI = dyn_cast(&I)) { - Slots[1] = Table.getSlot(VANI->getArgType()); - assert(Slots[1] != ~0U && "va_next return type unknown?"); - if (Slots[1] > MaxOpSlot) MaxOpSlot = Slots[1]; - NumOperands++; } else if (const GetElementPtrInst *GEP = dyn_cast(&I)) { // We need to encode the type of sequential type indices into their slot # unsigned Idx = 1; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 2e3febade9a..0c94ea74cd9 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -356,7 +356,6 @@ public: void visitCall(CallInst &I); void visitVAStart(CallInst &I); - void visitVANext(VANextInst &I); void visitVAArg(VAArgInst &I); void visitVAEnd(CallInst &I); void visitVACopy(CallInst &I); @@ -839,7 +838,7 @@ void SelectionDAGLowering::visitFree(FreeInst &I) { } std::pair -TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) { +TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest) { // We have no sane default behavior, just emit a useful error message and bail // out. std::cerr << "Variable arguments handling not implemented on this target!\n"; @@ -854,13 +853,16 @@ SDOperand TargetLowering::LowerVAEnd(SDOperand Chain, SDOperand L, } std::pair -TargetLowering::LowerVACopy(SDOperand Chain, SDOperand L, SelectionDAG &DAG) { - // Default to returning the input list. - return std::make_pair(L, Chain); +TargetLowering::LowerVACopy(SDOperand Chain, SDOperand Src, SDOperand Dest, + SelectionDAG &DAG) { + // We have no sane default behavior, just emit a useful error message and bail + // out. + std::cerr << "Variable arguments handling not implemented on this target!\n"; + abort(); } std::pair -TargetLowering::LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, +TargetLowering::LowerVAArgNext(SDOperand Chain, SDOperand VAList, const Type *ArgTy, SelectionDAG &DAG) { // We have no sane default behavior, just emit a useful error message and bail // out. @@ -871,23 +873,15 @@ TargetLowering::LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, void SelectionDAGLowering::visitVAStart(CallInst &I) { - std::pair Result = TLI.LowerVAStart(getRoot(), DAG); + std::pair Result = TLI.LowerVAStart(getRoot(), DAG, getValue(I.getOperand(1))); setValue(&I, Result.first); DAG.setRoot(Result.second); } void SelectionDAGLowering::visitVAArg(VAArgInst &I) { std::pair Result = - TLI.LowerVAArgNext(false, getRoot(), getValue(I.getOperand(0)), - I.getType(), DAG); - setValue(&I, Result.first); - DAG.setRoot(Result.second); -} - -void SelectionDAGLowering::visitVANext(VANextInst &I) { - std::pair Result = - TLI.LowerVAArgNext(true, getRoot(), getValue(I.getOperand(0)), - I.getArgType(), DAG); + TLI.LowerVAArgNext(getRoot(), getValue(I.getOperand(0)), + I.getType(), DAG); setValue(&I, Result.first); DAG.setRoot(Result.second); } @@ -898,7 +892,7 @@ void SelectionDAGLowering::visitVAEnd(CallInst &I) { void SelectionDAGLowering::visitVACopy(CallInst &I) { std::pair Result = - TLI.LowerVACopy(getRoot(), getValue(I.getOperand(1)), DAG); + TLI.LowerVACopy(getRoot(), getValue(I.getOperand(2)), getValue(I.getOperand(1)), DAG); setValue(&I, Result.first); DAG.setRoot(Result.second); } diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 11608b6bfa7..a41d12af4fd 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -988,18 +988,6 @@ void Interpreter::visitCastInst(CastInst &I) { SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF); } -void Interpreter::visitVANextInst(VANextInst &I) { - ExecutionContext &SF = ECStack.back(); - - // Get the incoming valist parameter. LLI treats the valist as a - // (ec-stack-depth var-arg-index) pair. - GenericValue VAList = getOperandValue(I.getOperand(0), SF); - - // Move the pointer to the next vararg. - ++VAList.UIntPairVal.second; - SetValue(&I, VAList, SF); -} - #define IMPLEMENT_VAARG(TY) \ case Type::TY##TyID: Dest.TY##Val = Src.TY##Val; break @@ -1033,6 +1021,9 @@ void Interpreter::visitVAArgInst(VAArgInst &I) { // Set the Value of this Instruction. SetValue(&I, Dest, SF); + + // Move the pointer to the next vararg. + ++VAList.UIntPairVal.second; } //===----------------------------------------------------------------------===// diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index 2e83f5e7c6d..180d0921b72 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -153,7 +153,6 @@ public: void visitShl(ShiftInst &I); void visitShr(ShiftInst &I); - void visitVANextInst(VANextInst &I); void visitVAArgInst(VAArgInst &I); void visitInstruction(Instruction &I) { std::cerr << I; diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp index e521a033a0a..de135cb3c2e 100644 --- a/lib/Target/Alpha/AlphaISelPattern.cpp +++ b/lib/Target/Alpha/AlphaISelPattern.cpp @@ -72,7 +72,8 @@ namespace { // AlphaTargetLowering - Alpha Implementation of the TargetLowering interface namespace { class AlphaTargetLowering : public TargetLowering { - int VarArgsFrameIndex; // FrameIndex for start of varargs area. + int VarArgsOffset; // What is the offset to the first vaarg + int VarArgsBase; // What is the base FrameIndex unsigned GP; //GOT vreg public: AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) { @@ -151,10 +152,10 @@ namespace { SelectionDAG &DAG); virtual std::pair - LowerVAStart(SDOperand Chain, SelectionDAG &DAG); + LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest); virtual std::pair - LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, + LowerVAArgNext(SDOperand Chain, SDOperand VAList, const Type *ArgTy, SelectionDAG &DAG); virtual std::pair @@ -300,12 +301,14 @@ AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) // If the functions takes variable number of arguments, copy all regs to stack if (F.isVarArg()) { + VarArgsOffset = count * 8; std::vector LS; for (int i = 0; i < 6; ++i) { if (args_int[i] < 1024) args_int[i] = AddLiveIn(MF,args_int[i], getRegClassFor(MVT::i64)); SDOperand argt = DAG.getCopyFromReg(args_int[i], MVT::i64, DAG.getRoot()); int FI = MFI->CreateFixedObject(8, -8 * (6 - i)); + if (i == 0) VarArgsBase = FI; SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64); LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(), argt, SDFI, DAG.getSrcValue(NULL))); @@ -393,15 +396,34 @@ AlphaTargetLowering::LowerCallTo(SDOperand Chain, } std::pair -AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) { - //vastart just returns the address of the VarArgsFrameIndex slot. - return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain); +AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest) { + // vastart just stores the address of the VarArgsBase and VarArgsOffset + SDOperand FR = DAG.getFrameIndex(VarArgsBase, MVT::i32); + SDOperand S1 = DAG.getNode(ISD::STORE, MVT::Other, Chain, FR, Dest, DAG.getSrcValue(NULL)); + SDOperand SA2 = DAG.getNode(ISD::ADD, MVT::i64, Dest, DAG.getConstant(8, MVT::i64)); + SDOperand S2 = DAG.getNode(ISD::STORE, MVT::Other, S1, + DAG.getConstant(VarArgsOffset, MVT::i64), SA2, + DAG.getSrcValue(NULL)); + + return std::make_pair(S2, S2); } std::pair AlphaTargetLowering:: -LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, +LowerVAArgNext(SDOperand Chain, SDOperand VAList, const Type *ArgTy, SelectionDAG &DAG) { - abort(); + //FIXME: For now, ignore FP + SDOperand Base = DAG.getLoad(MVT::i64, Chain, VAList, DAG.getSrcValue(NULL)); + SDOperand Tmp = DAG.getNode(ISD::ADD, MVT::i64, VAList, + DAG.getConstant(8, MVT::i64)); + SDOperand Offset = DAG.getLoad(MVT::i64, Chain, Tmp, DAG.getSrcValue(NULL)); + SDOperand DataPtr = DAG.getNode(ISD::ADD, MVT::i64, Base, Offset); + SDOperand Result = DAG.getLoad(MVT::i64, Chain, DataPtr, + DAG.getSrcValue(NULL)); + SDOperand NewOffset = DAG.getNode(ISD::ADD, MVT::i64, Offset, + DAG.getConstant(8, MVT::i64)); + SDOperand Update = DAG.getNode(ISD::STORE, MVT::Other, Result, NewOffset, + Tmp, DAG.getSrcValue(NULL)); + return std::make_pair(Result, Update); } diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 282d013047c..65979933dbb 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -145,7 +145,7 @@ namespace { // emit it inline where it would go. if (I.getType() == Type::VoidTy || !I.hasOneUse() || isa(I) || isa(I) || isa(I) || - isa(I) || isa(I) || isa(I)) + isa(I) || isa(I)) // Don't inline a load across a store or other bad things! return false; @@ -196,7 +196,6 @@ namespace { void visitLoadInst (LoadInst &I); void visitStoreInst (StoreInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); - void visitVANextInst(VANextInst &I); void visitVAArgInst (VAArgInst &I); void visitInstruction(Instruction &I) { @@ -1469,7 +1468,10 @@ void CWriter::visitCallInst(CallInst &I) { case Intrinsic::vastart: Out << "0; "; - Out << "va_start(*(va_list*)&" << Mang->getValueName(&I) << ", "; + // Out << "va_start(*(va_list*)&" << Mang->getValueName(&I) << ", "; + Out << "va_start(*(va_list*)"; + writeOperand(I.getOperand(1)); + Out << ", "; // Output the last argument to the enclosing function... if (I.getParent()->getParent()->arg_empty()) { std::cerr << "The C backend does not currently support zero " @@ -1482,7 +1484,7 @@ void CWriter::visitCallInst(CallInst &I) { return; case Intrinsic::vaend: if (!isa(I.getOperand(1))) { - Out << "va_end(*(va_list*)&"; + Out << "0; va_end(*(va_list*)"; writeOperand(I.getOperand(1)); Out << ')'; } else { @@ -1490,10 +1492,11 @@ void CWriter::visitCallInst(CallInst &I) { } return; case Intrinsic::vacopy: - Out << "0;"; - Out << "va_copy(*(va_list*)&" << Mang->getValueName(&I) << ", "; - Out << "*(va_list*)&"; + Out << "0; "; + Out << "va_copy(*(va_list*)"; writeOperand(I.getOperand(1)); + Out << ", *(va_list*)&"; + writeOperand(I.getOperand(2)); Out << ')'; return; case Intrinsic::returnaddress: @@ -1710,20 +1713,12 @@ void CWriter::visitGetElementPtrInst(GetElementPtrInst &I) { gep_type_end(I)); } -void CWriter::visitVANextInst(VANextInst &I) { - Out << Mang->getValueName(I.getOperand(0)); - Out << "; va_arg(*(va_list*)&" << Mang->getValueName(&I) << ", "; - printType(Out, I.getArgType()); - Out << ')'; -} - void CWriter::visitVAArgInst(VAArgInst &I) { - Out << "0;\n"; - Out << "{ va_list Tmp; va_copy(Tmp, *(va_list*)&"; + Out << "va_arg(*(va_list*)"; writeOperand(I.getOperand(0)); - Out << ");\n " << Mang->getValueName(&I) << " = va_arg(Tmp, "; + Out << ", "; printType(Out, I.getType()); - Out << ");\n va_end(Tmp); }"; + Out << ");\n "; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp index 282d013047c..65979933dbb 100644 --- a/lib/Target/CBackend/Writer.cpp +++ b/lib/Target/CBackend/Writer.cpp @@ -145,7 +145,7 @@ namespace { // emit it inline where it would go. if (I.getType() == Type::VoidTy || !I.hasOneUse() || isa(I) || isa(I) || isa(I) || - isa(I) || isa(I) || isa(I)) + isa(I) || isa(I)) // Don't inline a load across a store or other bad things! return false; @@ -196,7 +196,6 @@ namespace { void visitLoadInst (LoadInst &I); void visitStoreInst (StoreInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); - void visitVANextInst(VANextInst &I); void visitVAArgInst (VAArgInst &I); void visitInstruction(Instruction &I) { @@ -1469,7 +1468,10 @@ void CWriter::visitCallInst(CallInst &I) { case Intrinsic::vastart: Out << "0; "; - Out << "va_start(*(va_list*)&" << Mang->getValueName(&I) << ", "; + // Out << "va_start(*(va_list*)&" << Mang->getValueName(&I) << ", "; + Out << "va_start(*(va_list*)"; + writeOperand(I.getOperand(1)); + Out << ", "; // Output the last argument to the enclosing function... if (I.getParent()->getParent()->arg_empty()) { std::cerr << "The C backend does not currently support zero " @@ -1482,7 +1484,7 @@ void CWriter::visitCallInst(CallInst &I) { return; case Intrinsic::vaend: if (!isa(I.getOperand(1))) { - Out << "va_end(*(va_list*)&"; + Out << "0; va_end(*(va_list*)"; writeOperand(I.getOperand(1)); Out << ')'; } else { @@ -1490,10 +1492,11 @@ void CWriter::visitCallInst(CallInst &I) { } return; case Intrinsic::vacopy: - Out << "0;"; - Out << "va_copy(*(va_list*)&" << Mang->getValueName(&I) << ", "; - Out << "*(va_list*)&"; + Out << "0; "; + Out << "va_copy(*(va_list*)"; writeOperand(I.getOperand(1)); + Out << ", *(va_list*)&"; + writeOperand(I.getOperand(2)); Out << ')'; return; case Intrinsic::returnaddress: @@ -1710,20 +1713,12 @@ void CWriter::visitGetElementPtrInst(GetElementPtrInst &I) { gep_type_end(I)); } -void CWriter::visitVANextInst(VANextInst &I) { - Out << Mang->getValueName(I.getOperand(0)); - Out << "; va_arg(*(va_list*)&" << Mang->getValueName(&I) << ", "; - printType(Out, I.getArgType()); - Out << ')'; -} - void CWriter::visitVAArgInst(VAArgInst &I) { - Out << "0;\n"; - Out << "{ va_list Tmp; va_copy(Tmp, *(va_list*)&"; + Out << "va_arg(*(va_list*)"; writeOperand(I.getOperand(0)); - Out << ");\n " << Mang->getValueName(&I) << " = va_arg(Tmp, "; + Out << ", "; printType(Out, I.getType()); - Out << ");\n va_end(Tmp); }"; + Out << ");\n "; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/IA64/IA64ISelPattern.cpp b/lib/Target/IA64/IA64ISelPattern.cpp index 2e34b36715f..0830468a959 100644 --- a/lib/Target/IA64/IA64ISelPattern.cpp +++ b/lib/Target/IA64/IA64ISelPattern.cpp @@ -114,12 +114,16 @@ namespace { SelectionDAG &DAG); virtual std::pair - LowerVAStart(SDOperand Chain, SelectionDAG &DAG); + LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest); virtual std::pair - LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, + LowerVAArgNext(SDOperand Chain, SDOperand VAList, const Type *ArgTy, SelectionDAG &DAG); + virtual std::pair + LowerVACopy(SDOperand Chain, SDOperand Src, SDOperand Dest, + SelectionDAG &DAG); + virtual std::pair LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, SelectionDAG &DAG); @@ -380,34 +384,44 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, } std::pair -IA64TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) { - // vastart just returns the address of the VarArgsFrameIndex slot. - return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain); +IA64TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest) { + // vastart just stores the address of the VarArgsFrameIndex slot. + SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64); + SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain, FR, Dest, DAG.getSrcValue(NULL)); + return std::make_pair(Result, Result); } std::pair IA64TargetLowering:: -LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, +LowerVAArgNext(SDOperand Chain, SDOperand VAList, const Type *ArgTy, SelectionDAG &DAG) { MVT::ValueType ArgVT = getValueType(ArgTy); - SDOperand Result; - if (!isVANext) { - Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList, DAG.getSrcValue(NULL)); - } else { - unsigned Amt; - if (ArgVT == MVT::i32 || ArgVT == MVT::f32) - Amt = 8; - else { - assert((ArgVT == MVT::i64 || ArgVT == MVT::f64) && - "Other types should have been promoted for varargs!"); - Amt = 8; - } - Result = DAG.getNode(ISD::ADD, VAList.getValueType(), VAList, - DAG.getConstant(Amt, VAList.getValueType())); + SDOperand Val = DAG.getLoad(MVT::i64, Chain, VAList, DAG.getSrcValue(NULL)); + SDOperand Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), Val, DAG.getSrcValue(NULL)); + unsigned Amt; + if (ArgVT == MVT::i32 || ArgVT == MVT::f32) + Amt = 8; + else { + assert((ArgVT == MVT::i64 || ArgVT == MVT::f64) && + "Other types should have been promoted for varargs!"); + Amt = 8; } + Val = DAG.getNode(ISD::ADD, Val.getValueType(), Val, + DAG.getConstant(Amt, Val.getValueType())); + Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, + Val, VAList, DAG.getSrcValue(NULL)); return std::make_pair(Result, Chain); } +std::pair +IA64TargetLowering::LowerVACopy(SDOperand Chain, SDOperand Src, + SDOperand Dest, SelectionDAG &DAG) +{ + SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain, + Src, Dest, DAG.getSrcValue(NULL)); + return std::make_pair(Result, Result); +} + std::pair IA64TargetLowering:: LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, SelectionDAG &DAG) { diff --git a/lib/Target/PowerPC/PPC32ISelSimple.cpp b/lib/Target/PowerPC/PPC32ISelSimple.cpp index 49af9b6173a..065262c10d5 100644 --- a/lib/Target/PowerPC/PPC32ISelSimple.cpp +++ b/lib/Target/PowerPC/PPC32ISelSimple.cpp @@ -310,7 +310,6 @@ namespace { void visitShiftInst(ShiftInst &I); void visitPHINode(PHINode &I) {} // PHI nodes handled by second pass void visitCastInst(CastInst &I); - void visitVANextInst(VANextInst &I); void visitVAArgInst(VAArgInst &I); void visitInstruction(Instruction &I) { @@ -1978,6 +1977,7 @@ void PPC32ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { unsigned TmpReg1, TmpReg2, TmpReg3; switch (ID) { case Intrinsic::vastart: + //FIXME: need to store, not return a value // Get the address of the first vararg value... TmpReg1 = getReg(CI); addFrameReference(BuildMI(BB, PPC::ADDI, 2, TmpReg1), VarArgsFrameIndex, @@ -1985,6 +1985,7 @@ void PPC32ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { return; case Intrinsic::vacopy: + //FIXME: need to store into first arg the value of the second TmpReg1 = getReg(CI); TmpReg2 = getReg(CI.getOperand(1)); BuildMI(BB, PPC::OR, 2, TmpReg1).addReg(TmpReg2).addReg(TmpReg2); @@ -3679,37 +3680,12 @@ void PPC32ISel::emitCastOperation(MachineBasicBlock *MBB, abort(); } -/// visitVANextInst - Implement the va_next instruction... -/// -void PPC32ISel::visitVANextInst(VANextInst &I) { - unsigned VAList = getReg(I.getOperand(0)); - unsigned DestReg = getReg(I); - - unsigned Size; - switch (I.getArgType()->getTypeID()) { - default: - std::cerr << I; - assert(0 && "Error: bad type for va_next instruction!"); - return; - case Type::PointerTyID: - case Type::UIntTyID: - case Type::IntTyID: - Size = 4; - break; - case Type::ULongTyID: - case Type::LongTyID: - case Type::DoubleTyID: - Size = 8; - break; - } - - // Increment the VAList pointer... - BuildMI(BB, PPC::ADDI, 2, DestReg).addReg(VAList).addSImm(Size); -} - void PPC32ISel::visitVAArgInst(VAArgInst &I) { - unsigned VAList = getReg(I.getOperand(0)); + unsigned VAListPtr = getReg(I.getOperand(0)); unsigned DestReg = getReg(I); + unsigned VAList = makeAnotherReg(Type::IntTy); + BuildMI(BB, PPC::LWZ, 2, VAList).addSImm(0).addReg(VAListPtr); + int Size; switch (I.getType()->getTypeID()) { default: @@ -3719,20 +3695,28 @@ void PPC32ISel::visitVAArgInst(VAArgInst &I) { case Type::PointerTyID: case Type::UIntTyID: case Type::IntTyID: + Size = 4; BuildMI(BB, PPC::LWZ, 2, DestReg).addSImm(0).addReg(VAList); break; case Type::ULongTyID: case Type::LongTyID: + Size = 8; BuildMI(BB, PPC::LWZ, 2, DestReg).addSImm(0).addReg(VAList); BuildMI(BB, PPC::LWZ, 2, DestReg+1).addSImm(4).addReg(VAList); break; case Type::FloatTyID: + Size = 4; //?? Bad value? BuildMI(BB, PPC::LFS, 2, DestReg).addSImm(0).addReg(VAList); break; case Type::DoubleTyID: + Size = 8; BuildMI(BB, PPC::LFD, 2, DestReg).addSImm(0).addReg(VAList); break; } + // Increment the VAList pointer... + unsigned NP = makeAnotherReg(Type::IntTy); + BuildMI(BB, PPC::ADDI, 2, NP).addReg(VAList).addSImm(Size); + BuildMI(BB, PPC::STW, 3).addReg(NP).addSImm(0).addReg(VAListPtr); } /// visitGetElementPtrInst - instruction-select GEP instructions diff --git a/lib/Target/PowerPC/PPC64ISelPattern.cpp b/lib/Target/PowerPC/PPC64ISelPattern.cpp index 1d528a9a5b9..20fd7244447 100644 --- a/lib/Target/PowerPC/PPC64ISelPattern.cpp +++ b/lib/Target/PowerPC/PPC64ISelPattern.cpp @@ -98,12 +98,16 @@ namespace { SelectionDAG &DAG); virtual std::pair - LowerVAStart(SDOperand Chain, SelectionDAG &DAG); + LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest); virtual std::pair - LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, + LowerVAArgNext(SDOperand Chain, SDOperand VAList, const Type *ArgTy, SelectionDAG &DAG); + virtual std::pair + LowerVACopy(SDOperand Chain, SDOperand Src, SDOperand Dest, + SelectionDAG &DAG); + virtual std::pair LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, SelectionDAG &DAG); @@ -365,26 +369,36 @@ PPC64TargetLowering::LowerCallTo(SDOperand Chain, } std::pair -PPC64TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) { - //vastart just returns the address of the VarArgsFrameIndex slot. - return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain); +PPC64TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest) { + // vastart just stores the address of the VarArgsFrameIndex slot. + SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64); + SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain, FR, Dest, DAG.getSrcValue(NULL)); + return std::make_pair(Result, Result); } std::pair PPC64TargetLowering:: -LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, +LowerVAArgNext(SDOperand Chain, SDOperand VAList, const Type *ArgTy, SelectionDAG &DAG) { MVT::ValueType ArgVT = getValueType(ArgTy); SDOperand Result; - if (!isVANext) { - Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList, - DAG.getSrcValue(NULL)); - } else { - Result = DAG.getNode(ISD::ADD, VAList.getValueType(), VAList, - DAG.getConstant(8, VAList.getValueType())); - } + SDOperand Val = DAG.getLoad(MVT::i64, Chain, VAList, DAG.getSrcValue(NULL)); + Result = DAG.getLoad(ArgVT, Val.getValue(1), Val, DAG.getSrcValue(NULL)); + Val = DAG.getNode(ISD::ADD, VAList.getValueType(), Val, + DAG.getConstant(8, VAList.getValueType())); + Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, + Val, VAList, DAG.getSrcValue(NULL)); return std::make_pair(Result, Chain); } +std::pair +PPC64TargetLowering::LowerVACopy(SDOperand Chain, SDOperand Src, + SDOperand Dest, SelectionDAG &DAG) +{ + SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain, + Src, Dest, DAG.getSrcValue(NULL)); + return std::make_pair(Result, Result); +} + std::pair PPC64TargetLowering:: LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, diff --git a/lib/Target/Sparc/SparcV8ISelSimple.cpp b/lib/Target/Sparc/SparcV8ISelSimple.cpp index da97f971f18..363bfe19cbd 100644 --- a/lib/Target/Sparc/SparcV8ISelSimple.cpp +++ b/lib/Target/Sparc/SparcV8ISelSimple.cpp @@ -102,7 +102,6 @@ namespace { void visitBranchInst(BranchInst &I); void visitUnreachableInst(UnreachableInst &I) {} void visitCastInst(CastInst &I); - void visitVANextInst(VANextInst &I); void visitVAArgInst(VAArgInst &I); void visitLoadInst(LoadInst &I); void visitStoreInst(StoreInst &I); @@ -1754,8 +1753,10 @@ void V8ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { case Intrinsic::vastart: { // Add the VarArgsOffset to the frame pointer, and copy it to the result. - unsigned DestReg = getReg (CI); - BuildMI (BB, V8::ADDri, 2, DestReg).addReg (V8::FP).addSImm (VarArgsOffset); + unsigned DestReg = getReg (CI.getOperand(1)); + unsigned Tmp = makeAnotherReg(Type::IntTy); + BuildMI (BB, V8::ADDri, 2, Tmp).addReg (V8::FP).addSImm (VarArgsOffset); + BuildMI(BB, V8::ST, 3).addReg(DestReg).addSImm(0).addReg(Tmp); return; } @@ -1765,39 +1766,37 @@ void V8ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { case Intrinsic::vacopy: { // Copy the va_list ptr (arg1) to the result. - unsigned DestReg = getReg (CI), SrcReg = getReg (CI.getOperand (1)); - BuildMI (BB, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (SrcReg); + unsigned DestReg = getReg (CI.getOperand(1)), SrcReg = getReg (CI.getOperand (2)); + BuildMI(BB, V8::ST, 3).addReg(DestReg).addSImm(0).addReg(SrcReg); return; } } } -void V8ISel::visitVANextInst (VANextInst &I) { - // Add the type size to the vararg pointer (arg0). - unsigned DestReg = getReg (I); - unsigned SrcReg = getReg (I.getOperand (0)); - unsigned TySize = TM.getTargetData ().getTypeSize (I.getArgType ()); - BuildMI (BB, V8::ADDri, 2, DestReg).addReg (SrcReg).addSImm (TySize); -} - void V8ISel::visitVAArgInst (VAArgInst &I) { - unsigned VAList = getReg (I.getOperand (0)); + unsigned VAListPtr = getReg (I.getOperand (0)); unsigned DestReg = getReg (I); + unsigned Size; + unsigned VAList = makeAnotherReg(Type::IntTy); + BuildMI(BB, V8::LD, 2, VAList).addReg(VAListPtr).addSImm(0); switch (I.getType ()->getTypeID ()) { case Type::PointerTyID: case Type::UIntTyID: case Type::IntTyID: + Size = 4; BuildMI (BB, V8::LD, 2, DestReg).addReg (VAList).addSImm (0); - return; + break; case Type::ULongTyID: case Type::LongTyID: + Size = 8; BuildMI (BB, V8::LD, 2, DestReg).addReg (VAList).addSImm (0); BuildMI (BB, V8::LD, 2, DestReg+1).addReg (VAList).addSImm (4); - return; + break; case Type::DoubleTyID: { + Size = 8; unsigned DblAlign = TM.getTargetData().getDoubleAlignment(); unsigned TempReg = makeAnotherReg (Type::IntTy); unsigned TempReg2 = makeAnotherReg (Type::IntTy); @@ -1807,7 +1806,7 @@ void V8ISel::visitVAArgInst (VAArgInst &I) { BuildMI (BB, V8::ST, 3).addFrameIndex (FI).addSImm (0).addReg (TempReg); BuildMI (BB, V8::ST, 3).addFrameIndex (FI).addSImm (4).addReg (TempReg2); BuildMI (BB, V8::LDDFri, 2, DestReg).addFrameIndex (FI).addSImm (0); - return; + break; } default: @@ -1816,4 +1815,8 @@ void V8ISel::visitVAArgInst (VAArgInst &I) { abort (); return; } + unsigned tmp = makeAnotherReg(Type::IntTy); + BuildMI (BB, V8::ADDri, 2, tmp).addReg(VAList).addSImm(Size); + BuildMI(BB, V8::ST, 3).addReg(VAListPtr).addSImm(0).addReg(VAList); + return; } diff --git a/lib/Target/SparcV8/SparcV8ISelSimple.cpp b/lib/Target/SparcV8/SparcV8ISelSimple.cpp index da97f971f18..363bfe19cbd 100644 --- a/lib/Target/SparcV8/SparcV8ISelSimple.cpp +++ b/lib/Target/SparcV8/SparcV8ISelSimple.cpp @@ -102,7 +102,6 @@ namespace { void visitBranchInst(BranchInst &I); void visitUnreachableInst(UnreachableInst &I) {} void visitCastInst(CastInst &I); - void visitVANextInst(VANextInst &I); void visitVAArgInst(VAArgInst &I); void visitLoadInst(LoadInst &I); void visitStoreInst(StoreInst &I); @@ -1754,8 +1753,10 @@ void V8ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { case Intrinsic::vastart: { // Add the VarArgsOffset to the frame pointer, and copy it to the result. - unsigned DestReg = getReg (CI); - BuildMI (BB, V8::ADDri, 2, DestReg).addReg (V8::FP).addSImm (VarArgsOffset); + unsigned DestReg = getReg (CI.getOperand(1)); + unsigned Tmp = makeAnotherReg(Type::IntTy); + BuildMI (BB, V8::ADDri, 2, Tmp).addReg (V8::FP).addSImm (VarArgsOffset); + BuildMI(BB, V8::ST, 3).addReg(DestReg).addSImm(0).addReg(Tmp); return; } @@ -1765,39 +1766,37 @@ void V8ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { case Intrinsic::vacopy: { // Copy the va_list ptr (arg1) to the result. - unsigned DestReg = getReg (CI), SrcReg = getReg (CI.getOperand (1)); - BuildMI (BB, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (SrcReg); + unsigned DestReg = getReg (CI.getOperand(1)), SrcReg = getReg (CI.getOperand (2)); + BuildMI(BB, V8::ST, 3).addReg(DestReg).addSImm(0).addReg(SrcReg); return; } } } -void V8ISel::visitVANextInst (VANextInst &I) { - // Add the type size to the vararg pointer (arg0). - unsigned DestReg = getReg (I); - unsigned SrcReg = getReg (I.getOperand (0)); - unsigned TySize = TM.getTargetData ().getTypeSize (I.getArgType ()); - BuildMI (BB, V8::ADDri, 2, DestReg).addReg (SrcReg).addSImm (TySize); -} - void V8ISel::visitVAArgInst (VAArgInst &I) { - unsigned VAList = getReg (I.getOperand (0)); + unsigned VAListPtr = getReg (I.getOperand (0)); unsigned DestReg = getReg (I); + unsigned Size; + unsigned VAList = makeAnotherReg(Type::IntTy); + BuildMI(BB, V8::LD, 2, VAList).addReg(VAListPtr).addSImm(0); switch (I.getType ()->getTypeID ()) { case Type::PointerTyID: case Type::UIntTyID: case Type::IntTyID: + Size = 4; BuildMI (BB, V8::LD, 2, DestReg).addReg (VAList).addSImm (0); - return; + break; case Type::ULongTyID: case Type::LongTyID: + Size = 8; BuildMI (BB, V8::LD, 2, DestReg).addReg (VAList).addSImm (0); BuildMI (BB, V8::LD, 2, DestReg+1).addReg (VAList).addSImm (4); - return; + break; case Type::DoubleTyID: { + Size = 8; unsigned DblAlign = TM.getTargetData().getDoubleAlignment(); unsigned TempReg = makeAnotherReg (Type::IntTy); unsigned TempReg2 = makeAnotherReg (Type::IntTy); @@ -1807,7 +1806,7 @@ void V8ISel::visitVAArgInst (VAArgInst &I) { BuildMI (BB, V8::ST, 3).addFrameIndex (FI).addSImm (0).addReg (TempReg); BuildMI (BB, V8::ST, 3).addFrameIndex (FI).addSImm (4).addReg (TempReg2); BuildMI (BB, V8::LDDFri, 2, DestReg).addFrameIndex (FI).addSImm (0); - return; + break; } default: @@ -1816,4 +1815,8 @@ void V8ISel::visitVAArgInst (VAArgInst &I) { abort (); return; } + unsigned tmp = makeAnotherReg(Type::IntTy); + BuildMI (BB, V8::ADDri, 2, tmp).addReg(VAList).addSImm(Size); + BuildMI(BB, V8::ST, 3).addReg(VAListPtr).addSImm(0).addReg(VAList); + return; } diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp index 8ffcc827e2f..d28de2828d6 100644 --- a/lib/Target/X86/X86ISelPattern.cpp +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -176,12 +176,16 @@ namespace { SelectionDAG &DAG); virtual std::pair - LowerVAStart(SDOperand Chain, SelectionDAG &DAG); + LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest); virtual std::pair - LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, + LowerVAArgNext(SDOperand Chain, SDOperand VAList, const Type *ArgTy, SelectionDAG &DAG); + virtual std::pair + LowerVACopy(SDOperand Chain, SDOperand Src, SDOperand Dest, + SelectionDAG &DAG); + virtual std::pair LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, SelectionDAG &DAG); @@ -442,35 +446,44 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy, return std::make_pair(ResultVal, Chain); } -std::pair -X86TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) { - // vastart just returns the address of the VarArgsFrameIndex slot. - return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32), Chain); +std::pair +X86TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest) { + // vastart just stores the address of the VarArgsFrameIndex slot. + SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32); + SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain, FR, Dest, DAG.getSrcValue(NULL)); + return std::make_pair(Result, Result); } -std::pair X86TargetLowering:: -LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, - const Type *ArgTy, SelectionDAG &DAG) { +std::pair +X86TargetLowering::LowerVAArgNext(SDOperand Chain, SDOperand VAList, + const Type *ArgTy, SelectionDAG &DAG) { MVT::ValueType ArgVT = getValueType(ArgTy); - SDOperand Result; - if (!isVANext) { - Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList, - DAG.getSrcValue(NULL)); - } else { - unsigned Amt; - if (ArgVT == MVT::i32) - Amt = 4; - else { - assert((ArgVT == MVT::i64 || ArgVT == MVT::f64) && - "Other types should have been promoted for varargs!"); - Amt = 8; - } - Result = DAG.getNode(ISD::ADD, VAList.getValueType(), VAList, - DAG.getConstant(Amt, VAList.getValueType())); + SDOperand Val = DAG.getLoad(MVT::i32, Chain, VAList, DAG.getSrcValue(NULL)); + SDOperand Result = DAG.getLoad(ArgVT, Val.getValue(1), Val, DAG.getSrcValue(NULL)); + unsigned Amt; + if (ArgVT == MVT::i32) + Amt = 4; + else { + assert((ArgVT == MVT::i64 || ArgVT == MVT::f64) && + "Other types should have been promoted for varargs!"); + Amt = 8; } + Val = DAG.getNode(ISD::ADD, Val.getValueType(), Val, + DAG.getConstant(Amt, Val.getValueType())); + Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, + Val, VAList, DAG.getSrcValue(NULL)); return std::make_pair(Result, Chain); } +std::pair +X86TargetLowering::LowerVACopy(SDOperand Chain, SDOperand Src, + SDOperand Dest, SelectionDAG &DAG) +{ + SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain, + Src, Dest, DAG.getSrcValue(NULL)); + return std::make_pair(Result, Result); +} + //===----------------------------------------------------------------------===// // Fast Calling Convention implementation //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp index e5898a801b1..148a590fc37 100644 --- a/lib/Target/X86/X86ISelSimple.cpp +++ b/lib/Target/X86/X86ISelSimple.cpp @@ -232,7 +232,6 @@ namespace { void visitShiftInst(ShiftInst &I); void visitPHINode(PHINode &I) {} // PHI nodes handled by second pass void visitCastInst(CastInst &I); - void visitVANextInst(VANextInst &I); void visitVAArgInst(VAArgInst &I); void visitInstruction(Instruction &I) { @@ -1838,12 +1837,14 @@ void X86ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { unsigned TmpReg1, TmpReg2; switch (ID) { case Intrinsic::vastart: + //FIXME: store to first arg, don't return // Get the address of the first vararg value... TmpReg1 = getReg(CI); addFrameReference(BuildMI(BB, X86::LEA32r, 5, TmpReg1), VarArgsFrameIndex); return; case Intrinsic::vacopy: + //FIXME: copy val of second into first (which is a ptr) TmpReg1 = getReg(CI); TmpReg2 = getReg(CI.getOperand(1)); BuildMI(BB, X86::MOV32rr, 1, TmpReg1).addReg(TmpReg2); @@ -3745,38 +3746,12 @@ void X86ISel::emitCastOperation(MachineBasicBlock *BB, abort(); } -/// visitVANextInst - Implement the va_next instruction... -/// -void X86ISel::visitVANextInst(VANextInst &I) { - unsigned VAList = getReg(I.getOperand(0)); - unsigned DestReg = getReg(I); - - unsigned Size; - switch (I.getArgType()->getTypeID()) { - default: - std::cerr << I; - assert(0 && "Error: bad type for va_next instruction!"); - return; - case Type::PointerTyID: - case Type::UIntTyID: - case Type::IntTyID: - Size = 4; - break; - case Type::ULongTyID: - case Type::LongTyID: - case Type::DoubleTyID: - Size = 8; - break; - } - - // Increment the VAList pointer... - BuildMI(BB, X86::ADD32ri, 2, DestReg).addReg(VAList).addImm(Size); -} - void X86ISel::visitVAArgInst(VAArgInst &I) { - unsigned VAList = getReg(I.getOperand(0)); + unsigned VAListPtr = getReg(I.getOperand(0)); unsigned DestReg = getReg(I); - + unsigned VAList = makeAnotherReg(Type::IntTy); + addDirectMem(BuildMI(BB, X86::MOV32rm, 4, VAList), VAListPtr); + unsigned Size; switch (I.getType()->getTypeID()) { default: std::cerr << I; @@ -3785,17 +3760,24 @@ void X86ISel::visitVAArgInst(VAArgInst &I) { case Type::PointerTyID: case Type::UIntTyID: case Type::IntTyID: + Size = 4; addDirectMem(BuildMI(BB, X86::MOV32rm, 4, DestReg), VAList); break; case Type::ULongTyID: case Type::LongTyID: + Size = 8; addDirectMem(BuildMI(BB, X86::MOV32rm, 4, DestReg), VAList); addRegOffset(BuildMI(BB, X86::MOV32rm, 4, DestReg+1), VAList, 4); break; case Type::DoubleTyID: + Size = 8; addDirectMem(BuildMI(BB, X86::FLD64m, 4, DestReg), VAList); break; } + // Increment the VAList pointer... + unsigned NP = makeAnotherReg(Type::IntTy); + BuildMI(BB, X86::ADD32ri, 2, NP).addReg(VAList).addSImm(Size); + addDirectMem(BuildMI(BB, X86::MOV32rm, 5), VAListPtr).addReg(VAList); } /// visitGetElementPtrInst - instruction-select GEP instructions diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp index 3f1905156da..acd17e7fe1b 100644 --- a/lib/Transforms/Scalar/LICM.cpp +++ b/lib/Transforms/Scalar/LICM.cpp @@ -386,7 +386,7 @@ bool LICM::canSinkOrHoistInst(Instruction &I) { return isa(I) || isa(I) || isa(I) || isa(I) || - isa(I) || isa(I) || isa(I); + isa(I) || isa(I); } /// isNotUsedInLoop - Return true if the only users of this instruction are diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 9ae3b9a2890..e06bf50a9d1 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1188,10 +1188,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) { if (Operand) writeOperand(Operand, true); // Work with broken code Out << ", "; printType(I.getType()); - } else if (const VANextInst *VAN = dyn_cast(&I)) { - if (Operand) writeOperand(Operand, true); // Work with broken code - Out << ", "; - printType(VAN->getArgType()); } else if (Operand) { // Print the normal way... // PrintAllTypes - Instructions who have operands of all the same type diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index e1dead99f23..2bce2dcd22c 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -110,8 +110,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case Call: return "call"; case Shl: return "shl"; case Shr: return "shr"; - case VANext: return "vanext"; - case VAArg: return "vaarg"; + case VAArg: return "va_arg"; default: return " "; } @@ -139,8 +138,6 @@ bool Instruction::isIdenticalTo(Instruction *I) const { return LI->isVolatile() == cast(I)->isVolatile(); if (const StoreInst *SI = dyn_cast(this)) return SI->isVolatile() == cast(I)->isVolatile(); - if (const VANextInst *VAN = dyn_cast(this)) - return VAN->getArgType() == cast(I)->getArgType(); if (const CallInst *CI = dyn_cast(this)) return CI->isTailCall() == cast(I)->isTailCall(); return true; diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 7d3b0eecb88..68b685e7fcb 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -1096,7 +1096,6 @@ CastInst *CastInst::clone() const { return new CastInst(*this); } CallInst *CallInst::clone() const { return new CallInst(*this); } ShiftInst *ShiftInst::clone() const { return new ShiftInst(*this); } SelectInst *SelectInst::clone() const { return new SelectInst(*this); } -VANextInst *VANextInst::clone() const { return new VANextInst(*this); } VAArgInst *VAArgInst::clone() const { return new VAArgInst(*this); } PHINode *PHINode::clone() const { return new PHINode(*this); } ReturnInst *ReturnInst::clone() const { return new ReturnInst(*this); } diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 753a75ea0cf..0b1670ee710 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -178,7 +178,6 @@ namespace { // Anonymous namespace for class void visitPHINode(PHINode &PN); void visitBinaryOperator(BinaryOperator &B); void visitShiftInst(ShiftInst &SI); - void visitVANextInst(VANextInst &VAN) { visitInstruction(VAN); } void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); } void visitCallInst(CallInst &CI); void visitGetElementPtrInst(GetElementPtrInst &GEP); @@ -655,10 +654,10 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { Assert1(CI.getParent()->getParent()->getFunctionType()->isVarArg(), "llvm.va_start intrinsic may only occur in function with variable" " args!", &CI); - NumArgs = 0; + NumArgs = 1; break; case Intrinsic::vaend: NumArgs = 1; break; - case Intrinsic::vacopy: NumArgs = 1; break; + case Intrinsic::vacopy: NumArgs = 2; break; case Intrinsic::returnaddress: case Intrinsic::frameaddress: