mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-27 04:18:42 +00:00
[Verifier] Follow on to 240836
Address one missed review comment and do the rename I left out of that patch to make it reviewable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240843 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
1 parent
9a61a42713
commit
982139fde2
2 files changed
+80
-82
No files matched your search
@@ -197,7 +197,7 @@ public:
|
||||
CALLSITE_DELEGATE_GETTER(getNumArgOperands());
|
||||
}
|
||||
|
||||
Value *getArgOperand(unsigned i) const {
|
||||
ValTy *getArgOperand(unsigned i) const {
|
||||
CALLSITE_DELEGATE_GETTER(getArgOperand(i));
|
||||
}
|
||||
|
||||
|
||||
+79
-81
@@ -102,10 +102,8 @@ private:
|
||||
OS << '\n';
|
||||
}
|
||||
}
|
||||
void Write(const CallSite *CS) {
|
||||
if (!CS)
|
||||
return;
|
||||
Write(CS->getInstruction());
|
||||
void Write(ImmutableCallSite CS) {
|
||||
Write(CS.getInstruction());
|
||||
}
|
||||
|
||||
void Write(const Metadata *MD) {
|
||||
@@ -3144,8 +3142,8 @@ Verifier::VerifyIntrinsicIsVarArg(bool isVarArg,
|
||||
|
||||
/// visitIntrinsicFunction - Allow intrinsics to be verified in different ways.
|
||||
///
|
||||
void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallSite CI) {
|
||||
Function *IF = CI.getCalledFunction();
|
||||
void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallSite CS) {
|
||||
Function *IF = CS.getCalledFunction();
|
||||
Assert(IF->isDeclaration(), "Intrinsic functions should never be defined!",
|
||||
IF);
|
||||
|
||||
@@ -3189,41 +3187,41 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallSite CI) {
|
||||
|
||||
// If the intrinsic takes MDNode arguments, verify that they are either global
|
||||
// or are local to *this* function.
|
||||
for (unsigned i = 0, e = CI.getNumArgOperands(); i != e; ++i)
|
||||
if (auto *MD = dyn_cast<MetadataAsValue>(CI.getArgOperand(i)))
|
||||
visitMetadataAsValue(*MD, CI.getParent()->getParent());
|
||||
for (unsigned i = 0, e = CS.getNumArgOperands(); i != e; ++i)
|
||||
if (auto *MD = dyn_cast<MetadataAsValue>(CS.getArgOperand(i)))
|
||||
visitMetadataAsValue(*MD, CS.getParent()->getParent());
|
||||
|
||||
switch (ID) {
|
||||
default:
|
||||
break;
|
||||
case Intrinsic::ctlz: // llvm.ctlz
|
||||
case Intrinsic::cttz: // llvm.cttz
|
||||
Assert(isa<ConstantInt>(CI.getArgOperand(1)),
|
||||
Assert(isa<ConstantInt>(CS.getArgOperand(1)),
|
||||
"is_zero_undef argument of bit counting intrinsics must be a "
|
||||
"constant int",
|
||||
&CI);
|
||||
CS);
|
||||
break;
|
||||
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.getInstruction()));
|
||||
Assert(isa<MetadataAsValue>(CS.getArgOperand(0)),
|
||||
"invalid llvm.dbg.declare intrinsic call 1", CS);
|
||||
visitDbgIntrinsic("declare", cast<DbgDeclareInst>(*CS.getInstruction()));
|
||||
break;
|
||||
case Intrinsic::dbg_value: // llvm.dbg.value
|
||||
visitDbgIntrinsic("value", cast<DbgValueInst>(*CI.getInstruction()));
|
||||
visitDbgIntrinsic("value", cast<DbgValueInst>(*CS.getInstruction()));
|
||||
break;
|
||||
case Intrinsic::memcpy:
|
||||
case Intrinsic::memmove:
|
||||
case Intrinsic::memset: {
|
||||
ConstantInt *AlignCI = dyn_cast<ConstantInt>(CI.getArgOperand(3));
|
||||
ConstantInt *AlignCI = dyn_cast<ConstantInt>(CS.getArgOperand(3));
|
||||
Assert(AlignCI,
|
||||
"alignment argument of memory intrinsics must be a constant int",
|
||||
&CI);
|
||||
CS);
|
||||
const APInt &AlignVal = AlignCI->getValue();
|
||||
Assert(AlignCI->isZero() || AlignVal.isPowerOf2(),
|
||||
"alignment argument of memory intrinsics must be a power of 2", &CI);
|
||||
Assert(isa<ConstantInt>(CI.getArgOperand(4)),
|
||||
"alignment argument of memory intrinsics must be a power of 2", CS);
|
||||
Assert(isa<ConstantInt>(CS.getArgOperand(4)),
|
||||
"isvolatile argument of memory intrinsics must be a constant int",
|
||||
&CI);
|
||||
CS);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::gcroot:
|
||||
@@ -3231,76 +3229,76 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallSite CI) {
|
||||
case Intrinsic::gcread:
|
||||
if (ID == Intrinsic::gcroot) {
|
||||
AllocaInst *AI =
|
||||
dyn_cast<AllocaInst>(CI.getArgOperand(0)->stripPointerCasts());
|
||||
Assert(AI, "llvm.gcroot parameter #1 must be an alloca.", &CI);
|
||||
Assert(isa<Constant>(CI.getArgOperand(1)),
|
||||
"llvm.gcroot parameter #2 must be a constant.", &CI);
|
||||
dyn_cast<AllocaInst>(CS.getArgOperand(0)->stripPointerCasts());
|
||||
Assert(AI, "llvm.gcroot parameter #1 must be an alloca.", CS);
|
||||
Assert(isa<Constant>(CS.getArgOperand(1)),
|
||||
"llvm.gcroot parameter #2 must be a constant.", CS);
|
||||
if (!AI->getAllocatedType()->isPointerTy()) {
|
||||
Assert(!isa<ConstantPointerNull>(CI.getArgOperand(1)),
|
||||
Assert(!isa<ConstantPointerNull>(CS.getArgOperand(1)),
|
||||
"llvm.gcroot parameter #1 must either be a pointer alloca, "
|
||||
"or argument #2 must be a non-null constant.",
|
||||
&CI);
|
||||
CS);
|
||||
}
|
||||
}
|
||||
|
||||
Assert(CI.getParent()->getParent()->hasGC(),
|
||||
"Enclosing function does not use GC.", &CI);
|
||||
Assert(CS.getParent()->getParent()->hasGC(),
|
||||
"Enclosing function does not use GC.", CS);
|
||||
break;
|
||||
case Intrinsic::init_trampoline:
|
||||
Assert(isa<Function>(CI.getArgOperand(1)->stripPointerCasts()),
|
||||
Assert(isa<Function>(CS.getArgOperand(1)->stripPointerCasts()),
|
||||
"llvm.init_trampoline parameter #2 must resolve to a function.",
|
||||
&CI);
|
||||
CS);
|
||||
break;
|
||||
case Intrinsic::prefetch:
|
||||
Assert(isa<ConstantInt>(CI.getArgOperand(1)) &&
|
||||
isa<ConstantInt>(CI.getArgOperand(2)) &&
|
||||
cast<ConstantInt>(CI.getArgOperand(1))->getZExtValue() < 2 &&
|
||||
cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue() < 4,
|
||||
"invalid arguments to llvm.prefetch", &CI);
|
||||
Assert(isa<ConstantInt>(CS.getArgOperand(1)) &&
|
||||
isa<ConstantInt>(CS.getArgOperand(2)) &&
|
||||
cast<ConstantInt>(CS.getArgOperand(1))->getZExtValue() < 2 &&
|
||||
cast<ConstantInt>(CS.getArgOperand(2))->getZExtValue() < 4,
|
||||
"invalid arguments to llvm.prefetch", CS);
|
||||
break;
|
||||
case Intrinsic::stackprotector:
|
||||
Assert(isa<AllocaInst>(CI.getArgOperand(1)->stripPointerCasts()),
|
||||
"llvm.stackprotector parameter #2 must resolve to an alloca.", &CI);
|
||||
Assert(isa<AllocaInst>(CS.getArgOperand(1)->stripPointerCasts()),
|
||||
"llvm.stackprotector parameter #2 must resolve to an alloca.", CS);
|
||||
break;
|
||||
case Intrinsic::lifetime_start:
|
||||
case Intrinsic::lifetime_end:
|
||||
case Intrinsic::invariant_start:
|
||||
Assert(isa<ConstantInt>(CI.getArgOperand(0)),
|
||||
Assert(isa<ConstantInt>(CS.getArgOperand(0)),
|
||||
"size argument of memory use markers must be a constant integer",
|
||||
&CI);
|
||||
CS);
|
||||
break;
|
||||
case Intrinsic::invariant_end:
|
||||
Assert(isa<ConstantInt>(CI.getArgOperand(1)),
|
||||
"llvm.invariant.end parameter #2 must be a constant integer", &CI);
|
||||
Assert(isa<ConstantInt>(CS.getArgOperand(1)),
|
||||
"llvm.invariant.end parameter #2 must be a constant integer", CS);
|
||||
break;
|
||||
|
||||
case Intrinsic::frameescape: {
|
||||
BasicBlock *BB = CI.getParent();
|
||||
BasicBlock *BB = CS.getParent();
|
||||
Assert(BB == &BB->getParent()->front(),
|
||||
"llvm.frameescape used outside of entry block", &CI);
|
||||
"llvm.frameescape used outside of entry block", CS);
|
||||
Assert(!SawFrameEscape,
|
||||
"multiple calls to llvm.frameescape in one function", &CI);
|
||||
for (Value *Arg : CI.args()) {
|
||||
"multiple calls to llvm.frameescape in one function", CS);
|
||||
for (Value *Arg : CS.args()) {
|
||||
if (isa<ConstantPointerNull>(Arg))
|
||||
continue; // Null values are allowed as placeholders.
|
||||
auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts());
|
||||
Assert(AI && AI->isStaticAlloca(),
|
||||
"llvm.frameescape only accepts static allocas", &CI);
|
||||
"llvm.frameescape only accepts static allocas", CS);
|
||||
}
|
||||
FrameEscapeInfo[BB->getParent()].first = CI.getNumArgOperands();
|
||||
FrameEscapeInfo[BB->getParent()].first = CS.getNumArgOperands();
|
||||
SawFrameEscape = true;
|
||||
break;
|
||||
}
|
||||
case Intrinsic::framerecover: {
|
||||
Value *FnArg = CI.getArgOperand(0)->stripPointerCasts();
|
||||
Value *FnArg = CS.getArgOperand(0)->stripPointerCasts();
|
||||
Function *Fn = dyn_cast<Function>(FnArg);
|
||||
Assert(Fn && !Fn->isDeclaration(),
|
||||
"llvm.framerecover first "
|
||||
"argument must be function defined in this module",
|
||||
&CI);
|
||||
auto *IdxArg = dyn_cast<ConstantInt>(CI.getArgOperand(2));
|
||||
CS);
|
||||
auto *IdxArg = dyn_cast<ConstantInt>(CS.getArgOperand(2));
|
||||
Assert(IdxArg, "idx argument of llvm.framerecover must be a constant int",
|
||||
&CI);
|
||||
CS);
|
||||
auto &Entry = FrameEscapeInfo[Fn];
|
||||
Entry.second = unsigned(
|
||||
std::max(uint64_t(Entry.second), IdxArg->getLimitedValue(~0U) + 1));
|
||||
@@ -3308,49 +3306,49 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallSite CI) {
|
||||
}
|
||||
|
||||
case Intrinsic::experimental_gc_statepoint:
|
||||
Assert(!CI.isInlineAsm(),
|
||||
"gc.statepoint support for inline assembly unimplemented", &CI);
|
||||
Assert(CI.getParent()->getParent()->hasGC(),
|
||||
"Enclosing function does not use GC.", &CI);
|
||||
Assert(!CS.isInlineAsm(),
|
||||
"gc.statepoint support for inline assembly unimplemented", CS);
|
||||
Assert(CS.getParent()->getParent()->hasGC(),
|
||||
"Enclosing function does not use GC.", CS);
|
||||
|
||||
VerifyStatepoint(ImmutableCallSite(CI));
|
||||
VerifyStatepoint(CS);
|
||||
break;
|
||||
case Intrinsic::experimental_gc_result_int:
|
||||
case Intrinsic::experimental_gc_result_float:
|
||||
case Intrinsic::experimental_gc_result_ptr:
|
||||
case Intrinsic::experimental_gc_result: {
|
||||
Assert(CI.getParent()->getParent()->hasGC(),
|
||||
"Enclosing function does not use GC.", &CI);
|
||||
Assert(CS.getParent()->getParent()->hasGC(),
|
||||
"Enclosing function does not use GC.", CS);
|
||||
// Are we tied to a statepoint properly?
|
||||
CallSite StatepointCS(CI.getArgOperand(0));
|
||||
CallSite StatepointCS(CS.getArgOperand(0));
|
||||
const Function *StatepointFn =
|
||||
StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr;
|
||||
Assert(StatepointFn && StatepointFn->isDeclaration() &&
|
||||
StatepointFn->getIntrinsicID() ==
|
||||
Intrinsic::experimental_gc_statepoint,
|
||||
"gc.result operand #1 must be from a statepoint", &CI,
|
||||
CI.getArgOperand(0));
|
||||
"gc.result operand #1 must be from a statepoint", CS,
|
||||
CS.getArgOperand(0));
|
||||
|
||||
// Assert that result type matches wrapped callee.
|
||||
const Value *Target = StatepointCS.getArgument(2);
|
||||
const PointerType *PT = cast<PointerType>(Target->getType());
|
||||
const FunctionType *TargetFuncType =
|
||||
cast<FunctionType>(PT->getElementType());
|
||||
Assert(CI.getType() == TargetFuncType->getReturnType(),
|
||||
"gc.result result type does not match wrapped callee", &CI);
|
||||
Assert(CS.getType() == TargetFuncType->getReturnType(),
|
||||
"gc.result result type does not match wrapped callee", CS);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::experimental_gc_relocate: {
|
||||
Assert(CI.getNumArgOperands() == 3, "wrong number of arguments", &CI);
|
||||
Assert(CS.getNumArgOperands() == 3, "wrong number of arguments", CS);
|
||||
|
||||
// Check that this relocate is correctly tied to the statepoint
|
||||
|
||||
// This is case for relocate on the unwinding path of an invoke statepoint
|
||||
if (ExtractValueInst *ExtractValue =
|
||||
dyn_cast<ExtractValueInst>(CI.getArgOperand(0))) {
|
||||
dyn_cast<ExtractValueInst>(CS.getArgOperand(0))) {
|
||||
Assert(isa<LandingPadInst>(ExtractValue->getAggregateOperand()),
|
||||
"gc relocate on unwind path incorrectly linked to the statepoint",
|
||||
&CI);
|
||||
CS);
|
||||
|
||||
const BasicBlock *InvokeBB =
|
||||
ExtractValue->getParent()->getUniquePredecessor();
|
||||
@@ -3368,32 +3366,32 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallSite CI) {
|
||||
// In all other cases relocate should be tied to the statepoint directly.
|
||||
// This covers relocates on a normal return path of invoke statepoint and
|
||||
// relocates of a call statepoint
|
||||
auto Token = CI.getArgOperand(0);
|
||||
auto Token = CS.getArgOperand(0);
|
||||
Assert(isa<Instruction>(Token) && isStatepoint(cast<Instruction>(Token)),
|
||||
"gc relocate is incorrectly tied to the statepoint", &CI, Token);
|
||||
"gc relocate is incorrectly tied to the statepoint", CS, Token);
|
||||
}
|
||||
|
||||
// Verify rest of the relocate arguments
|
||||
|
||||
GCRelocateOperands Ops(CI);
|
||||
GCRelocateOperands Ops(CS);
|
||||
ImmutableCallSite StatepointCS(Ops.getStatepoint());
|
||||
|
||||
// Both the base and derived must be piped through the safepoint
|
||||
Value* Base = CI.getArgOperand(1);
|
||||
Value* Base = CS.getArgOperand(1);
|
||||
Assert(isa<ConstantInt>(Base),
|
||||
"gc.relocate operand #2 must be integer offset", &CI);
|
||||
"gc.relocate operand #2 must be integer offset", CS);
|
||||
|
||||
Value* Derived = CI.getArgOperand(2);
|
||||
Value* Derived = CS.getArgOperand(2);
|
||||
Assert(isa<ConstantInt>(Derived),
|
||||
"gc.relocate operand #3 must be integer offset", &CI);
|
||||
"gc.relocate operand #3 must be integer offset", CS);
|
||||
|
||||
const int BaseIndex = cast<ConstantInt>(Base)->getZExtValue();
|
||||
const int DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue();
|
||||
// Check the bounds
|
||||
Assert(0 <= BaseIndex && BaseIndex < (int)StatepointCS.arg_size(),
|
||||
"gc.relocate: statepoint base index out of bounds", &CI);
|
||||
"gc.relocate: statepoint base index out of bounds", CS);
|
||||
Assert(0 <= DerivedIndex && DerivedIndex < (int)StatepointCS.arg_size(),
|
||||
"gc.relocate: statepoint derived index out of bounds", &CI);
|
||||
"gc.relocate: statepoint derived index out of bounds", CS);
|
||||
|
||||
// Check that BaseIndex and DerivedIndex fall within the 'gc parameters'
|
||||
// section of the statepoint's argument
|
||||
@@ -3422,24 +3420,24 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallSite CI) {
|
||||
Assert(GCParamArgsStart <= BaseIndex && BaseIndex < GCParamArgsEnd,
|
||||
"gc.relocate: statepoint base index doesn't fall within the "
|
||||
"'gc parameters' section of the statepoint call",
|
||||
&CI);
|
||||
CS);
|
||||
Assert(GCParamArgsStart <= DerivedIndex && DerivedIndex < GCParamArgsEnd,
|
||||
"gc.relocate: statepoint derived index doesn't fall within the "
|
||||
"'gc parameters' section of the statepoint call",
|
||||
&CI);
|
||||
CS);
|
||||
|
||||
// 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(CS);
|
||||
Assert(Operands.getDerivedPtr()->getType()->isPointerTy(),
|
||||
"gc.relocate: relocated value must be a gc pointer", &CI);
|
||||
"gc.relocate: relocated value must be a gc pointer", CS);
|
||||
|
||||
// gc_relocate return type must be a pointer type, and is verified earlier in
|
||||
// VerifyIntrinsicType().
|
||||
Assert(cast<PointerType>(CI.getType())->getAddressSpace() ==
|
||||
Assert(cast<PointerType>(CS.getType())->getAddressSpace() ==
|
||||
cast<PointerType>(Operands.getDerivedPtr()->getType())->getAddressSpace(),
|
||||
"gc.relocate: relocating a pointer shouldn't change its address space", &CI);
|
||||
"gc.relocate: relocating a pointer shouldn't change its address space", CS);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user