diff options
author | Reid Spencer <rspencer@reidspencer.com> | 2006-01-27 11:49:27 +0000 |
---|---|---|
committer | Reid Spencer <rspencer@reidspencer.com> | 2006-01-27 11:49:27 +0000 |
commit | e2a5fb0e089165f80080c294c1096be4f5739662 (patch) | |
tree | c60660fc6f3af672b7f0fafc1816a625beef8fc0 /lib/VMCore/AutoUpgrade.cpp | |
parent | 2f81fb78dc15984af7dbbfc0bb91a63842616c32 (diff) | |
download | external_llvm-e2a5fb0e089165f80080c294c1096be4f5739662.zip external_llvm-e2a5fb0e089165f80080c294c1096be4f5739662.tar.gz external_llvm-e2a5fb0e089165f80080c294c1096be4f5739662.tar.bz2 |
Fix auto-upgrade of intrinsics to work properly with both assembly and
bytecode reading. This code is crufty, the result of much hacking to get things
working correctly. Cleanup patches will follow.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25682 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore/AutoUpgrade.cpp')
-rw-r--r-- | lib/VMCore/AutoUpgrade.cpp | 126 |
1 files changed, 98 insertions, 28 deletions
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(); } } |