Skip to content

Commit

Permalink
[Verifier] Verify invokes of intrinsics
Browse files Browse the repository at this point in the history
We support invoking a subset of llvm's intrinsics, but the verifier didn't account for this.  We had previously added a special case to verify invokes of statepoints.  By generalizing the code in terms of CallSite, we can verify invokes of other intrinsics as well.  Interestingly, this found one test case which was invalid.

Note: I'm deliberately leaving the naming change from CI to CS to a follow up change.  That will happen shortly, I just wanted to reduce the diff to make it clear what was happening with this one.

Differential Revision: http://reviews.llvm.org/D10118



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240836 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
preames committed Jun 26, 2015
1 parent 7cb828a commit f84a650
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 23 deletions.
23 changes: 21 additions & 2 deletions include/llvm/IR/CallSite.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class CallInst;
class InvokeInst;

template <typename FunTy = const Function,
typename BBTy = const BasicBlock,
typename ValTy = const Value,
typename UserTy = const User,
typename InstrTy = const Instruction,
Expand Down Expand Up @@ -82,6 +83,9 @@ class CallSiteBase {
InstrTy *operator->() const { return I.getPointer(); }
explicit operator bool() const { return I.getPointer(); }

/// Get the basic block containing the call site
BBTy* getParent() const { return getInstruction()->getParent(); }

/// getCalledValue - Return the pointer to function that is being called.
///
ValTy *getCalledValue() const {
Expand Down Expand Up @@ -189,6 +193,20 @@ class CallSiteBase {
else \
cast<InvokeInst>(II)->METHOD

unsigned getNumArgOperands() const {
CALLSITE_DELEGATE_GETTER(getNumArgOperands());
}

Value *getArgOperand(unsigned i) const {
CALLSITE_DELEGATE_GETTER(getArgOperand(i));
}

bool isInlineAsm() const {
if (isCall())
return cast<CallInst>(getInstruction())->isInlineAsm();
return false;
}

/// getCallingConv/setCallingConv - get or set the calling convention of the
/// call.
CallingConv::ID getCallingConv() const {
Expand Down Expand Up @@ -366,8 +384,9 @@ class CallSiteBase {
}
};

class CallSite : public CallSiteBase<Function, Value, User, Instruction,
CallInst, InvokeInst, User::op_iterator> {
class CallSite : public CallSiteBase<Function, BasicBlock, Value, User,
Instruction, CallInst, InvokeInst,
User::op_iterator> {
public:
CallSite() {}
CallSite(CallSiteBase B) : CallSiteBase(B) {}
Expand Down
36 changes: 17 additions & 19 deletions lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ struct VerifierSupport {
OS << '\n';
}
}
void Write(const CallSite *CS) {
if (!CS)
return;
Write(CS->getInstruction());
}

void Write(const Metadata *MD) {
if (!MD)
Expand Down Expand Up @@ -367,7 +372,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
void visitSelectInst(SelectInst &SI);
void visitUserOp1(Instruction &I);
void visitUserOp2(Instruction &I) { visitUserOp1(I); }
void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI);
void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallSite CS);
template <class DbgIntrinsicTy>
void visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII);
void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);
Expand Down Expand Up @@ -2289,6 +2294,10 @@ void Verifier::VerifyCallSite(CallSite CS) {
"Function has metadata parameter but isn't an intrinsic", I);
}

if (Function *F = CS.getCalledFunction())
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
visitIntrinsicFunctionCall(ID, CS);

visitInstruction(*I);
}

Expand Down Expand Up @@ -2384,10 +2393,6 @@ void Verifier::visitCallInst(CallInst &CI) {

if (CI.isMustTailCall())
verifyMustTailCall(CI);

if (Function *F = CI.getCalledFunction())
if (Intrinsic::ID ID = F->getIntrinsicID())
visitIntrinsicFunctionCall(ID, CI);
}

void Verifier::visitInvokeInst(InvokeInst &II) {
Expand All @@ -2398,13 +2403,6 @@ void Verifier::visitInvokeInst(InvokeInst &II) {
Assert(II.getUnwindDest()->isLandingPad(),
"The unwind destination does not have a landingpad instruction!", &II);

if (Function *F = II.getCalledFunction())
// TODO: Ideally we should use visitIntrinsicFunction here. But it uses
// CallInst as an input parameter. It not woth updating this whole
// function only to support statepoint verification.
if (F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint)
VerifyStatepoint(ImmutableCallSite(&II));

visitTerminatorInst(II);
}

Expand Down Expand Up @@ -3146,7 +3144,7 @@ Verifier::VerifyIntrinsicIsVarArg(bool isVarArg,

/// visitIntrinsicFunction - Allow intrinsics to be verified in different ways.
///
void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallSite CI) {
Function *IF = CI.getCalledFunction();
Assert(IF->isDeclaration(), "Intrinsic functions should never be defined!",
IF);
Expand Down Expand Up @@ -3208,10 +3206,10 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
case Intrinsic::dbg_declare: // llvm.dbg.declare
Assert(isa<MetadataAsValue>(CI.getArgOperand(0)),
"invalid llvm.dbg.declare intrinsic call 1", &CI);
visitDbgIntrinsic("declare", cast<DbgDeclareInst>(CI));
visitDbgIntrinsic("declare", cast<DbgDeclareInst>(*CI.getInstruction()));
break;
case Intrinsic::dbg_value: // llvm.dbg.value
visitDbgIntrinsic("value", cast<DbgValueInst>(CI));
visitDbgIntrinsic("value", cast<DbgValueInst>(*CI.getInstruction()));
break;
case Intrinsic::memcpy:
case Intrinsic::memmove:
Expand Down Expand Up @@ -3282,7 +3280,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
"llvm.frameescape used outside of entry block", &CI);
Assert(!SawFrameEscape,
"multiple calls to llvm.frameescape in one function", &CI);
for (Value *Arg : CI.arg_operands()) {
for (Value *Arg : CI.args()) {
if (isa<ConstantPointerNull>(Arg))
continue; // Null values are allowed as placeholders.
auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts());
Expand Down Expand Up @@ -3315,7 +3313,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
Assert(CI.getParent()->getParent()->hasGC(),
"Enclosing function does not use GC.", &CI);

VerifyStatepoint(ImmutableCallSite(&CI));
VerifyStatepoint(ImmutableCallSite(CI));
break;
case Intrinsic::experimental_gc_result_int:
case Intrinsic::experimental_gc_result_float:
Expand Down Expand Up @@ -3377,7 +3375,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {

// Verify rest of the relocate arguments

GCRelocateOperands Ops(&CI);
GCRelocateOperands Ops(CI);
ImmutableCallSite StatepointCS(Ops.getStatepoint());

// Both the base and derived must be piped through the safepoint
Expand Down Expand Up @@ -3433,7 +3431,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
// Relocated value must be a pointer type, but gc_relocate does not need to return the
// same pointer type as the relocated pointer. It can be casted to the correct type later
// if it's desired. However, they must have the same address space.
GCRelocateOperands Operands(&CI);
GCRelocateOperands Operands(CI);
Assert(Operands.getDerivedPtr()->getType()->isPointerTy(),
"gc.relocate: relocated value must be a gc pointer", &CI);

Expand Down
4 changes: 2 additions & 2 deletions test/CodeGen/WinEH/cppeh-prepared-catch.ll
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ entry:
%.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?f@@YAXXZ" to i8*), i8* %1, i32 1)
%2 = bitcast i8* %.i8 to double*
%3 = bitcast double* %2 to i8*
invoke void (...) @llvm.donothing()
invoke void () @llvm.donothing()
to label %done unwind label %lpad

done:
Expand Down Expand Up @@ -201,7 +201,7 @@ declare void @llvm.frameescape(...) #3
; Function Attrs: nounwind readnone
declare i8* @llvm.framerecover(i8*, i8*, i32) #2

declare void @llvm.donothing(...)
declare void @llvm.donothing()

attributes #0 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" "wineh-parent"="?f@@YAXXZ" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
Expand Down

0 comments on commit f84a650

Please sign in to comment.