Skip to content

[irgen] Add support to IRGenDebugInfo for emitting an llvm.dbg.addr instead of llvm.dbg.declare. #41379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
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
123 changes: 80 additions & 43 deletions lib/IRGen/IRGenDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,13 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
Optional<SILLocation> VarLoc,
SILDebugVariable VarInfo,
IndirectionKind = DirectValue,
ArtificialKind = RealValue);
ArtificialKind = RealValue,
AddrDbgInstrKind = AddrDbgInstrKind::DbgDeclare);
void emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
llvm::DILocalVariable *Var, llvm::DIExpression *Expr,
unsigned Line, unsigned Col, llvm::DILocalScope *Scope,
const SILDebugScope *DS, bool InCoroContext);
const SILDebugScope *DS, bool InCoroContext,
AddrDbgInstrKind = AddrDbgInstrKind::DbgDeclare);

void emitGlobalVariableDeclaration(llvm::GlobalVariable *Storage,
StringRef Name, StringRef LinkageName,
Expand Down Expand Up @@ -2486,7 +2488,7 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo DbgTy,
const SILDebugScope *DS, Optional<SILLocation> DbgInstLoc,
SILDebugVariable VarInfo, IndirectionKind Indirection,
ArtificialKind Artificial) {
ArtificialKind Artificial, AddrDbgInstrKind AddrDInstrKind) {
assert(DS && "variable has no scope");

if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
Expand Down Expand Up @@ -2620,7 +2622,8 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
if (DIExpr)
emitDbgIntrinsic(
Builder, Piece, Var, DIExpr, DInstLine, DInstLoc.column, Scope, DS,
Indirection == CoroDirectValue || Indirection == CoroIndirectValue);
Indirection == CoroDirectValue || Indirection == CoroIndirectValue,
AddrDInstrKind);
}

// Emit locationless intrinsic for variables that were optimized away.
Expand All @@ -2629,14 +2632,16 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
emitDbgIntrinsic(Builder, llvm::ConstantInt::get(IGM.Int64Ty, 0), Var,
DIExpr, DInstLine, DInstLoc.column, Scope, DS,
Indirection == CoroDirectValue ||
Indirection == CoroIndirectValue);
Indirection == CoroIndirectValue,
AddrDInstrKind);
}
}

void IRGenDebugInfoImpl::emitDbgIntrinsic(
IRBuilder &Builder, llvm::Value *Storage, llvm::DILocalVariable *Var,
llvm::DIExpression *Expr, unsigned Line, unsigned Col,
llvm::DILocalScope *Scope, const SILDebugScope *DS, bool InCoroContext) {
llvm::DILocalScope *Scope, const SILDebugScope *DS, bool InCoroContext,
AddrDbgInstrKind AddrDInstKind) {
// Set the location/scope of the intrinsic.
auto *InlinedAt = createInlinedAt(DS);
auto DL =
Expand All @@ -2650,12 +2655,11 @@ void IRGenDebugInfoImpl::emitDbgIntrinsic(

// Fragment DIExpression cannot cover the whole variable
// or going out-of-bound.
if (auto Fragment = Expr->getFragmentInfo())
if (auto Fragment = Expr->getFragmentInfo()) {
if (auto VarSize = Var->getSizeInBits()) {
unsigned FragSize = Fragment->SizeInBits;
unsigned FragOffset = Fragment->OffsetInBits;
if (FragOffset + FragSize > *VarSize ||
FragSize == *VarSize) {
if (FragOffset + FragSize > *VarSize || FragSize == *VarSize) {
// Drop the fragment part
assert(Expr->isValid());
// Since this expression is valid, DW_OP_LLVM_fragment
Expand All @@ -2664,49 +2668,78 @@ void IRGenDebugInfoImpl::emitDbgIntrinsic(
Expr = DBuilder.createExpression(OrigElements.drop_back(3));
}
}
}

struct DbgInserter {
llvm::DIBuilder &builder;
AddrDbgInstrKind forceDbgDeclare;

llvm::Instruction *insert(llvm::Value *Addr, llvm::DILocalVariable *VarInfo,
llvm::DIExpression *Expr,
const llvm::DILocation *DL,
llvm::Instruction *InsertBefore) {
if (forceDbgDeclare == AddrDbgInstrKind::DbgDeclare)
return builder.insertDeclare(Addr, VarInfo, Expr, DL, InsertBefore);
return builder.insertDbgAddrIntrinsic(Addr, VarInfo, Expr, DL,
InsertBefore);
}

llvm::Instruction *insert(llvm::Value *Addr, llvm::DILocalVariable *VarInfo,
llvm::DIExpression *Expr,
const llvm::DILocation *DL,
llvm::BasicBlock *Block) {
if (forceDbgDeclare == AddrDbgInstrKind::DbgDeclare)
return builder.insertDeclare(Addr, VarInfo, Expr, DL, Block);
return builder.insertDbgAddrIntrinsic(Addr, VarInfo, Expr, DL, Block);
}
};
DbgInserter inserter{DBuilder, AddrDInstKind};

// A dbg.declare is only meaningful if there is a single alloca for
// the variable that is live throughout the function.
// If we have a single alloca, just insert the debug in
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Storage)) {
auto *ParentBB = Alloca->getParent();
auto InsertBefore = std::next(Alloca->getIterator());
if (InsertBefore != ParentBB->end())
DBuilder.insertDeclare(Alloca, Var, Expr, DL, &*InsertBefore);
inserter.insert(Alloca, Var, Expr, DL, &*InsertBefore);
else
DBuilder.insertDeclare(Alloca, Var, Expr, DL, ParentBB);
} else if ((isa<llvm::IntrinsicInst>(Storage) &&
cast<llvm::IntrinsicInst>(Storage)->getIntrinsicID() ==
llvm::Intrinsic::coro_alloca_get)) {
// FIXME: The live range of a coroutine alloca within the function may be
// limited, so using a dbg.addr instead of a dbg.declare would be more
// appropriate.
DBuilder.insertDeclare(Storage, Var, Expr, DL, BB);
} else if (InCoroContext) {
inserter.insert(Alloca, Var, Expr, DL, ParentBB);
return;
}

if ((isa<llvm::IntrinsicInst>(Storage) &&
cast<llvm::IntrinsicInst>(Storage)->getIntrinsicID() ==
llvm::Intrinsic::coro_alloca_get)) {
inserter.insert(Storage, Var, Expr, DL, BB);
return;
}

if (InCoroContext) {
// Function arguments in async functions are emitted without a shadow copy
// (that would interfer with coroutine splitting) but with a dbg.declare to
// give CoroSplit.cpp license to emit a shadow copy for them pointing inside
// the Swift Context argument that is valid throughout the function.
auto &EntryBlock = BB->getParent()->getEntryBlock();
if (auto *InsertBefore = &*EntryBlock.getFirstInsertionPt())
DBuilder.insertDeclare(Storage, Var, Expr, DL, InsertBefore);
else
DBuilder.insertDeclare(Storage, Var, Expr, DL, &EntryBlock);
} else {
// Insert a dbg.value at the current insertion point.
if (isa<llvm::Argument>(Storage) && !Var->getArg() &&
BB->getFirstNonPHIOrDbg())
// SelectionDAGISel only generates debug info for a dbg.value
// that is associated with a llvm::Argument if either its !DIVariable
// is marked as argument or there is no non-debug intrinsic instruction
// before it. So In the case of associating a llvm::Argument with a
// non-argument debug variable -- usually via a !DIExpression -- we
// need to make sure that dbg.value is before any non-phi / no-dbg
// instruction.
DBuilder.insertDbgValueIntrinsic(Storage, Var, Expr, DL,
BB->getFirstNonPHIOrDbg());
inserter.insert(Storage, Var, Expr, DL, InsertBefore);
else
DBuilder.insertDbgValueIntrinsic(Storage, Var, Expr, DL, BB);
inserter.insert(Storage, Var, Expr, DL, &EntryBlock);
return;
}

// Insert a dbg.value at the current insertion point.
if (isa<llvm::Argument>(Storage) && !Var->getArg() &&
BB->getFirstNonPHIOrDbg())
// SelectionDAGISel only generates debug info for a dbg.value
// that is associated with a llvm::Argument if either its !DIVariable
// is marked as argument or there is no non-debug intrinsic instruction
// before it. So In the case of associating a llvm::Argument with a
// non-argument debug variable -- usually via a !DIExpression -- we
// need to make sure that dbg.value is before any non-phi / no-dbg
// instruction.
DBuilder.insertDbgValueIntrinsic(Storage, Var, Expr, DL,
BB->getFirstNonPHIOrDbg());
else
DBuilder.insertDbgValueIntrinsic(Storage, Var, Expr, DL, BB);
}

void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
Expand Down Expand Up @@ -2875,20 +2908,24 @@ void IRGenDebugInfo::emitArtificialFunction(IRBuilder &Builder,

void IRGenDebugInfo::emitVariableDeclaration(
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo Ty,
const SILDebugScope *DS, Optional<SILLocation> VarLoc, SILDebugVariable VarInfo,
IndirectionKind Indirection, ArtificialKind Artificial) {
const SILDebugScope *DS, Optional<SILLocation> VarLoc,
SILDebugVariable VarInfo, IndirectionKind Indirection,
ArtificialKind Artificial, AddrDbgInstrKind AddrDInstKind) {
static_cast<IRGenDebugInfoImpl *>(this)->emitVariableDeclaration(
Builder, Storage, Ty, DS, VarLoc, VarInfo, Indirection, Artificial);
Builder, Storage, Ty, DS, VarLoc, VarInfo, Indirection, Artificial,
AddrDInstKind);
}

void IRGenDebugInfo::emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
llvm::DILocalVariable *Var,
llvm::DIExpression *Expr, unsigned Line,
unsigned Col, llvm::DILocalScope *Scope,
const SILDebugScope *DS,
bool InCoroContext) {
bool InCoroContext,
AddrDbgInstrKind AddrDInstKind) {
static_cast<IRGenDebugInfoImpl *>(this)->emitDbgIntrinsic(
Builder, Storage, Var, Expr, Line, Col, Scope, DS, InCoroContext);
Builder, Storage, Var, Expr, Line, Col, Scope, DS, InCoroContext,
AddrDInstKind);
}

void IRGenDebugInfo::emitGlobalVariableDeclaration(
Expand Down
23 changes: 19 additions & 4 deletions lib/IRGen/IRGenDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ enum IndirectionKind {
};
enum ArtificialKind : bool { RealValue = false, ArtificialValue = true };

/// Used to signal to emitDbgIntrinsic that we actually want to emit dbg.declare
/// instead of dbg.addr. By default, we now emit llvm.dbg.addr instead of
/// llvm.dbg.declare for normal variables. This is not true for metadata which
/// truly are function wide and should be llvm.dbg.declare.
enum class AddrDbgInstrKind : bool {
DbgDeclare,
DbgAddr,
};

/// Helper object that keeps track of the current CompileUnit, File,
/// LexicalScope, and knows how to translate a \c SILLocation into an
/// \c llvm::DebugLoc.
Expand Down Expand Up @@ -144,13 +153,19 @@ class IRGenDebugInfo {
Optional<SILLocation> VarLoc,
SILDebugVariable VarInfo,
IndirectionKind Indirection = DirectValue,
ArtificialKind Artificial = RealValue);

/// Emit a dbg.declare or dbg.value intrinsic, depending on Storage.
ArtificialKind Artificial = RealValue,
AddrDbgInstrKind = AddrDbgInstrKind::DbgDeclare);

/// Emit a dbg.addr or dbg.value intrinsic, depending on Storage. If \p
/// ForceDbgDeclare is set to Yes, then instead of emitting a dbg.addr, we
/// will insert a dbg.declare. Please only use that if you know that the given
/// value can never be moved and have its lifetime ended early (e.x.: type
/// metadata).
void emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
llvm::DILocalVariable *Var, llvm::DIExpression *Expr,
unsigned Line, unsigned Col, llvm::DILocalScope *Scope,
const SILDebugScope *DS, bool InCoroContext = false);
const SILDebugScope *DS, bool InCoroContext = false,
AddrDbgInstrKind = AddrDbgInstrKind::DbgDeclare);

enum { NotHeapAllocated = false };

Expand Down
18 changes: 13 additions & 5 deletions lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,8 @@ class IRGenSILFunction :
SILType SILTy, const SILDebugScope *DS,
SILLocation VarLoc,
SILDebugVariable VarInfo,
IndirectionKind Indirection) {
IndirectionKind Indirection,
AddrDbgInstrKind DbgInstrKind = AddrDbgInstrKind::DbgDeclare) {
// TODO: fix demangling for C++ types (SR-13223).
if (swift::TypeBase *ty = SILTy.getASTType().getPointer()) {
if (MetatypeType *metaTy = dyn_cast<MetatypeType>(ty))
Expand All @@ -1072,10 +1073,12 @@ class IRGenSILFunction :
if (VarInfo.ArgNo) {
PrologueLocation AutoRestore(IGM.DebugInfo.get(), Builder);
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarLoc,
VarInfo, Indirection);
VarInfo, Indirection, ArtificialKind::RealValue,
DbgInstrKind);
} else
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarLoc,
VarInfo, Indirection);
VarInfo, Indirection, ArtificialKind::RealValue,
DbgInstrKind);
}

void emitFailBB() {
Expand Down Expand Up @@ -4914,7 +4917,11 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
auto funcTy = CurSILFn->getLoweredFunctionType();
emitErrorResultVar(funcTy, funcTy->getErrorResult(), i);
}
return;

// If we were not moved return early. If this SILUndef was moved, then we
// need to let it through so we can ensure the debug info invalidated.
if (!i->getWasMoved())
return;
}
bool IsInCoro = InCoroContext(*CurSILFn, *i);

Expand Down Expand Up @@ -4974,7 +4981,8 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
return;

emitDebugVariableDeclaration(Copy, DbgTy, SILTy, i->getDebugScope(),
i->getLoc(), *VarInfo, Indirection);
i->getLoc(), *VarInfo, Indirection,
AddrDbgInstrKind(i->getWasMoved()));
}

void IRGenSILFunction::visitFixLifetimeInst(swift::FixLifetimeInst *i) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1767,7 +1767,7 @@ bool DataflowState::process(
debug.markAsMoved();
if (auto varInfo = debug.getVarInfo()) {
builder.createDebugValue(
mvi->getLoc(),
debug.inst->getLoc(),
SILUndef::get(address->getType(), builder.getModule()), *varInfo,
false /*poison*/, true /*was moved*/);
}
Expand Down Expand Up @@ -1913,7 +1913,7 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
if (auto debug = DebugVarCarryingInst::getFromValue(address)) {
if (auto varInfo = debug.getVarInfo()) {
builder.createDebugValue(
mvi->getLoc(),
debug.inst->getLoc(),
SILUndef::get(address->getType(), builder.getModule()), *varInfo,
false,
/*was moved*/ true);
Expand Down Expand Up @@ -2021,7 +2021,7 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
if (auto debug = DebugVarCarryingInst::getFromValue(address)) {
if (auto varInfo = debug.getVarInfo()) {
builder.createDebugValue(
mvi->getLoc(),
debug.inst->getLoc(),
SILUndef::get(address->getType(), builder.getModule()), *varInfo,
false,
/*was moved*/ true);
Expand Down Expand Up @@ -2060,7 +2060,7 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
if (auto debug = DebugVarCarryingInst::getFromValue(address)) {
if (auto varInfo = debug.getVarInfo()) {
builder.createDebugValue(
mvi->getLoc(),
debug.inst->getLoc(),
SILUndef::get(address->getType(), builder.getModule()), *varInfo,
false,
/*was moved*/ true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ bool MoveKillsCopyableValuesChecker::check() {
// Use an autogenerated location to ensure that if we are next to a
// terminator, we don't assert.
builder.createDebugValue(
RegularLocation::getAutoGeneratedLocation(),
dbgVarInfo.inst->getLoc(),
SILUndef::get(mvi->getOperand()->getType(), mod), *varInfo,
false /*poison*/, true /*moved*/);
}
Expand Down
Loading