diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index 66b6bb060185f2077c9e1080095971e2af139633..c95018d17725c9cb542532637f9c458b2fdf1d39 100644 (file)
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
/// personality function.
const Value *PersonalityFn;
+ /// \brief Whether we've seen a call to @llvm.frameallocate in this function
+ /// already.
+ bool SawFrameAllocate;
+
public:
explicit Verifier(raw_ostream &OS = dbgs())
- : VerifierSupport(OS), Context(nullptr), PersonalityFn(nullptr) {}
+ : VerifierSupport(OS), Context(nullptr), PersonalityFn(nullptr),
+ SawFrameAllocate(false) {}
bool verify(const Function &F) {
M = F.getParent();
visit(const_cast<Function &>(F));
InstsInThisBlock.clear();
PersonalityFn = nullptr;
+ SawFrameAllocate = false;
return !Broken;
}
}
// Check these last, so we diagnose problems in operands first.
- Assert1(!isa<MDNodeFwdDecl>(MD), "Expected no forward declarations!", &MD);
+ Assert1(!MD.isTemporary(), "Expected no forward declarations!", &MD);
Assert1(MD.isResolved(), "All nodes should be resolved!", &MD);
}
// Check the entry node
const BasicBlock *Entry = &F.getEntryBlock();
- Assert1(pred_begin(Entry) == pred_end(Entry),
+ Assert1(pred_empty(Entry),
"Entry block to function must not have predecessors!", Entry);
// The address of the entry block cannot be taken, unless it is dead.
return VerifyIntrinsicType(ThisArgType->getVectorElementType(),
Infos, ArgTys);
}
+ case IITDescriptor::PtrToArgument: {
+ if (D.getArgumentNumber() >= ArgTys.size())
+ return true;
+ Type * ReferenceType = ArgTys[D.getArgumentNumber()];
+ PointerType *ThisArgType = dyn_cast<PointerType>(Ty);
+ return (!ThisArgType || ThisArgType->getElementType() != ReferenceType);
+ }
}
llvm_unreachable("unhandled");
}
Assert1(isa<ConstantInt>(CI.getArgOperand(1)),
"llvm.invariant.end parameter #2 must be a constant integer", &CI);
break;
-
+
+ case Intrinsic::frameallocate: {
+ BasicBlock *BB = CI.getParent();
+ Assert1(BB == &BB->getParent()->front(),
+ "llvm.frameallocate used outside of entry block", &CI);
+ Assert1(!SawFrameAllocate,
+ "multiple calls to llvm.frameallocate in one function", &CI);
+ SawFrameAllocate = true;
+ Assert1(isa<ConstantInt>(CI.getArgOperand(0)),
+ "llvm.frameallocate argument must be constant integer size", &CI);
+ break;
+ }
+ case Intrinsic::framerecover: {
+ Value *FnArg = CI.getArgOperand(0)->stripPointerCasts();
+ Function *Fn = dyn_cast<Function>(FnArg);
+ Assert1(Fn && !Fn->isDeclaration(), "llvm.framerecover first "
+ "argument must be function defined in this module", &CI);
+ break;
+ }
+
case Intrinsic::experimental_gc_statepoint: {
Assert1(!CI.doesNotAccessMemory() &&
!CI.onlyReadsMemory(),
"gc.statepoint callee must be of function pointer type",
&CI, Target);
FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType());
- Assert1(!TargetFuncType->isVarArg(),
- "gc.statepoint support for var arg functions not implemented", &CI);
const Value *NumCallArgsV = CI.getArgOperand(1);
Assert1(isa<ConstantInt>(NumCallArgsV),
Assert1(NumCallArgs >= 0,
"gc.statepoint number of arguments to underlying call "
"must be positive", &CI);
- Assert1(NumCallArgs == (int)TargetFuncType->getNumParams(),
- "gc.statepoint mismatch in number of call args", &CI);
+ const int NumParams = (int)TargetFuncType->getNumParams();
+ if (TargetFuncType->isVarArg()) {
+ Assert1(NumCallArgs >= NumParams,
+ "gc.statepoint mismatch in number of vararg call args", &CI);
+
+ // TODO: Remove this limitation
+ Assert1(TargetFuncType->getReturnType()->isVoidTy(),
+ "gc.statepoint doesn't support wrapping non-void "
+ "vararg functions yet", &CI);
+ } else
+ Assert1(NumCallArgs == NumParams,
+ "gc.statepoint mismatch in number of call args", &CI);
const Value *Unused = CI.getArgOperand(2);
Assert1(isa<ConstantInt>(Unused) &&
// Verify that the types of the call parameter arguments match
// the type of the wrapped callee.
- for (int i = 0; i < NumCallArgs; i++) {
+ for (int i = 0; i < NumParams; i++) {
Type *ParamType = TargetFuncType->getParamType(i);
Type *ArgType = CI.getArgOperand(3+i)->getType();
Assert1(ArgType == ParamType,
case Intrinsic::experimental_gc_result_ptr: {
// Are we tied to a statepoint properly?
CallSite StatepointCS(CI.getArgOperand(0));
- const Function *StatepointFn = StatepointCS.getCalledFunction();
+ const Function *StatepointFn =
+ StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr;
Assert2(StatepointFn && StatepointFn->isDeclaration() &&
StatepointFn->getIntrinsicID() == Intrinsic::experimental_gc_statepoint,
- "token must be from a statepoint", &CI, CI.getArgOperand(0));
+ "gc.result operand #1 must be from a statepoint",
+ &CI, CI.getArgOperand(0));
// Assert that result type matches wrapped callee.
const Value *Target = StatepointCS.getArgument(0);
// Are we tied to a statepoint properly?
CallSite StatepointCS(CI.getArgOperand(0));
const Function *StatepointFn =
- StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : NULL;
+ StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr;
Assert2(StatepointFn && StatepointFn->isDeclaration() &&
StatepointFn->getIntrinsicID() == Intrinsic::experimental_gc_statepoint,
- "token must be from a statepoint", &CI, CI.getArgOperand(0));
+ "gc.relocate operand #1 must be from a statepoint",
+ &CI, CI.getArgOperand(0));
// Both the base and derived must be piped through the safepoint
Value* Base = CI.getArgOperand(1);
- Assert1( isa<ConstantInt>(Base), "must be integer offset", &CI);
+ Assert1(isa<ConstantInt>(Base),
+ "gc.relocate operand #2 must be integer offset", &CI);
Value* Derived = CI.getArgOperand(2);
- Assert1( isa<ConstantInt>(Derived), "must be integer offset", &CI);
+ Assert1(isa<ConstantInt>(Derived),
+ "gc.relocate operand #3 must be integer offset", &CI);
const int BaseIndex = cast<ConstantInt>(Base)->getZExtValue();
const int DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue();
// Check the bounds
Assert1(0 <= BaseIndex &&
BaseIndex < (int)StatepointCS.arg_size(),
- "index out of bounds", &CI);
+ "gc.relocate: statepoint base index out of bounds", &CI);
Assert1(0 <= DerivedIndex &&
DerivedIndex < (int)StatepointCS.arg_size(),
- "index out of bounds", &CI);
+ "gc.relocate: statepoint derived index out of bounds", &CI);
+
+ // Check that BaseIndex and DerivedIndex fall within the 'gc parameters'
+ // section of the statepoint's argument
+ const int NumCallArgs =
+ cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue();
+ const int NumDeoptArgs =
+ cast<ConstantInt>(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue();
+ const int GCParamArgsStart = NumCallArgs + NumDeoptArgs + 4;
+ const int GCParamArgsEnd = StatepointCS.arg_size();
+ Assert1(GCParamArgsStart <= BaseIndex &&
+ BaseIndex < GCParamArgsEnd,
+ "gc.relocate: statepoint base index doesn't fall within the "
+ "'gc parameters' section of the statepoint call", &CI);
+ Assert1(GCParamArgsStart <= DerivedIndex &&
+ DerivedIndex < GCParamArgsEnd,
+ "gc.relocate: statepoint derived index doesn't fall within the "
+ "'gc parameters' section of the statepoint call", &CI);
+
// Assert that the result type matches the type of the relocated pointer
GCRelocateOperands Operands(&CI);
Assert1(Operands.derivedPtr()->getType() == CI.getType(),
- "gc.relocate: relocating a pointer shouldn't change it's type",
+ "gc.relocate: relocating a pointer shouldn't change its type",
&CI);
break;
}
return new DebugInfoVerifierLegacyPass(FatalErrors);
}
-PreservedAnalyses VerifierPass::run(Module *M) {
- if (verifyModule(*M, &dbgs()) && FatalErrors)
+PreservedAnalyses VerifierPass::run(Module &M) {
+ if (verifyModule(M, &dbgs()) && FatalErrors)
report_fatal_error("Broken module found, compilation aborted!");
return PreservedAnalyses::all();
}
-PreservedAnalyses VerifierPass::run(Function *F) {
- if (verifyFunction(*F, &dbgs()) && FatalErrors)
+PreservedAnalyses VerifierPass::run(Function &F) {
+ if (verifyFunction(F, &dbgs()) && FatalErrors)
report_fatal_error("Broken function found, compilation aborted!");
return PreservedAnalyses::all();