Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 8 additions & 189 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,6 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
void visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call);
void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI);
void visitVPIntrinsic(VPIntrinsic &VPI);
void visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII);
void visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI);
void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);
void visitAtomicRMWInst(AtomicRMWInst &RMWI);
Expand Down Expand Up @@ -636,15 +635,12 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
void verifyFrameRecoverIndices();
void verifySiblingFuncletUnwinds();

void verifyFragmentExpression(const DbgVariableIntrinsic &I);
void verifyFragmentExpression(const DbgVariableRecord &I);
template <typename ValueOrMetadata>
void verifyFragmentExpression(const DIVariable &V,
DIExpression::FragmentInfo Fragment,
ValueOrMetadata *Desc);
void verifyFnArgs(const DbgVariableIntrinsic &I);
void verifyFnArgs(const DbgVariableRecord &DVR);
void verifyNotEntryValue(const DbgVariableIntrinsic &I);
void verifyNotEntryValue(const DbgVariableRecord &I);

/// Module-level debug info verification...
Expand Down Expand Up @@ -5494,11 +5490,6 @@ void Verifier::visitInstruction(Instruction &I) {
visitMDNode(*N, AreDebugLocsAllowed::Yes);
}

if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) {
verifyFragmentExpression(*DII);
verifyNotEntryValue(*DII);
}

SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
I.getAllMetadata(MDs);
for (auto Attachment : MDs) {
Expand Down Expand Up @@ -5703,18 +5694,14 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
visitConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(Call));
break;
case Intrinsic::dbg_declare: // llvm.dbg.declare
Check(isa<MetadataAsValue>(Call.getArgOperand(0)),
"invalid llvm.dbg.declare intrinsic call 1", Call);
visitDbgIntrinsic("declare", cast<DbgVariableIntrinsic>(Call));
break;
case Intrinsic::dbg_value: // llvm.dbg.value
visitDbgIntrinsic("value", cast<DbgVariableIntrinsic>(Call));
break;
case Intrinsic::dbg_assign: // llvm.dbg.assign
visitDbgIntrinsic("assign", cast<DbgVariableIntrinsic>(Call));
break;
case Intrinsic::dbg_label: // llvm.dbg.label
visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(Call));
case Intrinsic::dbg_value: // llvm.dbg.value
case Intrinsic::dbg_assign: // llvm.dbg.assign
case Intrinsic::dbg_label: // llvm.dbg.label
// We no longer interpret debug intrinsics (the old variable-location
// design). They're meaningless as far as LLVM is concerned we could make
// it an error for them to appear, but it's possible we'll have users
// converting back to intrinsics for the forseeable future (such as DXIL),
// so tolerate their existance.
break;
case Intrinsic::memcpy:
case Intrinsic::memcpy_inline:
Expand Down Expand Up @@ -7123,123 +7110,6 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) {
}
}

void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) {
auto *MD = DII.getRawLocation();
CheckDI(isa<ValueAsMetadata>(MD) || isa<DIArgList>(MD) ||
(isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()),
"invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD);
CheckDI(isa<DILocalVariable>(DII.getRawVariable()),
"invalid llvm.dbg." + Kind + " intrinsic variable", &DII,
DII.getRawVariable());
CheckDI(isa<DIExpression>(DII.getRawExpression()),
"invalid llvm.dbg." + Kind + " intrinsic expression", &DII,
DII.getRawExpression());

if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&DII)) {
CheckDI(isa<DIAssignID>(DAI->getRawAssignID()),
"invalid llvm.dbg.assign intrinsic DIAssignID", &DII,
DAI->getRawAssignID());
const auto *RawAddr = DAI->getRawAddress();
CheckDI(
isa<ValueAsMetadata>(RawAddr) ||
(isa<MDNode>(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands()),
"invalid llvm.dbg.assign intrinsic address", &DII,
DAI->getRawAddress());
CheckDI(isa<DIExpression>(DAI->getRawAddressExpression()),
"invalid llvm.dbg.assign intrinsic address expression", &DII,
DAI->getRawAddressExpression());
// All of the linked instructions should be in the same function as DII.
for (Instruction *I : at::getAssignmentInsts(DAI))
CheckDI(DAI->getFunction() == I->getFunction(),
"inst not in same function as dbg.assign", I, DAI);
}

// Ignore broken !dbg attachments; they're checked elsewhere.
if (MDNode *N = DII.getDebugLoc().getAsMDNode())
if (!isa<DILocation>(N))
return;

BasicBlock *BB = DII.getParent();
Function *F = BB ? BB->getParent() : nullptr;

// The scopes for variables and !dbg attachments must agree.
DILocalVariable *Var = DII.getVariable();
DILocation *Loc = DII.getDebugLoc();
CheckDI(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",
&DII, BB, F);

DISubprogram *VarSP = getSubprogram(Var->getRawScope());
DISubprogram *LocSP = getSubprogram(Loc->getRawScope());
if (!VarSP || !LocSP)
return; // Broken scope chains are checked elsewhere.

CheckDI(VarSP == LocSP,
"mismatched subprogram between llvm.dbg." + Kind +
" variable and !dbg attachment",
&DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc,
Loc->getScope()->getSubprogram());

// This check is redundant with one in visitLocalVariable().
CheckDI(isType(Var->getRawType()), "invalid type ref", Var,
Var->getRawType());
verifyFnArgs(DII);
}

void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) {
CheckDI(isa<DILabel>(DLI.getRawLabel()),
"invalid llvm.dbg." + Kind + " intrinsic variable", &DLI,
DLI.getRawLabel());

// Ignore broken !dbg attachments; they're checked elsewhere.
if (MDNode *N = DLI.getDebugLoc().getAsMDNode())
if (!isa<DILocation>(N))
return;

BasicBlock *BB = DLI.getParent();
Function *F = BB ? BB->getParent() : nullptr;

// The scopes for variables and !dbg attachments must agree.
DILabel *Label = DLI.getLabel();
DILocation *Loc = DLI.getDebugLoc();
Check(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment", &DLI,
BB, F);

DISubprogram *LabelSP = getSubprogram(Label->getRawScope());
DISubprogram *LocSP = getSubprogram(Loc->getRawScope());
if (!LabelSP || !LocSP)
return;

CheckDI(LabelSP == LocSP,
"mismatched subprogram between llvm.dbg." + Kind +
" label and !dbg attachment",
&DLI, BB, F, Label, Label->getScope()->getSubprogram(), Loc,
Loc->getScope()->getSubprogram());
}

void Verifier::verifyFragmentExpression(const DbgVariableIntrinsic &I) {
DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable());
DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression());

// We don't know whether this intrinsic verified correctly.
if (!V || !E || !E->isValid())
return;

// Nothing to do if this isn't a DW_OP_LLVM_fragment expression.
auto Fragment = E->getFragmentInfo();
if (!Fragment)
return;

// The frontend helps out GDB by emitting the members of local anonymous
// unions as artificial local variables with shared storage. When SROA splits
// the storage for artificial local variables that are smaller than the entire
// union, the overhang piece will be outside of the allotted space for the
// variable and this check fails.
// FIXME: Remove this check as soon as clang stops doing this; it hides bugs.
if (V->isArtificial())
return;

verifyFragmentExpression(*V, *Fragment, &I);
}
void Verifier::verifyFragmentExpression(const DbgVariableRecord &DVR) {
DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(DVR.getRawVariable());
DIExpression *E = dyn_cast_or_null<DIExpression>(DVR.getRawExpression());
Expand Down Expand Up @@ -7282,34 +7152,6 @@ void Verifier::verifyFragmentExpression(const DIVariable &V,
CheckDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V);
}

void Verifier::verifyFnArgs(const DbgVariableIntrinsic &I) {
// This function does not take the scope of noninlined function arguments into
// account. Don't run it if current function is nodebug, because it may
// contain inlined debug intrinsics.
if (!HasDebugInfo)
return;

// For performance reasons only check non-inlined ones.
if (I.getDebugLoc()->getInlinedAt())
return;

DILocalVariable *Var = I.getVariable();
CheckDI(Var, "dbg intrinsic without variable");

unsigned ArgNo = Var->getArg();
if (!ArgNo)
return;

// Verify there are no duplicate function argument debug info entries.
// These will cause hard-to-debug assertions in the DWARF backend.
if (DebugFnArgs.size() < ArgNo)
DebugFnArgs.resize(ArgNo, nullptr);

auto *Prev = DebugFnArgs[ArgNo - 1];
DebugFnArgs[ArgNo - 1] = Var;
CheckDI(!Prev || (Prev == Var), "conflicting debug info for argument", &I,
Prev, Var);
}
void Verifier::verifyFnArgs(const DbgVariableRecord &DVR) {
// This function does not take the scope of noninlined function arguments into
// account. Don't run it if current function is nodebug, because it may
Expand Down Expand Up @@ -7339,29 +7181,6 @@ void Verifier::verifyFnArgs(const DbgVariableRecord &DVR) {
Prev, Var);
}

void Verifier::verifyNotEntryValue(const DbgVariableIntrinsic &I) {
DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression());

// We don't know whether this intrinsic verified correctly.
if (!E || !E->isValid())
return;

if (isa<ValueAsMetadata>(I.getRawLocation())) {
Value *VarValue = I.getVariableLocationOp(0);
if (isa<UndefValue>(VarValue) || isa<PoisonValue>(VarValue))
return;
// We allow EntryValues for swift async arguments, as they have an
// ABI-guarantee to be turned into a specific register.
if (auto *ArgLoc = dyn_cast_or_null<Argument>(VarValue);
ArgLoc && ArgLoc->hasAttribute(Attribute::SwiftAsync))
return;
}

CheckDI(!E->isEntryValue(),
"Entry values are only allowed in MIR unless they target a "
"swiftasync Argument",
&I);
}
void Verifier::verifyNotEntryValue(const DbgVariableRecord &DVR) {
DIExpression *E = dyn_cast_or_null<DIExpression>(DVR.getRawExpression());

Expand Down
Loading