diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Bytecode/Reader/Reader.cpp | 45 | ||||
-rw-r--r-- | lib/Bytecode/Reader/Reader.h | 6 | ||||
-rw-r--r-- | lib/VMCore/AutoUpgrade.cpp | 126 |
3 files changed, 131 insertions, 46 deletions
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index d142aac..f9ac0ba 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -861,7 +861,6 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, Result = new CallInst(F, Params); if (isTailCall) cast<CallInst>(Result)->setTailCall(); if (CallingConv) cast<CallInst>(Result)->setCallingConv(CallingConv); - isCall = true; break; } case 56: // Invoke with encoded CC @@ -1034,13 +1033,6 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, BB->getInstList().push_back(Result); - if (this->hasUpgradedIntrinsicFunctions && isCall) - if (Instruction* inst = UpgradeIntrinsicCall(cast<CallInst>(Result))) { - Result->replaceAllUsesWith(inst); - Result->eraseFromParent(); - Result = inst; - } - unsigned TypeSlot; if (Result->getType() == InstTy) TypeSlot = iType; @@ -1862,6 +1854,25 @@ void BytecodeReader::ParseFunctionBody(Function* F) { delete PlaceHolder; } + // If upgraded intrinsic functions were detected during reading of the + // module information, then we need to look for instructions that need to + // be upgraded. This can't be done while the instructions are read in because + // additional instructions inserted mess up the slot numbering. + if (!upgradedFunctions.empty()) { + for (Function::iterator BI = F->begin(), BE = F->end(); BI != BE; ++BI) + for (BasicBlock::iterator II = BI->begin(), IE = BI->end(); + II != IE; ++II) + if (CallInst* CI = dyn_cast<CallInst>(II)) { + std::map<Function*,Function*>::iterator FI = + upgradedFunctions.find(CI->getCalledFunction()); + if (FI != upgradedFunctions.end()) { + Instruction* newI = UpgradeIntrinsicCall(CI,FI->second); + CI->replaceAllUsesWith(newI); + CI->eraseFromParent(); + } + } + } + // Clear out function-level types... FunctionTypes.clear(); CompactionTypes.clear(); @@ -1937,6 +1948,7 @@ void BytecodeReader::ParseAllFunctionBodies() { ++Fi; } LazyFunctionLoadMap.clear(); + } /// Parse the global type list @@ -2055,13 +2067,6 @@ void BytecodeReader::ParseModuleGlobalInfo() { Function *Func = new Function(FTy, GlobalValue::ExternalLinkage, "", TheModule); - // Replace with upgraded intrinsic function, if applicable. - if (Function* upgrdF = UpgradeIntrinsicFunction(Func)) { - hasUpgradedIntrinsicFunctions = true; - Func->eraseFromParent(); - Func = upgrdF; - } - insertValue(Func, (FnSignature & (~0U >> 1)) >> 5, ModuleValues); // Flags are not used yet. @@ -2433,6 +2438,16 @@ void BytecodeReader::ParseBytecode(BufPtr Buf, unsigned Length, if (hasFunctions()) error("Function expected, but bytecode stream ended!"); + // Look for intrinsic functions to upgrade, upgrade them, and save the + // mapping from old function to new for use later when instructions are + // converted. + for (Module::iterator FI = TheModule->begin(), FE = TheModule->end(); + FI != FE; ++FI) + if (Function* newF = UpgradeIntrinsicFunction(FI)) { + upgradedFunctions.insert(std::make_pair(FI,newF)); + FI->setName(""); + } + // Tell the handler we're done with the module if (Handler) Handler->handleModuleEnd(ModuleID); diff --git a/lib/Bytecode/Reader/Reader.h b/lib/Bytecode/Reader/Reader.h index 21eb846..ffc251b 100644 --- a/lib/Bytecode/Reader/Reader.h +++ b/lib/Bytecode/Reader/Reader.h @@ -323,9 +323,9 @@ private: /// In release 1.7 we changed intrinsic functions to not be overloaded. There /// is no bytecode change for this, but to optimize the auto-upgrade of calls - /// to intrinsic functions, we set this flag to identify when a module has - /// been read that contains intrinsics that were upgraded. - bool hasUpgradedIntrinsicFunctions; + /// to intrinsic functions, we save a mapping of old function definitions to + /// the new ones so call instructions can be upgraded efficiently. + std::map<Function*,Function*> upgradedFunctions; /// CompactionTypes - If a compaction table is active in the current function, /// this is the mapping that it contains. We keep track of what resolved type diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index b68b8b7..91b0d31 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -75,9 +75,26 @@ static inline const Type* getTypeFromFunctionName(Function* F) { return 0; } +// This assumes the Function is one of the intrinsics we upgraded. +static inline const Type* getTypeFromFunction(Function *F) { + const Type* Ty = F->getReturnType(); + if (Ty->isFloatingPoint()) + return Ty; + if (Ty->isSigned()) + return Ty->getUnsignedVersion(); + if (Ty->isInteger()) + return Ty; + if (Ty == Type::BoolTy) { + Function::const_arg_iterator ArgIt = F->arg_begin(); + if (ArgIt != F->arg_end()) + return ArgIt->getType(); + } + return 0; +} + bool llvm::IsUpgradeableIntrinsicName(const std::string& Name) { // Quickly eliminate it, if it's not a candidate. - if (Name.length() <= 5 || Name[0] != 'l' || Name[1] != 'l' || Name[2] != + if (Name.length() <= 8 || Name[0] != 'l' || Name[1] != 'l' || Name[2] != 'v' || Name[3] != 'm' || Name[4] != '.') return false; @@ -140,23 +157,68 @@ Function* llvm::UpgradeIntrinsicFunction(Function* F) { return 0; } -Instruction* llvm::UpgradeIntrinsicCall(CallInst *CI) { + +Instruction* llvm::MakeUpgradedCall( + Function* F, const std::vector<Value*>& Params, BasicBlock* BB, + bool isTailCall, unsigned CallingConv) { + assert(F && "Need a Function to make a CallInst"); + assert(BB && "Need a BasicBlock to make a CallInst"); + + // Convert the params + bool signedArg = false; + std::vector<Value*> Oprnds; + for (std::vector<Value*>::const_iterator PI = Params.begin(), + PE = Params.end(); PI != PE; ++PI) { + const Type* opTy = (*PI)->getType(); + if (opTy->isSigned()) { + signedArg = true; + CastInst* cast = + new CastInst(*PI,opTy->getUnsignedVersion(), "autoupgrade_cast"); + BB->getInstList().push_back(cast); + Oprnds.push_back(cast); + } + else + Oprnds.push_back(*PI); + } + + Instruction* result = new CallInst(F,Oprnds,"autoupgrade_call"); + if (isTailCall) cast<CallInst>(result)->setTailCall(); + if (CallingConv) cast<CallInst>(result)->setCallingConv(CallingConv); + if (signedArg) { + const Type* newTy = F->getReturnType()->getUnsignedVersion(); + CastInst* final = new CastInst(result, newTy, "autoupgrade_uncast"); + BB->getInstList().push_back(result); + result = final; + } + return result; +} + +Instruction* llvm::UpgradeIntrinsicCall(CallInst *CI, Function* newF) { Function *F = CI->getCalledFunction(); - if (const Type* Ty = getTypeFromFunctionName(F)) { - Function* newF = UpgradeIntrinsicFunction(F); + if (const Type* Ty = + (newF ? getTypeFromFunction(newF) : getTypeFromFunctionName(F))) { std::vector<Value*> Oprnds; - for (User::op_iterator OI = CI->op_begin(), OE = CI->op_end(); - OI != OE; ++OI) - Oprnds.push_back(CI); - CallInst* newCI = new CallInst(newF,Oprnds,"autoupgrade_call",CI); - if (Ty->isSigned()) { - const Type* newTy = Ty->getUnsignedVersion(); - newCI->setOperand(1,new CastInst(newCI->getOperand(1), newTy, - "autoupgrade_cast", newCI)); - CastInst* final = new CastInst(newCI, Ty, "autoupgrade_uncast",newCI); - newCI->moveBefore(final); - return final; + User::op_iterator OI = CI->op_begin(); + ++OI; + for (User::op_iterator OE = CI->op_end() ; OI != OE; ++OI) { + const Type* opTy = OI->get()->getType(); + if (opTy->isSigned()) + Oprnds.push_back( + new CastInst(OI->get(),opTy->getUnsignedVersion(), + "autoupgrade_cast",CI)); + else + Oprnds.push_back(*OI); } + CallInst* newCI = new CallInst((newF?newF:F),Oprnds,"autoupgrade_call",CI); + newCI->setTailCall(CI->isTailCall()); + newCI->setCallingConv(CI->getCallingConv()); + if (const Type* oldType = CI->getCalledFunction()->getReturnType()) + if (oldType->isSigned()) { + CastInst* final = + new CastInst(newCI, oldType, "autoupgrade_uncast",newCI); + newCI->moveBefore(final); + return final; + } return newCI; } return 0; @@ -170,20 +232,28 @@ bool llvm::UpgradeCallsToIntrinsic(Function* F) { std::vector<Value*> Oprnds; User::op_iterator OI = CI->op_begin(); ++OI; - for (User::op_iterator OE = CI->op_end(); OI != OE; ++OI) - Oprnds.push_back(*OI); - CallInst* newCI = new CallInst(newF,Oprnds,"autoupgrade_call",CI); - const Type* Ty = Oprnds[0]->getType(); - if (Ty->isSigned()) { - const Type* newTy = Ty->getUnsignedVersion(); - newCI->setOperand(1,new CastInst(newCI->getOperand(1), newTy, - "autoupgrade_cast", newCI)); - CastInst* final = new CastInst(newCI, Ty, "autoupgrade_uncast",newCI); - newCI->moveBefore(final); - CI->replaceAllUsesWith(final); - } else { - CI->replaceAllUsesWith(newCI); + for (User::op_iterator OE = CI->op_end(); OI != OE; ++OI) { + const Type* opTy = OI->get()->getType(); + if (opTy->isSigned()) { + Oprnds.push_back( + new CastInst(OI->get(),opTy->getUnsignedVersion(), + "autoupgrade_cast",CI)); + } + else + Oprnds.push_back(*OI); } + CallInst* newCI = new CallInst(newF,Oprnds,"autoupgrade_call",CI); + newCI->setTailCall(CI->isTailCall()); + newCI->setCallingConv(CI->getCallingConv()); + if (const Type* Ty = CI->getCalledFunction()->getReturnType()) + if (Ty->isSigned()) { + CastInst* final = + new CastInst(newCI, Ty, "autoupgrade_uncast",newCI); + newCI->moveBefore(final); + CI->replaceAllUsesWith(final); + } else { + CI->replaceAllUsesWith(newCI); + } CI->eraseFromParent(); } } |