#define LLVM_ASSEMBLY_AUTOUPGRADE_H
#include <string>
+#include <vector>
namespace llvm {
class Function;
class CallInst;
class Instruction;
+ class Value;
+ class BasicBlock;
/// This function determines if the \p Name provides is a name for which the
/// auto-upgrade to a non-overloaded name applies.
/// @brief Remove overloaded intrinsic function names.
Function* UpgradeIntrinsicFunction(Function* F);
+ Instruction* MakeUpgradedCall(
+ Function* F, ///< The function to call
+ const std::vector<Value*>& Params, ///< Operands of the call
+ BasicBlock* BB, ///< Basic block the caller will insert result to
+ bool isTailCall = false, ///< True if this is a tail call.
+ unsigned CallingConv = 0 ///< Calling convention to use
+ );
+
/// In LLVM 1.7, the overloading of intrinsic functions was replaced with
/// separate functions for each of the various argument sizes. This function
/// implements the auto-upgrade feature from old overloaded names to the new
/// @param CI The CallInst to potentially auto-upgrade.
/// @returns An instrution to replace \p CI with.
/// @brief Get replacement instruction for overloaded intrinsic function call.
- Instruction* UpgradeIntrinsicCall(CallInst* CI);
+ Instruction* UpgradeIntrinsicCall(CallInst* CI, Function* newF = 0);
/// Upgrade both the function and all the calls made to it, if that function
/// needs to be upgraded. This is like a combination of the above two
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
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;
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();
++Fi;
}
LazyFunctionLoadMap.clear();
+
}
/// Parse the global type list
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.
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);
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;
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;
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();
}
}