[opaque pointer type] Avoid using PointerType::getElementType for a few cases of CallInst

Calls to llvm::Value::mutateType are becoming extra-sensitive now that
instructions have extra type information that will not be derived from
operands or result type (alloca, gep, load, call/invoke, etc... ). The
special-handling for mutateType will get more complicated as this work
continues - it might be worth making mutateType virtual & pushing the
complexity down into the classes that need special handling. But with
only two significant uses of mutateType (vectorization and linking) this
seems OK for now.

Totally open to ideas/suggestions/improvements, of course.

With this, and a bunch of exceptions, we can roundtrip an indirect call
site through bitcode and IR. (a direct call site is actually trickier...
I haven't figured out how to deal with the IR deserializer's lazy
construction of Function/GlobalVariable decl's based on the type of the
entity which means looking through the "pointer to T" type referring to
the global)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235458 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Blaikie 2015-04-21 23:26:57 +00:00
parent bc4233f437
commit d62a1e966c
8 changed files with 116 additions and 46 deletions

View File

@ -194,6 +194,14 @@ public:
CALLSITE_DELEGATE_SETTER(setCallingConv(CC)); CALLSITE_DELEGATE_SETTER(setCallingConv(CC));
} }
FunctionType *getFunctionType() const {
CALLSITE_DELEGATE_GETTER(getFunctionType());
}
void mutateFunctionType(FunctionType *Ty) const {
CALLSITE_DELEGATE_SETTER(mutateFunctionType(Ty));
}
/// getAttributes/setAttributes - get or set the parameter attributes of /// getAttributes/setAttributes - get or set the parameter attributes of
/// the call. /// the call.
const AttributeSet &getAttributes() const { const AttributeSet &getAttributes() const {

View File

@ -1284,14 +1284,26 @@ public:
/// ///
class CallInst : public Instruction { class CallInst : public Instruction {
AttributeSet AttributeList; ///< parameter attributes for call AttributeSet AttributeList; ///< parameter attributes for call
FunctionType *FTy;
CallInst(const CallInst &CI); CallInst(const CallInst &CI);
void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr); void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) {
init(cast<FunctionType>(
cast<PointerType>(Func->getType())->getElementType()),
Func, Args, NameStr);
}
void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
const Twine &NameStr);
void init(Value *Func, const Twine &NameStr); void init(Value *Func, const Twine &NameStr);
/// Construct a CallInst given a range of arguments. /// Construct a CallInst given a range of arguments.
/// \brief Construct a CallInst from a range of arguments /// \brief Construct a CallInst from a range of arguments
inline CallInst(Value *Func, ArrayRef<Value *> Args, inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
const Twine &NameStr, Instruction *InsertBefore); const Twine &NameStr, Instruction *InsertBefore);
inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr,
Instruction *InsertBefore)
: CallInst(cast<FunctionType>(
cast<PointerType>(Func->getType())->getElementType()),
Func, Args, NameStr, InsertBefore) {}
/// Construct a CallInst given a range of arguments. /// Construct a CallInst given a range of arguments.
/// \brief Construct a CallInst from a range of arguments /// \brief Construct a CallInst from a range of arguments
@ -1308,8 +1320,15 @@ public:
ArrayRef<Value *> Args, ArrayRef<Value *> Args,
const Twine &NameStr = "", const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) { Instruction *InsertBefore = nullptr) {
return new(unsigned(Args.size() + 1)) return Create(cast<FunctionType>(
CallInst(Func, Args, NameStr, InsertBefore); cast<PointerType>(Func->getType())->getElementType()),
Func, Args, NameStr, InsertBefore);
}
static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
return new (unsigned(Args.size() + 1))
CallInst(Ty, Func, Args, NameStr, InsertBefore);
} }
static CallInst *Create(Value *Func, static CallInst *Create(Value *Func,
ArrayRef<Value *> Args, ArrayRef<Value *> Args,
@ -1347,9 +1366,11 @@ public:
~CallInst() override; ~CallInst() override;
FunctionType *getFunctionType() const { FunctionType *getFunctionType() const { return FTy; }
return cast<FunctionType>(
cast<PointerType>(getCalledValue()->getType())->getElementType()); void mutateFunctionType(FunctionType *FTy) {
mutateType(FTy->getReturnType());
this->FTy = FTy;
} }
// Note that 'musttail' implies 'tail'. // Note that 'musttail' implies 'tail'.
@ -1533,6 +1554,14 @@ public:
/// setCalledFunction - Set the function called. /// setCalledFunction - Set the function called.
void setCalledFunction(Value* Fn) { void setCalledFunction(Value* Fn) {
setCalledFunction(
cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()),
Fn);
}
void setCalledFunction(FunctionType *FTy, Value *Fn) {
this->FTy = FTy;
assert(FTy == cast<FunctionType>(
cast<PointerType>(Fn->getType())->getElementType()));
Op<-1>() = Fn; Op<-1>() = Fn;
} }
@ -1573,14 +1602,12 @@ CallInst::CallInst(Value *Func, ArrayRef<Value *> Args,
init(Func, Args, NameStr); init(Func, Args, NameStr);
} }
CallInst::CallInst(Value *Func, ArrayRef<Value *> Args, CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
const Twine &NameStr, Instruction *InsertBefore) const Twine &NameStr, Instruction *InsertBefore)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) : Instruction(Ty->getReturnType(), Instruction::Call,
->getElementType())->getReturnType(), OperandTraits<CallInst>::op_end(this) - (Args.size() + 1),
Instruction::Call, unsigned(Args.size() + 1), InsertBefore) {
OperandTraits<CallInst>::op_end(this) - (Args.size() + 1), init(Ty, Func, Args, NameStr);
unsigned(Args.size() + 1), InsertBefore) {
init(Func, Args, NameStr);
} }
@ -3034,6 +3061,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value)
/// ///
class InvokeInst : public TerminatorInst { class InvokeInst : public TerminatorInst {
AttributeSet AttributeList; AttributeSet AttributeList;
FunctionType *FTy;
InvokeInst(const InvokeInst &BI); InvokeInst(const InvokeInst &BI);
void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
ArrayRef<Value *> Args, const Twine &NameStr); ArrayRef<Value *> Args, const Twine &NameStr);
@ -3074,6 +3102,13 @@ public:
/// Provide fast operand accessors /// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
FunctionType *getFunctionType() const { return FTy; }
void mutateFunctionType(FunctionType *FTy) {
mutateType(FTy->getReturnType());
this->FTy = FTy;
}
/// getNumArgOperands - Return the number of invoke arguments. /// getNumArgOperands - Return the number of invoke arguments.
/// ///
unsigned getNumArgOperands() const { return getNumOperands() - 3; } unsigned getNumArgOperands() const { return getNumOperands() - 3; }
@ -3223,6 +3258,14 @@ public:
/// setCalledFunction - Set the function called. /// setCalledFunction - Set the function called.
void setCalledFunction(Value* Fn) { void setCalledFunction(Value* Fn) {
setCalledFunction(
cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()),
Fn);
}
void setCalledFunction(FunctionType *FTy, Value *Fn) {
this->FTy = FTy;
assert(FTy == cast<FunctionType>(
cast<PointerType>(Fn->getType())->getElementType()));
Op<-3>() = Fn; Op<-3>() = Fn;
} }

View File

@ -5224,7 +5224,7 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
// Finish off the Attribute and check them // Finish off the Attribute and check them
AttributeSet PAL = AttributeSet::get(Context, Attrs); AttributeSet PAL = AttributeSet::get(Context, Attrs);
CallInst *CI = CallInst::Create(Callee, Args); CallInst *CI = CallInst::Create(Ty, Callee, Args);
CI->setTailCallKind(TCK); CI->setTailCallKind(TCK);
CI->setCallingConv(CC); CI->setCallingConv(CC);
CI->setAttributes(PAL); CI->setAttributes(PAL);

View File

@ -4184,12 +4184,11 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
PointerType *OpTy = dyn_cast<PointerType>(Callee->getType()); PointerType *OpTy = dyn_cast<PointerType>(Callee->getType());
if (!OpTy) if (!OpTy)
return Error("Callee is not a pointer type"); return Error("Callee is not a pointer type");
FunctionType *PFTy = dyn_cast<FunctionType>(OpTy->getElementType()); if (!FTy) {
if (!PFTy) FTy = dyn_cast<FunctionType>(OpTy->getElementType());
return Error("Callee is not of pointer to function type"); if (!FTy)
if (!FTy) return Error("Callee is not of pointer to function type");
FTy = PFTy; } else if (OpTy->getElementType() != FTy)
if (PFTy != FTy)
return Error("Explicit call type does not match pointee type of " return Error("Explicit call type does not match pointee type of "
"callee operand"); "callee operand");
if (Record.size() < FTy->getNumParams() + OpNum) if (Record.size() < FTy->getNumParams() + OpNum)
@ -4220,7 +4219,7 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
} }
} }
I = CallInst::Create(Callee, Args); I = CallInst::Create(FTy, Callee, Args);
InstructionList.push_back(I); InstructionList.push_back(I);
cast<CallInst>(I)->setCallingConv( cast<CallInst>(I)->setCallingConv(
static_cast<CallingConv::ID>((~(1U << 14) & CCInfo) >> 1)); static_cast<CallingConv::ID>((~(1U << 14) & CCInfo) >> 1));

View File

@ -263,14 +263,13 @@ void LandingPadInst::addClause(Constant *Val) {
CallInst::~CallInst() { CallInst::~CallInst() {
} }
void CallInst::init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) { void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
const Twine &NameStr) {
this->FTy = FTy;
assert(NumOperands == Args.size() + 1 && "NumOperands not set up?"); assert(NumOperands == Args.size() + 1 && "NumOperands not set up?");
Op<-1>() = Func; Op<-1>() = Func;
#ifndef NDEBUG #ifndef NDEBUG
FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
assert((Args.size() == FTy->getNumParams() || assert((Args.size() == FTy->getNumParams() ||
(FTy->isVarArg() && Args.size() > FTy->getNumParams())) && (FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
"Calling a function with bad signature!"); "Calling a function with bad signature!");
@ -286,15 +285,12 @@ void CallInst::init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) {
} }
void CallInst::init(Value *Func, const Twine &NameStr) { void CallInst::init(Value *Func, const Twine &NameStr) {
FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
assert(NumOperands == 1 && "NumOperands not set up?"); assert(NumOperands == 1 && "NumOperands not set up?");
Op<-1>() = Func; Op<-1>() = Func;
#ifndef NDEBUG
FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
assert(FTy->getNumParams() == 0 && "Calling a function with bad signature"); assert(FTy->getNumParams() == 0 && "Calling a function with bad signature");
#endif
setName(NameStr); setName(NameStr);
} }
@ -320,10 +316,10 @@ CallInst::CallInst(Value *Func, const Twine &Name,
} }
CallInst::CallInst(const CallInst &CI) CallInst::CallInst(const CallInst &CI)
: Instruction(CI.getType(), Instruction::Call, : Instruction(CI.getType(), Instruction::Call,
OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(), OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(),
CI.getNumOperands()) { CI.getNumOperands()),
setAttributes(CI.getAttributes()); AttributeList(CI.AttributeList), FTy(CI.FTy) {
setTailCallKind(CI.getTailCallKind()); setTailCallKind(CI.getTailCallKind());
setCallingConv(CI.getCallingConv()); setCallingConv(CI.getCallingConv());
@ -543,15 +539,14 @@ Instruction* CallInst::CreateFree(Value* Source, BasicBlock *InsertAtEnd) {
void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
ArrayRef<Value *> Args, const Twine &NameStr) { ArrayRef<Value *> Args, const Twine &NameStr) {
FTy = cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType());
assert(NumOperands == 3 + Args.size() && "NumOperands not set up?"); assert(NumOperands == 3 + Args.size() && "NumOperands not set up?");
Op<-3>() = Fn; Op<-3>() = Fn;
Op<-2>() = IfNormal; Op<-2>() = IfNormal;
Op<-1>() = IfException; Op<-1>() = IfException;
#ifndef NDEBUG #ifndef NDEBUG
FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType());
assert(((Args.size() == FTy->getNumParams()) || assert(((Args.size() == FTy->getNumParams()) ||
(FTy->isVarArg() && Args.size() > FTy->getNumParams())) && (FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
"Invoking a function with bad signature"); "Invoking a function with bad signature");
@ -567,11 +562,11 @@ void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
} }
InvokeInst::InvokeInst(const InvokeInst &II) InvokeInst::InvokeInst(const InvokeInst &II)
: TerminatorInst(II.getType(), Instruction::Invoke, : TerminatorInst(II.getType(), Instruction::Invoke,
OperandTraits<InvokeInst>::op_end(this) OperandTraits<InvokeInst>::op_end(this) -
- II.getNumOperands(), II.getNumOperands(),
II.getNumOperands()) { II.getNumOperands()),
setAttributes(II.getAttributes()); AttributeList(II.AttributeList), FTy(II.FTy) {
setCallingConv(II.getCallingConv()); setCallingConv(II.getCallingConv());
std::copy(II.op_begin(), II.op_end(), op_begin()); std::copy(II.op_begin(), II.op_end(), op_begin());
SubclassOptionalData = II.SubclassOptionalData; SubclassOptionalData = II.SubclassOptionalData;

View File

@ -2120,7 +2120,11 @@ void Verifier::VerifyCallSite(CallSite CS) {
Assert(FPTy->getElementType()->isFunctionTy(), Assert(FPTy->getElementType()->isFunctionTy(),
"Called function is not pointer to function type!", I); "Called function is not pointer to function type!", I);
FunctionType *FTy = cast<FunctionType>(FPTy->getElementType());
Assert(FPTy->getElementType() == CS.getFunctionType(),
"Called function is not the same type as the call!", I);
FunctionType *FTy = CS.getFunctionType();
// Verify that the correct number of arguments are being passed // Verify that the correct number of arguments are being passed
if (FTy->isVarArg()) if (FTy->isVarArg())

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/ValueMapper.h" #include "llvm/Transforms/Utils/ValueMapper.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h" #include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h" #include "llvm/IR/InlineAsm.h"
@ -384,6 +385,16 @@ void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap,
} }
// If the instruction's type is being remapped, do so now. // If the instruction's type is being remapped, do so now.
if (TypeMapper) if (auto CS = CallSite(I)) {
SmallVector<Type *, 3> Tys;
FunctionType *Old = CS.getFunctionType();
unsigned NumOld = Old->getNumParams();
assert(NumOld <= CS.arg_size());
for (unsigned i = 0; i != NumOld; ++i)
Tys.push_back(CS.getArgument(i)->getType());
CS.mutateFunctionType(FunctionType::get(
TypeMapper ? TypeMapper->remapType(I->getType()) : I->getType(), Tys,
Old->isVarArg()));
} else if (TypeMapper)
I->mutateType(TypeMapper->remapType(I->getType())); I->mutateType(TypeMapper->remapType(I->getType()));
} }

View File

@ -3103,7 +3103,17 @@ namespace {
else if (H->hasName()) else if (H->hasName())
K->takeName(H); K->takeName(H);
if (!isa<StoreInst>(K)) if (auto CS = CallSite(K)) {
SmallVector<Type *, 3> Tys;
FunctionType *Old = CS.getFunctionType();
unsigned NumOld = Old->getNumParams();
assert(NumOld <= ReplacedOperands.size());
for (unsigned i = 0; i != NumOld; ++i)
Tys.push_back(ReplacedOperands[i]->getType());
CS.mutateFunctionType(
FunctionType::get(getVecTypeForPair(L->getType(), H->getType()),
Tys, Old->isVarArg()));
} else if (!isa<StoreInst>(K))
K->mutateType(getVecTypeForPair(L->getType(), H->getType())); K->mutateType(getVecTypeForPair(L->getType(), H->getType()));
unsigned KnownIDs[] = { unsigned KnownIDs[] = {