mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-02 07:32:52 +00:00
Change the interface to Module::getOrInsertFunction to be easier to use,to resolve PR1088, and to help PR411.
This simplifies many clients also git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32989 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
70d130516a
commit
b76efb71d4
@ -21,15 +21,14 @@
|
||||
using namespace llvm;
|
||||
|
||||
template <class ArgIt>
|
||||
static Function *EnsureFunctionExists(Module &M, const char *Name,
|
||||
ArgIt ArgBegin, ArgIt ArgEnd,
|
||||
const Type *RetTy) {
|
||||
if (Function *F = M.getNamedFunction(Name)) return F;
|
||||
// It doesn't already exist in the program, insert a new definition now.
|
||||
static void EnsureFunctionExists(Module &M, const char *Name,
|
||||
ArgIt ArgBegin, ArgIt ArgEnd,
|
||||
const Type *RetTy) {
|
||||
// Insert a correctly-typed definition now.
|
||||
std::vector<const Type *> ParamTys;
|
||||
for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
|
||||
ParamTys.push_back(I->getType());
|
||||
return M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
|
||||
M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
|
||||
}
|
||||
|
||||
/// ReplaceCallWith - This function is used when we want to lower an intrinsic
|
||||
@ -38,53 +37,24 @@ static Function *EnsureFunctionExists(Module &M, const char *Name,
|
||||
/// prototype doesn't match the arguments we expect to pass in.
|
||||
template <class ArgIt>
|
||||
static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
|
||||
ArgIt ArgBegin, ArgIt ArgEnd, bool isSigned,
|
||||
const Type *RetTy, Function *&FCache) {
|
||||
ArgIt ArgBegin, ArgIt ArgEnd,
|
||||
const Type *RetTy, Constant *&FCache) {
|
||||
if (!FCache) {
|
||||
// If we haven't already looked up this function, check to see if the
|
||||
// program already contains a function with this name.
|
||||
Module *M = CI->getParent()->getParent()->getParent();
|
||||
FCache = M->getNamedFunction(NewFn);
|
||||
if (!FCache) {
|
||||
// It doesn't already exist in the program, insert a new definition now.
|
||||
std::vector<const Type *> ParamTys;
|
||||
for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
|
||||
ParamTys.push_back((*I)->getType());
|
||||
FCache = M->getOrInsertFunction(NewFn,
|
||||
FunctionType::get(RetTy, ParamTys, false));
|
||||
}
|
||||
}
|
||||
|
||||
const FunctionType *FT = FCache->getFunctionType();
|
||||
std::vector<Value*> Operands;
|
||||
unsigned ArgNo = 0;
|
||||
for (ArgIt I = ArgBegin; I != ArgEnd && ArgNo != FT->getNumParams();
|
||||
++I, ++ArgNo) {
|
||||
Value *Arg = *I;
|
||||
if (Arg->getType() != FT->getParamType(ArgNo)) {
|
||||
Instruction::CastOps opcode = CastInst::getCastOpcode(Arg, isSigned,
|
||||
FT->getParamType(ArgNo), isSigned);
|
||||
Arg = CastInst::create(opcode, Arg, FT->getParamType(ArgNo),
|
||||
Arg->getName(), CI);
|
||||
}
|
||||
Operands.push_back(Arg);
|
||||
// Get or insert the definition now.
|
||||
std::vector<const Type *> ParamTys;
|
||||
for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
|
||||
ParamTys.push_back((*I)->getType());
|
||||
FCache = M->getOrInsertFunction(NewFn,
|
||||
FunctionType::get(RetTy, ParamTys, false));
|
||||
}
|
||||
// Pass nulls into any additional arguments...
|
||||
for (; ArgNo != FT->getNumParams(); ++ArgNo)
|
||||
Operands.push_back(Constant::getNullValue(FT->getParamType(ArgNo)));
|
||||
|
||||
std::string Name = CI->getName(); CI->setName("");
|
||||
if (FT->getReturnType() == Type::VoidTy) Name.clear();
|
||||
CallInst *NewCI = new CallInst(FCache, Operands, Name, CI);
|
||||
if (!CI->use_empty()) {
|
||||
Value *V = NewCI;
|
||||
if (CI->getType() != NewCI->getType()) {
|
||||
Instruction::CastOps opcode = CastInst::getCastOpcode(NewCI, isSigned,
|
||||
CI->getType(), isSigned);
|
||||
V = CastInst::create(opcode, NewCI, CI->getType(), Name, CI);
|
||||
}
|
||||
CI->replaceAllUsesWith(V);
|
||||
}
|
||||
std::vector<Value*> Operands(ArgBegin, ArgEnd);
|
||||
CallInst *NewCI = new CallInst(FCache, Operands, CI->getName(), CI);
|
||||
if (!CI->use_empty())
|
||||
CI->replaceAllUsesWith(NewCI);
|
||||
return NewCI;
|
||||
}
|
||||
|
||||
@ -286,10 +256,9 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
|
||||
// by the lowerinvoke pass. In both cases, the right thing to do is to
|
||||
// convert the call to an explicit setjmp or longjmp call.
|
||||
case Intrinsic::setjmp: {
|
||||
static Function *SetjmpFCache = 0;
|
||||
static const unsigned castOpcodes[] = { Instruction::BitCast };
|
||||
static Constant *SetjmpFCache = 0;
|
||||
Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
|
||||
castOpcodes, Type::Int32Ty, SetjmpFCache);
|
||||
Type::Int32Ty, SetjmpFCache);
|
||||
if (CI->getType() != Type::VoidTy)
|
||||
CI->replaceAllUsesWith(V);
|
||||
break;
|
||||
@ -300,21 +269,17 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
|
||||
break;
|
||||
|
||||
case Intrinsic::longjmp: {
|
||||
static Function *LongjmpFCache = 0;
|
||||
static const unsigned castOpcodes[] =
|
||||
{ Instruction::BitCast, 0 };
|
||||
static Constant *LongjmpFCache = 0;
|
||||
ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
|
||||
castOpcodes, Type::VoidTy, LongjmpFCache);
|
||||
Type::VoidTy, LongjmpFCache);
|
||||
break;
|
||||
}
|
||||
|
||||
case Intrinsic::siglongjmp: {
|
||||
// Insert the call to abort
|
||||
static Function *AbortFCache = 0;
|
||||
static const unsigned castOpcodes[] =
|
||||
{ Instruction::BitCast, 0 };
|
||||
static Constant *AbortFCache = 0;
|
||||
ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(),
|
||||
castOpcodes, Type::VoidTy, AbortFCache);
|
||||
Type::VoidTy, AbortFCache);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::ctpop_i8:
|
||||
@ -393,38 +358,38 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
|
||||
break; // Simply strip out debugging intrinsics
|
||||
|
||||
case Intrinsic::memcpy_i32: {
|
||||
static Function *MemcpyFCache = 0;
|
||||
static Constant *MemcpyFCache = 0;
|
||||
ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
|
||||
false, (*(CI->op_begin()+1))->getType(), MemcpyFCache);
|
||||
(*(CI->op_begin()+1))->getType(), MemcpyFCache);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::memcpy_i64: {
|
||||
static Function *MemcpyFCache = 0;
|
||||
static Constant *MemcpyFCache = 0;
|
||||
ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
|
||||
false, (*(CI->op_begin()+1))->getType(), MemcpyFCache);
|
||||
(*(CI->op_begin()+1))->getType(), MemcpyFCache);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::memmove_i32: {
|
||||
static Function *MemmoveFCache = 0;
|
||||
static Constant *MemmoveFCache = 0;
|
||||
ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
|
||||
false, (*(CI->op_begin()+1))->getType(), MemmoveFCache);
|
||||
(*(CI->op_begin()+1))->getType(), MemmoveFCache);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::memmove_i64: {
|
||||
static Function *MemmoveFCache = 0;
|
||||
static Constant *MemmoveFCache = 0;
|
||||
ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
|
||||
false, (*(CI->op_begin()+1))->getType(), MemmoveFCache);
|
||||
(*(CI->op_begin()+1))->getType(), MemmoveFCache);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::memset_i32: {
|
||||
static Function *MemsetFCache = 0;
|
||||
static Constant *MemsetFCache = 0;
|
||||
ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
|
||||
true, (*(CI->op_begin()+1))->getType(), MemsetFCache);
|
||||
(*(CI->op_begin()+1))->getType(), MemsetFCache);
|
||||
}
|
||||
case Intrinsic::memset_i64: {
|
||||
static Function *MemsetFCache = 0;
|
||||
static Constant *MemsetFCache = 0;
|
||||
ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
|
||||
true, (*(CI->op_begin()+1))->getType(), MemsetFCache);
|
||||
(*(CI->op_begin()+1))->getType(), MemsetFCache);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::isunordered_f32:
|
||||
@ -440,15 +405,15 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
|
||||
break;
|
||||
}
|
||||
case Intrinsic::sqrt_f32: {
|
||||
static Function *sqrtfFCache = 0;
|
||||
static Constant *sqrtfFCache = 0;
|
||||
ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(),
|
||||
false, Type::FloatTy, sqrtfFCache);
|
||||
Type::FloatTy, sqrtfFCache);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::sqrt_f64: {
|
||||
static Function *sqrtFCache = 0;
|
||||
static Constant *sqrtFCache = 0;
|
||||
ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(),
|
||||
false, Type::DoubleTy, sqrtFCache);
|
||||
Type::DoubleTy, sqrtFCache);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ public:
|
||||
const Type* getIntPtrType() const { return TD->getIntPtrType(); }
|
||||
|
||||
/// @brief Return a Function* for the putchar libcall
|
||||
Function* get_putchar() {
|
||||
Constant *get_putchar() {
|
||||
if (!putchar_func)
|
||||
putchar_func =
|
||||
M->getOrInsertFunction("putchar", Type::Int32Ty, Type::Int32Ty, NULL);
|
||||
@ -230,7 +230,7 @@ public:
|
||||
}
|
||||
|
||||
/// @brief Return a Function* for the puts libcall
|
||||
Function* get_puts() {
|
||||
Constant *get_puts() {
|
||||
if (!puts_func)
|
||||
puts_func = M->getOrInsertFunction("puts", Type::Int32Ty,
|
||||
PointerType::get(Type::Int8Ty),
|
||||
@ -239,7 +239,7 @@ public:
|
||||
}
|
||||
|
||||
/// @brief Return a Function* for the fputc libcall
|
||||
Function* get_fputc(const Type* FILEptr_type) {
|
||||
Constant *get_fputc(const Type* FILEptr_type) {
|
||||
if (!fputc_func)
|
||||
fputc_func = M->getOrInsertFunction("fputc", Type::Int32Ty, Type::Int32Ty,
|
||||
FILEptr_type, NULL);
|
||||
@ -247,7 +247,7 @@ public:
|
||||
}
|
||||
|
||||
/// @brief Return a Function* for the fputs libcall
|
||||
Function* get_fputs(const Type* FILEptr_type) {
|
||||
Constant *get_fputs(const Type* FILEptr_type) {
|
||||
if (!fputs_func)
|
||||
fputs_func = M->getOrInsertFunction("fputs", Type::Int32Ty,
|
||||
PointerType::get(Type::Int8Ty),
|
||||
@ -256,7 +256,7 @@ public:
|
||||
}
|
||||
|
||||
/// @brief Return a Function* for the fwrite libcall
|
||||
Function* get_fwrite(const Type* FILEptr_type) {
|
||||
Constant *get_fwrite(const Type* FILEptr_type) {
|
||||
if (!fwrite_func)
|
||||
fwrite_func = M->getOrInsertFunction("fwrite", TD->getIntPtrType(),
|
||||
PointerType::get(Type::Int8Ty),
|
||||
@ -267,7 +267,7 @@ public:
|
||||
}
|
||||
|
||||
/// @brief Return a Function* for the sqrt libcall
|
||||
Function* get_sqrt() {
|
||||
Constant *get_sqrt() {
|
||||
if (!sqrt_func)
|
||||
sqrt_func = M->getOrInsertFunction("sqrt", Type::DoubleTy,
|
||||
Type::DoubleTy, NULL);
|
||||
@ -275,7 +275,7 @@ public:
|
||||
}
|
||||
|
||||
/// @brief Return a Function* for the strlen libcall
|
||||
Function* get_strcpy() {
|
||||
Constant *get_strcpy() {
|
||||
if (!strcpy_func)
|
||||
strcpy_func = M->getOrInsertFunction("strcpy",
|
||||
PointerType::get(Type::Int8Ty),
|
||||
@ -286,7 +286,7 @@ public:
|
||||
}
|
||||
|
||||
/// @brief Return a Function* for the strlen libcall
|
||||
Function* get_strlen() {
|
||||
Constant *get_strlen() {
|
||||
if (!strlen_func)
|
||||
strlen_func = M->getOrInsertFunction("strlen", TD->getIntPtrType(),
|
||||
PointerType::get(Type::Int8Ty),
|
||||
@ -295,7 +295,7 @@ public:
|
||||
}
|
||||
|
||||
/// @brief Return a Function* for the memchr libcall
|
||||
Function* get_memchr() {
|
||||
Constant *get_memchr() {
|
||||
if (!memchr_func)
|
||||
memchr_func = M->getOrInsertFunction("memchr",
|
||||
PointerType::get(Type::Int8Ty),
|
||||
@ -306,7 +306,7 @@ public:
|
||||
}
|
||||
|
||||
/// @brief Return a Function* for the memcpy libcall
|
||||
Function* get_memcpy() {
|
||||
Constant *get_memcpy() {
|
||||
if (!memcpy_func) {
|
||||
const Type *SBP = PointerType::get(Type::Int8Ty);
|
||||
const char *N = TD->getIntPtrType() == Type::Int32Ty ?
|
||||
@ -318,17 +318,17 @@ public:
|
||||
return memcpy_func;
|
||||
}
|
||||
|
||||
Function *getUnaryFloatFunction(const char *Name, Function *&Cache) {
|
||||
Constant *getUnaryFloatFunction(const char *Name, Constant *&Cache) {
|
||||
if (!Cache)
|
||||
Cache = M->getOrInsertFunction(Name, Type::FloatTy, Type::FloatTy, NULL);
|
||||
return Cache;
|
||||
}
|
||||
|
||||
Function *get_floorf() { return getUnaryFloatFunction("floorf", floorf_func);}
|
||||
Function *get_ceilf() { return getUnaryFloatFunction( "ceilf", ceilf_func);}
|
||||
Function *get_roundf() { return getUnaryFloatFunction("roundf", roundf_func);}
|
||||
Function *get_rintf() { return getUnaryFloatFunction( "rintf", rintf_func);}
|
||||
Function *get_nearbyintf() { return getUnaryFloatFunction("nearbyintf",
|
||||
Constant *get_floorf() { return getUnaryFloatFunction("floorf", floorf_func);}
|
||||
Constant *get_ceilf() { return getUnaryFloatFunction( "ceilf", ceilf_func);}
|
||||
Constant *get_roundf() { return getUnaryFloatFunction("roundf", roundf_func);}
|
||||
Constant *get_rintf() { return getUnaryFloatFunction( "rintf", rintf_func);}
|
||||
Constant *get_nearbyintf() { return getUnaryFloatFunction("nearbyintf",
|
||||
nearbyintf_func); }
|
||||
private:
|
||||
/// @brief Reset our cached data for a new Module
|
||||
@ -354,13 +354,13 @@ private:
|
||||
|
||||
private:
|
||||
/// Caches for function pointers.
|
||||
Function *putchar_func, *puts_func;
|
||||
Function *fputc_func, *fputs_func, *fwrite_func;
|
||||
Function *memcpy_func, *memchr_func;
|
||||
Function* sqrt_func;
|
||||
Function *strcpy_func, *strlen_func;
|
||||
Function *floorf_func, *ceilf_func, *roundf_func;
|
||||
Function *rintf_func, *nearbyintf_func;
|
||||
Constant *putchar_func, *puts_func;
|
||||
Constant *fputc_func, *fputs_func, *fwrite_func;
|
||||
Constant *memcpy_func, *memchr_func;
|
||||
Constant *sqrt_func;
|
||||
Constant *strcpy_func, *strlen_func;
|
||||
Constant *floorf_func, *ceilf_func, *roundf_func;
|
||||
Constant *rintf_func, *nearbyintf_func;
|
||||
Module *M; ///< Cached Module
|
||||
TargetData *TD; ///< Cached TargetData
|
||||
};
|
||||
@ -564,12 +564,12 @@ public:
|
||||
if (!CSI) {
|
||||
// The second operand is not constant, or not signed. Just lower this to
|
||||
// memchr since we know the length of the string since it is constant.
|
||||
Function* f = SLC.get_memchr();
|
||||
Constant *f = SLC.get_memchr();
|
||||
std::vector<Value*> args;
|
||||
args.push_back(ci->getOperand(1));
|
||||
args.push_back(ci->getOperand(2));
|
||||
args.push_back(ConstantInt::get(SLC.getIntPtrType(), len));
|
||||
ci->replaceAllUsesWith( new CallInst(f, args, ci->getName(), ci));
|
||||
ci->replaceAllUsesWith(new CallInst(f, args, ci->getName(), ci));
|
||||
ci->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
@ -1344,13 +1344,10 @@ public:
|
||||
return false;
|
||||
|
||||
// printf("%s\n",str) -> puts(str)
|
||||
Function* puts_func = SLC.get_puts();
|
||||
if (!puts_func)
|
||||
return false;
|
||||
std::vector<Value*> args;
|
||||
args.push_back(CastToCStr(ci->getOperand(2), *ci));
|
||||
new CallInst(puts_func,args,ci->getName(),ci);
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,len));
|
||||
new CallInst(SLC.get_puts(), CastToCStr(ci->getOperand(2), *ci),
|
||||
ci->getName(), ci);
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty, len));
|
||||
break;
|
||||
}
|
||||
case 'c':
|
||||
@ -1359,12 +1356,9 @@ public:
|
||||
if (len != 2)
|
||||
return false;
|
||||
|
||||
Function* putchar_func = SLC.get_putchar();
|
||||
if (!putchar_func)
|
||||
return false;
|
||||
CastInst* cast = CastInst::createSExtOrBitCast(
|
||||
CastInst *Char = CastInst::createSExtOrBitCast(
|
||||
ci->getOperand(2), Type::Int32Ty, CI->getName()+".int", ci);
|
||||
new CallInst(putchar_func, cast, "", ci);
|
||||
new CallInst(SLC.get_putchar(), Char, "", ci);
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty, 1));
|
||||
break;
|
||||
}
|
||||
@ -1424,14 +1418,10 @@ public:
|
||||
|
||||
// fprintf(file,fmt) -> fwrite(fmt,strlen(fmt),file)
|
||||
const Type* FILEptr_type = ci->getOperand(1)->getType();
|
||||
Function* fwrite_func = SLC.get_fwrite(FILEptr_type);
|
||||
if (!fwrite_func)
|
||||
return false;
|
||||
|
||||
// Make sure that the fprintf() and fwrite() functions both take the
|
||||
// same type of char pointer.
|
||||
if (ci->getOperand(2)->getType() !=
|
||||
fwrite_func->getFunctionType()->getParamType(0))
|
||||
if (ci->getOperand(2)->getType() != PointerType::get(Type::Int8Ty))
|
||||
return false;
|
||||
|
||||
std::vector<Value*> args;
|
||||
@ -1439,7 +1429,7 @@ public:
|
||||
args.push_back(ConstantInt::get(SLC.getIntPtrType(),len));
|
||||
args.push_back(ConstantInt::get(SLC.getIntPtrType(),1));
|
||||
args.push_back(ci->getOperand(1));
|
||||
new CallInst(fwrite_func,args,ci->getName(),ci);
|
||||
new CallInst(SLC.get_fwrite(FILEptr_type), args, ci->getName(), ci);
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,len));
|
||||
ci->eraseFromParent();
|
||||
return true;
|
||||
@ -1465,26 +1455,19 @@ public:
|
||||
if (getConstantStringLength(ci->getOperand(3), len, &CA)) {
|
||||
// fprintf(file,"%s",str) -> fwrite(str,strlen(str),1,file)
|
||||
const Type* FILEptr_type = ci->getOperand(1)->getType();
|
||||
Function* fwrite_func = SLC.get_fwrite(FILEptr_type);
|
||||
if (!fwrite_func)
|
||||
return false;
|
||||
std::vector<Value*> args;
|
||||
args.push_back(CastToCStr(ci->getOperand(3), *ci));
|
||||
args.push_back(ConstantInt::get(SLC.getIntPtrType(),len));
|
||||
args.push_back(ConstantInt::get(SLC.getIntPtrType(),1));
|
||||
args.push_back(ConstantInt::get(SLC.getIntPtrType(), len));
|
||||
args.push_back(ConstantInt::get(SLC.getIntPtrType(), 1));
|
||||
args.push_back(ci->getOperand(1));
|
||||
new CallInst(fwrite_func,args,ci->getName(),ci);
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,len));
|
||||
new CallInst(SLC.get_fwrite(FILEptr_type), args, ci->getName(), ci);
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty, len));
|
||||
} else {
|
||||
// fprintf(file,"%s",str) -> fputs(str,file)
|
||||
const Type* FILEptr_type = ci->getOperand(1)->getType();
|
||||
Function* fputs_func = SLC.get_fputs(FILEptr_type);
|
||||
if (!fputs_func)
|
||||
return false;
|
||||
std::vector<Value*> args;
|
||||
args.push_back(CastToCStr(ci->getOperand(3), *ci));
|
||||
args.push_back(ci->getOperand(1));
|
||||
new CallInst(fputs_func,args,ci->getName(),ci);
|
||||
new CallInst(SLC.get_fputs(FILEptr_type),
|
||||
CastToCStr(ci->getOperand(3), *ci),
|
||||
ci->getOperand(1), ci->getName(),ci);
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,len));
|
||||
}
|
||||
break;
|
||||
@ -1493,12 +1476,9 @@ public:
|
||||
{
|
||||
// fprintf(file,"%c",c) -> fputc(c,file)
|
||||
const Type* FILEptr_type = ci->getOperand(1)->getType();
|
||||
Function* fputc_func = SLC.get_fputc(FILEptr_type);
|
||||
if (!fputc_func)
|
||||
return false;
|
||||
CastInst* cast = CastInst::createSExtOrBitCast(
|
||||
ci->getOperand(3), Type::Int32Ty, CI->getName()+".int", ci);
|
||||
new CallInst(fputc_func,cast,ci->getOperand(1),"",ci);
|
||||
new CallInst(SLC.get_fputc(FILEptr_type), cast,ci->getOperand(1),"",ci);
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,1));
|
||||
break;
|
||||
}
|
||||
@ -1563,15 +1543,12 @@ public:
|
||||
len++;
|
||||
|
||||
// sprintf(str,fmt) -> llvm.memcpy(str,fmt,strlen(fmt),1)
|
||||
Function* memcpy_func = SLC.get_memcpy();
|
||||
if (!memcpy_func)
|
||||
return false;
|
||||
std::vector<Value*> args;
|
||||
args.push_back(ci->getOperand(1));
|
||||
args.push_back(ci->getOperand(2));
|
||||
args.push_back(ConstantInt::get(SLC.getIntPtrType(),len));
|
||||
args.push_back(ConstantInt::get(Type::Int32Ty,1));
|
||||
new CallInst(memcpy_func,args,"",ci);
|
||||
new CallInst(SLC.get_memcpy(), args, "", ci);
|
||||
ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,len));
|
||||
ci->eraseFromParent();
|
||||
return true;
|
||||
@ -1592,12 +1569,8 @@ public:
|
||||
switch (CI->getZExtValue()) {
|
||||
case 's': {
|
||||
// sprintf(dest,"%s",str) -> llvm.memcpy(dest, str, strlen(str)+1, 1)
|
||||
Function* strlen_func = SLC.get_strlen();
|
||||
Function* memcpy_func = SLC.get_memcpy();
|
||||
if (!strlen_func || !memcpy_func)
|
||||
return false;
|
||||
|
||||
Value *Len = new CallInst(strlen_func, CastToCStr(ci->getOperand(3), *ci),
|
||||
Value *Len = new CallInst(SLC.get_strlen(),
|
||||
CastToCStr(ci->getOperand(3), *ci),
|
||||
ci->getOperand(3)->getName()+".len", ci);
|
||||
Value *Len1 = BinaryOperator::createAdd(Len,
|
||||
ConstantInt::get(Len->getType(), 1),
|
||||
@ -1610,7 +1583,7 @@ public:
|
||||
args.push_back(CastToCStr(ci->getOperand(3), *ci));
|
||||
args.push_back(Len1);
|
||||
args.push_back(ConstantInt::get(Type::Int32Ty,1));
|
||||
new CallInst(memcpy_func, args, "", ci);
|
||||
new CallInst(SLC.get_memcpy(), args, "", ci);
|
||||
|
||||
// The strlen result is the unincremented number of bytes in the string.
|
||||
if (!ci->use_empty()) {
|
||||
@ -1676,29 +1649,24 @@ public:
|
||||
{
|
||||
// fputs(s,F) -> fputc(s[0],F) (if s is constant and strlen(s) == 1)
|
||||
const Type* FILEptr_type = ci->getOperand(2)->getType();
|
||||
Function* fputc_func = SLC.get_fputc(FILEptr_type);
|
||||
if (!fputc_func)
|
||||
return false;
|
||||
LoadInst* loadi = new LoadInst(ci->getOperand(1),
|
||||
ci->getOperand(1)->getName()+".byte",ci);
|
||||
CastInst* casti = new SExtInst(loadi, Type::Int32Ty,
|
||||
loadi->getName()+".int", ci);
|
||||
new CallInst(fputc_func,casti,ci->getOperand(2),"",ci);
|
||||
new CallInst(SLC.get_fputc(FILEptr_type), casti,
|
||||
ci->getOperand(2), "", ci);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// fputs(s,F) -> fwrite(s,1,len,F) (if s is constant and strlen(s) > 1)
|
||||
const Type* FILEptr_type = ci->getOperand(2)->getType();
|
||||
Function* fwrite_func = SLC.get_fwrite(FILEptr_type);
|
||||
if (!fwrite_func)
|
||||
return false;
|
||||
std::vector<Value*> parms;
|
||||
parms.push_back(ci->getOperand(1));
|
||||
parms.push_back(ConstantInt::get(SLC.getIntPtrType(),len));
|
||||
parms.push_back(ConstantInt::get(SLC.getIntPtrType(),1));
|
||||
parms.push_back(ci->getOperand(2));
|
||||
new CallInst(fwrite_func,parms,"",ci);
|
||||
new CallInst(SLC.get_fwrite(FILEptr_type), parms, "", ci);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1860,7 +1828,7 @@ public:
|
||||
case Type::Int64TyID : CTTZName = "llvm.cttz.i64"; break;
|
||||
}
|
||||
|
||||
Function *F = SLC.getModule()->getOrInsertFunction(CTTZName, ArgType,
|
||||
Constant *F = SLC.getModule()->getOrInsertFunction(CTTZName, ArgType,
|
||||
ArgType, NULL);
|
||||
Value *V = CastInst::createIntegerCast(TheCall->getOperand(1), ArgType,
|
||||
false/*ZExt*/, "tmp", TheCall);
|
||||
@ -1921,7 +1889,7 @@ struct UnaryDoubleFPOptimizer : public LibCallOptimization {
|
||||
/// when the target supports the destination function and where there can be
|
||||
/// no precision loss.
|
||||
static bool ShrinkFunctionToFloatVersion(CallInst *CI, SimplifyLibCalls &SLC,
|
||||
Function *(SimplifyLibCalls::*FP)()){
|
||||
Constant *(SimplifyLibCalls::*FP)()){
|
||||
if (CastInst *Cast = dyn_cast<CastInst>(CI->getOperand(1)))
|
||||
if (Cast->getOperand(0)->getType() == Type::FloatTy) {
|
||||
Value *New = new CallInst((SLC.*FP)(), Cast->getOperand(0),
|
||||
|
@ -32,8 +32,8 @@ namespace {
|
||||
/// %free calls.
|
||||
///
|
||||
class VISIBILITY_HIDDEN LowerAllocations : public BasicBlockPass {
|
||||
Function *MallocFunc; // Functions in the module we are processing
|
||||
Function *FreeFunc; // Initialized by doInitialization
|
||||
Constant *MallocFunc; // Functions in the module we are processing
|
||||
Constant *FreeFunc; // Initialized by doInitialization
|
||||
bool LowerMallocArgToInteger;
|
||||
public:
|
||||
LowerAllocations(bool LowerToInt = false)
|
||||
@ -84,19 +84,12 @@ FunctionPass *llvm::createLowerAllocationsPass(bool LowerMallocArgToInteger) {
|
||||
// This function is always successful.
|
||||
//
|
||||
bool LowerAllocations::doInitialization(Module &M) {
|
||||
const Type *SBPTy = PointerType::get(Type::Int8Ty);
|
||||
MallocFunc = M.getNamedFunction("malloc");
|
||||
FreeFunc = M.getNamedFunction("free");
|
||||
|
||||
if (MallocFunc == 0) {
|
||||
// Prototype malloc as "void* malloc(...)", because we don't know in
|
||||
// doInitialization whether size_t is int or long.
|
||||
FunctionType *FT = FunctionType::get(SBPTy,std::vector<const Type*>(),true);
|
||||
MallocFunc = M.getOrInsertFunction("malloc", FT);
|
||||
}
|
||||
if (FreeFunc == 0)
|
||||
FreeFunc = M.getOrInsertFunction("free" , Type::VoidTy, SBPTy, (Type *)0);
|
||||
|
||||
const Type *BPTy = PointerType::get(Type::Int8Ty);
|
||||
// Prototype malloc as "char* malloc(...)", because we don't know in
|
||||
// doInitialization whether size_t is int or long.
|
||||
FunctionType *FT = FunctionType::get(BPTy, std::vector<const Type*>(), true);
|
||||
MallocFunc = M.getOrInsertFunction("malloc", FT);
|
||||
FreeFunc = M.getOrInsertFunction("free" , Type::VoidTy, BPTy, (Type *)0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -145,27 +138,8 @@ bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
|
||||
}
|
||||
}
|
||||
|
||||
const FunctionType *MallocFTy = MallocFunc->getFunctionType();
|
||||
std::vector<Value*> MallocArgs;
|
||||
|
||||
if (MallocFTy->getNumParams() > 0 || MallocFTy->isVarArg()) {
|
||||
if (MallocFTy->isVarArg()) {
|
||||
if (MallocArg->getType() != IntPtrTy)
|
||||
MallocArg = CastInst::createIntegerCast(MallocArg, IntPtrTy,
|
||||
false /*ZExt*/, "", I);
|
||||
} else if (MallocFTy->getNumParams() > 0 &&
|
||||
MallocFTy->getParamType(0) != Type::Int32Ty)
|
||||
MallocArg = CastInst::createIntegerCast(
|
||||
MallocArg, MallocFTy->getParamType(0), false/*ZExt*/, "",I);
|
||||
MallocArgs.push_back(MallocArg);
|
||||
}
|
||||
|
||||
// If malloc is prototyped to take extra arguments, pass nulls.
|
||||
for (unsigned i = 1; i < MallocFTy->getNumParams(); ++i)
|
||||
MallocArgs.push_back(Constant::getNullValue(MallocFTy->getParamType(i)));
|
||||
|
||||
// Create the call to Malloc...
|
||||
CallInst *MCall = new CallInst(MallocFunc, MallocArgs, "", I);
|
||||
// Create the call to Malloc.
|
||||
CallInst *MCall = new CallInst(MallocFunc, MallocArg, "", I);
|
||||
MCall->setTailCall();
|
||||
|
||||
// Create a cast instruction to convert to the right type...
|
||||
@ -181,23 +155,11 @@ bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
|
||||
Changed = true;
|
||||
++NumLowered;
|
||||
} else if (FreeInst *FI = dyn_cast<FreeInst>(I)) {
|
||||
const FunctionType *FreeFTy = FreeFunc->getFunctionType();
|
||||
std::vector<Value*> FreeArgs;
|
||||
|
||||
if (FreeFTy->getNumParams() > 0 || FreeFTy->isVarArg()) {
|
||||
Value *MCast = FI->getOperand(0);
|
||||
if (FreeFTy->getNumParams() > 0 &&
|
||||
FreeFTy->getParamType(0) != MCast->getType())
|
||||
MCast = new BitCastInst(MCast, FreeFTy->getParamType(0), "", I);
|
||||
FreeArgs.push_back(MCast);
|
||||
}
|
||||
|
||||
// If malloc is prototyped to take extra arguments, pass nulls.
|
||||
for (unsigned i = 1; i < FreeFTy->getNumParams(); ++i)
|
||||
FreeArgs.push_back(Constant::getNullValue(FreeFTy->getParamType(i)));
|
||||
Value *PtrCast = new BitCastInst(FI->getOperand(0),
|
||||
PointerType::get(Type::Int8Ty), "", I);
|
||||
|
||||
// Insert a call to the free function...
|
||||
(new CallInst(FreeFunc, FreeArgs, "", I))->setTailCall();
|
||||
(new CallInst(FreeFunc, PtrCast, "", I))->setTailCall();
|
||||
|
||||
// Delete the old free instruction
|
||||
I = --BBIL.erase(I);
|
||||
|
@ -60,15 +60,15 @@ static cl::opt<bool> ExpensiveEHSupport("enable-correct-eh-support",
|
||||
namespace {
|
||||
class VISIBILITY_HIDDEN LowerInvoke : public FunctionPass {
|
||||
// Used for both models.
|
||||
Function *WriteFn;
|
||||
Function *AbortFn;
|
||||
Constant *WriteFn;
|
||||
Constant *AbortFn;
|
||||
Value *AbortMessage;
|
||||
unsigned AbortMessageLength;
|
||||
|
||||
// Used for expensive EH support.
|
||||
const Type *JBLinkTy;
|
||||
GlobalVariable *JBListHead;
|
||||
Function *SetJmpFn, *LongJmpFn;
|
||||
Constant *SetJmpFn, *LongJmpFn;
|
||||
|
||||
// We peek in TLI to grab the target's jmp_buf size and alignment
|
||||
const TargetLowering *TLI;
|
||||
@ -87,7 +87,7 @@ namespace {
|
||||
}
|
||||
|
||||
private:
|
||||
void createAbortMessage();
|
||||
void createAbortMessage(Module *M);
|
||||
void writeAbortMessage(Instruction *IB);
|
||||
bool insertCheapEHSupport(Function &F);
|
||||
void splitLiveRangesLiveAcrossInvokes(std::vector<InvokeInst*> &Invokes);
|
||||
@ -148,29 +148,12 @@ bool LowerInvoke::doInitialization(Module &M) {
|
||||
|
||||
// We need the 'write' and 'abort' functions for both models.
|
||||
AbortFn = M.getOrInsertFunction("abort", Type::VoidTy, (Type *)0);
|
||||
|
||||
// Unfortunately, 'write' can end up being prototyped in several different
|
||||
// ways. If the user defines a three (or more) operand function named 'write'
|
||||
// we will use their prototype. We _do not_ want to insert another instance
|
||||
// of a write prototype, because we don't know that the funcresolve pass will
|
||||
// run after us. If there is a definition of a write function, but it's not
|
||||
// suitable for our uses, we just don't emit write calls. If there is no
|
||||
// write prototype at all, we just add one.
|
||||
if (Function *WF = M.getNamedFunction("write")) {
|
||||
if (WF->getFunctionType()->getNumParams() > 3 ||
|
||||
WF->getFunctionType()->isVarArg())
|
||||
WriteFn = WF;
|
||||
else
|
||||
WriteFn = 0;
|
||||
} else {
|
||||
WriteFn = M.getOrInsertFunction("write", Type::VoidTy, Type::Int32Ty,
|
||||
VoidPtrTy, Type::Int32Ty, (Type *)0);
|
||||
}
|
||||
WriteFn = M.getOrInsertFunction("write", Type::VoidTy, Type::Int32Ty,
|
||||
VoidPtrTy, Type::Int32Ty, (Type *)0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LowerInvoke::createAbortMessage() {
|
||||
Module &M = *WriteFn->getParent();
|
||||
void LowerInvoke::createAbortMessage(Module *M) {
|
||||
if (ExpensiveEHSupport) {
|
||||
// The abort message for expensive EH support tells the user that the
|
||||
// program 'unwound' without an 'invoke' instruction.
|
||||
@ -180,7 +163,7 @@ void LowerInvoke::createAbortMessage() {
|
||||
|
||||
GlobalVariable *MsgGV = new GlobalVariable(Msg->getType(), true,
|
||||
GlobalValue::InternalLinkage,
|
||||
Msg, "abortmsg", &M);
|
||||
Msg, "abortmsg", M);
|
||||
std::vector<Constant*> GEPIdx(2, Constant::getNullValue(Type::Int32Ty));
|
||||
AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, GEPIdx);
|
||||
} else {
|
||||
@ -193,7 +176,7 @@ void LowerInvoke::createAbortMessage() {
|
||||
|
||||
GlobalVariable *MsgGV = new GlobalVariable(Msg->getType(), true,
|
||||
GlobalValue::InternalLinkage,
|
||||
Msg, "abortmsg", &M);
|
||||
Msg, "abortmsg", M);
|
||||
std::vector<Constant*> GEPIdx(2, Constant::getNullValue(Type::Int32Ty));
|
||||
AbortMessage = ConstantExpr::getGetElementPtr(MsgGV, GEPIdx);
|
||||
}
|
||||
@ -201,30 +184,15 @@ void LowerInvoke::createAbortMessage() {
|
||||
|
||||
|
||||
void LowerInvoke::writeAbortMessage(Instruction *IB) {
|
||||
if (WriteFn) {
|
||||
if (AbortMessage == 0) createAbortMessage();
|
||||
if (AbortMessage == 0)
|
||||
createAbortMessage(IB->getParent()->getParent()->getParent());
|
||||
|
||||
// These are the arguments we WANT...
|
||||
std::vector<Value*> Args;
|
||||
Args.push_back(ConstantInt::get(Type::Int32Ty, 2));
|
||||
Args.push_back(AbortMessage);
|
||||
Args.push_back(ConstantInt::get(Type::Int32Ty, AbortMessageLength));
|
||||
|
||||
// If the actual declaration of write disagrees, insert casts as
|
||||
// appropriate.
|
||||
const FunctionType *FT = WriteFn->getFunctionType();
|
||||
unsigned NumArgs = FT->getNumParams();
|
||||
for (unsigned i = 0; i != 3; ++i)
|
||||
if (i < NumArgs && FT->getParamType(i) != Args[i]->getType())
|
||||
if (Args[i]->getType()->isInteger())
|
||||
Args[i] = ConstantExpr::getIntegerCast(cast<Constant>(Args[i]),
|
||||
FT->getParamType(i), true);
|
||||
else
|
||||
Args[i] = ConstantExpr::getBitCast(cast<Constant>(Args[i]),
|
||||
FT->getParamType(i));
|
||||
|
||||
(new CallInst(WriteFn, Args, "", IB))->setTailCall();
|
||||
}
|
||||
// These are the arguments we WANT...
|
||||
std::vector<Value*> Args;
|
||||
Args.push_back(ConstantInt::get(Type::Int32Ty, 2));
|
||||
Args.push_back(AbortMessage);
|
||||
Args.push_back(ConstantInt::get(Type::Int32Ty, AbortMessageLength));
|
||||
(new CallInst(WriteFn, Args, "", IB))->setTailCall();
|
||||
}
|
||||
|
||||
bool LowerInvoke::insertCheapEHSupport(Function &F) {
|
||||
|
Loading…
Reference in New Issue
Block a user