Skip to content

Commit 28fb3db

Browse files
authored
Merge pull request #41378 from gottesmm/pr-4f030e9c7eb178276a709f3b668f8f9f357ffb40
[move-function] Add initial debug info support to move checker passes.
2 parents 2827804 + edbe4db commit 28fb3db

20 files changed

+418
-74
lines changed

docs/SIL.rst

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3178,7 +3178,7 @@ alloc_stack
31783178
```````````
31793179
::
31803180

3181-
sil-instruction ::= 'alloc_stack' '[dynamic_lifetime]'? '[lexical]'? sil-type (',' debug-var-attr)*
3181+
sil-instruction ::= 'alloc_stack' '[dynamic_lifetime]'? '[lexical]'? '[moved]'? sil-type (',' debug-var-attr)*
31823182

31833183
%1 = alloc_stack $T
31843184
// %1 has type $*T
@@ -3204,6 +3204,12 @@ This is the case, e.g. for conditionally initialized objects.
32043204
The optional ``lexical`` attribute specifies that the storage corresponds to a
32053205
local variable in the Swift source.
32063206

3207+
The optional ``moved`` attribute specifies that at the source level, the
3208+
variable associated with this alloc_stack was moved and furthermore that at the
3209+
SIL level it passed move operator checking. This means that one can not assume
3210+
that the value in the alloc_stack can be semantically valid over the entire
3211+
function frame when emitting debug info.
3212+
32073213
The memory is not retainable. To allocate a retainable box for a value
32083214
type, use ``alloc_box``.
32093215

@@ -3548,7 +3554,7 @@ debug_value
35483554

35493555
::
35503556

3551-
sil-instruction ::= debug_value '[poison]'? sil-operand (',' debug-var-attr)* advanced-debug-var-attr* (',' 'expr' debug-info-expr)?
3557+
sil-instruction ::= debug_value '[poison]'? '[moved]'? sil-operand (',' debug-var-attr)* advanced-debug-var-attr* (',' 'expr' debug-info-expr)?
35523558

35533559
debug_value %1 : $Int
35543560

@@ -3557,6 +3563,11 @@ specified operand. The declaration in question is identified by either the
35573563
SILLocation attached to the debug_value instruction or the SILLocation specified
35583564
in the advanced debug variable attributes.
35593565

3566+
If the '[moved]' flag is set, then one knows that the debug_value's operand is
3567+
moved at some point of the program, so one can not model the debug_value using
3568+
constructs that assume that the value is live for the entire function (e.x.:
3569+
llvm.dbg.declare).
3570+
35603571
::
35613572

35623573
debug-var-attr ::= 'var'

include/swift/SIL/DebugUtils.h

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -325,34 +325,61 @@ struct DebugVarCarryingInst {
325325
llvm_unreachable("Not implemented");
326326
}
327327
}
328-
};
329328

330-
/// Attempt to discover a StringRef varName for the value \p value. If we fail,
331-
/// we return the name "unknown".
332-
inline StringRef getDebugVarName(SILValue value) {
333-
if (auto *asi = dyn_cast<AllocStackInst>(value)) {
334-
DebugVarCarryingInst debugVar(asi);
335-
if (auto varInfo = debugVar.getVarInfo()) {
336-
return varInfo->Name;
337-
} else {
338-
if (auto *decl = debugVar.getDecl()) {
339-
return decl->getBaseName().userFacingName();
340-
}
329+
void markAsMoved() {
330+
switch (kind) {
331+
case Kind::Invalid:
332+
llvm_unreachable("Invalid?!");
333+
case Kind::DebugValue:
334+
cast<DebugValueInst>(inst)->markAsMoved();
335+
break;
336+
case Kind::AllocStack:
337+
cast<AllocStackInst>(inst)->markAsMoved();
338+
break;
339+
case Kind::AllocBox:
340+
llvm_unreachable("Not implemented");
341341
}
342342
}
343343

344-
StringRef varName = "unknown";
345-
if (auto *use = getSingleDebugUse(value)) {
346-
DebugVarCarryingInst debugVar(use->getUser());
347-
if (auto varInfo = debugVar.getVarInfo()) {
344+
/// If \p value is an alloc_stack, alloc_box use that. Otherwise, see if \p
345+
/// value has a single debug user, return that. Otherwise return the invalid
346+
/// DebugVarCarryingInst.
347+
static DebugVarCarryingInst getFromValue(SILValue value);
348+
349+
/// Take in \p inst, a potentially invalid DebugVarCarryingInst, and returns a
350+
/// name for it. If we have an invalid value or don't find var info or a decl,
351+
/// return "unknown".
352+
///
353+
/// The reason this isn't a method is that in all the other parts of
354+
/// DebugVarCarryingInst, we use Invalid to signal early error.
355+
static StringRef getName(DebugVarCarryingInst inst) {
356+
if (!inst)
357+
return "unknown";
358+
StringRef varName = "unknown";
359+
if (auto varInfo = inst.getVarInfo()) {
348360
varName = varInfo->Name;
349-
} else {
350-
if (auto *decl = debugVar.getDecl()) {
351-
varName = decl->getBaseName().userFacingName();
352-
}
361+
} else if (auto *decl = inst.getDecl()) {
362+
varName = decl->getBaseName().userFacingName();
353363
}
364+
return varName;
354365
}
355-
return varName;
366+
};
367+
368+
inline DebugVarCarryingInst DebugVarCarryingInst::getFromValue(SILValue value) {
369+
if (isa<AllocStackInst>(value) || isa<AllocBoxInst>(value))
370+
return DebugVarCarryingInst(cast<SingleValueInstruction>(value));
371+
372+
if (auto *use = getSingleDebugUse(value))
373+
return DebugVarCarryingInst(use->getUser());
374+
375+
return DebugVarCarryingInst();
376+
}
377+
378+
/// Attempt to discover a StringRef varName for the value \p value. If we fail,
379+
/// we return the name "unknown".
380+
inline StringRef getDebugVarName(SILValue value) {
381+
auto inst = DebugVarCarryingInst::getFromValue(value);
382+
return DebugVarCarryingInst::getName(inst);
356383
}
357384

358385
} // end namespace swift

include/swift/SIL/SILBuilder.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -382,15 +382,16 @@ class SILBuilder {
382382
AllocStackInst *createAllocStack(SILLocation Loc, SILType elementType,
383383
Optional<SILDebugVariable> Var = None,
384384
bool hasDynamicLifetime = false,
385-
bool isLexical = false) {
385+
bool isLexical = false,
386+
bool wasMoved = false) {
386387
llvm::SmallString<4> Name;
387388
Loc.markAsPrologue();
388389
assert((!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
389390
"location is a VarDecl, but SILDebugVariable is empty");
390391
return insert(AllocStackInst::create(
391392
getSILDebugLocation(Loc), elementType, getFunction(),
392-
substituteAnonymousArgs(Name, Var, Loc), hasDynamicLifetime,
393-
isLexical));
393+
substituteAnonymousArgs(Name, Var, Loc), hasDynamicLifetime, isLexical,
394+
wasMoved));
394395
}
395396

396397
AllocRefInst *createAllocRef(SILLocation Loc, SILType ObjectType,
@@ -941,9 +942,11 @@ class SILBuilder {
941942

942943
DebugValueInst *createDebugValue(SILLocation Loc, SILValue src,
943944
SILDebugVariable Var,
944-
bool poisonRefs = false);
945+
bool poisonRefs = false,
946+
bool wasMoved = false);
945947
DebugValueInst *createDebugValueAddr(SILLocation Loc, SILValue src,
946-
SILDebugVariable Var);
948+
SILDebugVariable Var,
949+
bool wasMoved = false);
947950

948951
/// Create a debug_value according to the type of \p src
949952
SILInstruction *emitDebugDescription(SILLocation Loc, SILValue src,

include/swift/SIL/SILCloner.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ SILCloner<ImplClass>::visitAllocStackInst(AllocStackInst *Inst) {
800800
}
801801
auto *NewInst = getBuilder().createAllocStack(
802802
Loc, getOpType(Inst->getElementType()), VarInfo,
803-
Inst->hasDynamicLifetime(), Inst->isLexical());
803+
Inst->hasDynamicLifetime(), Inst->isLexical(), Inst->getWasMoved());
804804
remapDebugVarInfo(DebugVarCarryingInst(NewInst));
805805
recordClonedInstruction(Inst, NewInst);
806806
}
@@ -1277,9 +1277,9 @@ SILCloner<ImplClass>::visitDebugValueInst(DebugValueInst *Inst) {
12771277
// Since we want the debug info to survive, we do not remap the location here.
12781278
SILDebugVariable VarInfo = *Inst->getVarInfo();
12791279
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1280-
auto *NewInst = getBuilder().createDebugValue(Inst->getLoc(),
1281-
getOpValue(Inst->getOperand()),
1282-
VarInfo, Inst->poisonRefs());
1280+
auto *NewInst = getBuilder().createDebugValue(
1281+
Inst->getLoc(), getOpValue(Inst->getOperand()), VarInfo,
1282+
Inst->poisonRefs(), Inst->getWasMoved());
12831283
remapDebugVarInfo(DebugVarCarryingInst(NewInst));
12841284
recordClonedInstruction(Inst, NewInst);
12851285
}

include/swift/SIL/SILInstruction.h

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,14 +1916,19 @@ class AllocStackInst final
19161916
bool dynamicLifetime = false;
19171917
bool lexical = false;
19181918

1919+
/// Set to true if this alloc_stack's memory location was passed to _move at
1920+
/// any point of the program.
1921+
bool wasMoved = false;
1922+
19191923
AllocStackInst(SILDebugLocation Loc, SILType elementType,
19201924
ArrayRef<SILValue> TypeDependentOperands, SILFunction &F,
19211925
Optional<SILDebugVariable> Var, bool hasDynamicLifetime,
1922-
bool isLexical);
1926+
bool isLexical, bool wasMoved);
19231927

19241928
static AllocStackInst *create(SILDebugLocation Loc, SILType elementType,
19251929
SILFunction &F, Optional<SILDebugVariable> Var,
1926-
bool hasDynamicLifetime, bool isLexical);
1930+
bool hasDynamicLifetime, bool isLexical,
1931+
bool wasMoved);
19271932

19281933
SIL_DEBUG_VAR_SUPPLEMENT_TRAILING_OBJS_IMPL()
19291934

@@ -1940,6 +1945,10 @@ class AllocStackInst final
19401945
}
19411946
}
19421947

1948+
void markAsMoved() { wasMoved = true; }
1949+
1950+
bool getWasMoved() const { return wasMoved; }
1951+
19431952
/// Set to true that this alloc_stack contains a value whose lifetime can not
19441953
/// be ascertained from uses.
19451954
///
@@ -4696,22 +4705,34 @@ class DebugValueInst final
46964705

46974706
TailAllocatedDebugVariable VarInfo;
46984707

4708+
/// Set to true if this debug_value is on an SSA value that was moved.
4709+
///
4710+
/// IRGen uses this information to determine if we should use llvm.dbg.addr or
4711+
/// llvm.dbg.declare.
4712+
bool operandWasMoved = false;
4713+
46994714
DebugValueInst(SILDebugLocation DebugLoc, SILValue Operand,
4700-
SILDebugVariable Var, bool poisonRefs);
4715+
SILDebugVariable Var, bool poisonRefs, bool operandWasMoved);
47014716
static DebugValueInst *create(SILDebugLocation DebugLoc, SILValue Operand,
47024717
SILModule &M, SILDebugVariable Var,
4703-
bool poisonRefs);
4718+
bool poisonRefs, bool operandWasMoved);
47044719
static DebugValueInst *createAddr(SILDebugLocation DebugLoc, SILValue Operand,
4705-
SILModule &M, SILDebugVariable Var);
4720+
SILModule &M, SILDebugVariable Var,
4721+
bool operandWasMoved);
47064722

47074723
SIL_DEBUG_VAR_SUPPLEMENT_TRAILING_OBJS_IMPL()
47084724

47094725
size_t numTrailingObjects(OverloadToken<char>) const { return 1; }
47104726

47114727
public:
4728+
void markAsMoved() { operandWasMoved = true; }
4729+
4730+
bool getWasMoved() const { return operandWasMoved; }
4731+
47124732
/// Return the underlying variable declaration that this denotes,
47134733
/// or null if we don't have one.
47144734
VarDecl *getDecl() const;
4735+
47154736
/// Return the debug variable information attached to this instruction.
47164737
Optional<SILDebugVariable> getVarInfo() const {
47174738
Optional<SILType> AuxVarType;

lib/SIL/IR/SILBuilder.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -572,24 +572,25 @@ void SILBuilder::emitDestructureValueOperation(
572572

573573
DebugValueInst *SILBuilder::createDebugValue(SILLocation Loc, SILValue src,
574574
SILDebugVariable Var,
575-
bool poisonRefs) {
575+
bool poisonRefs,
576+
bool operandWasMoved) {
576577
llvm::SmallString<4> Name;
577578
// Debug location overrides cannot apply to debug value instructions.
578579
DebugLocOverrideRAII LocOverride{*this, None};
579580
return insert(DebugValueInst::create(
580581
getSILDebugLocation(Loc), src, getModule(),
581-
*substituteAnonymousArgs(Name, Var, Loc), poisonRefs));
582+
*substituteAnonymousArgs(Name, Var, Loc), poisonRefs, operandWasMoved));
582583
}
583584

584-
DebugValueInst *SILBuilder::createDebugValueAddr(SILLocation Loc,
585-
SILValue src,
586-
SILDebugVariable Var) {
585+
DebugValueInst *SILBuilder::createDebugValueAddr(SILLocation Loc, SILValue src,
586+
SILDebugVariable Var,
587+
bool wasMoved) {
587588
llvm::SmallString<4> Name;
588589
// Debug location overrides cannot apply to debug addr instructions.
589590
DebugLocOverrideRAII LocOverride{*this, None};
590-
return insert(
591-
DebugValueInst::createAddr(getSILDebugLocation(Loc), src, getModule(),
592-
*substituteAnonymousArgs(Name, Var, Loc)));
591+
return insert(DebugValueInst::createAddr(
592+
getSILDebugLocation(Loc), src, getModule(),
593+
*substituteAnonymousArgs(Name, Var, Loc), wasMoved));
593594
}
594595

595596
void SILBuilder::emitScopedBorrowOperation(SILLocation loc, SILValue original,

lib/SIL/IR/SILInstructions.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,15 @@ SILDebugVariable::createFromAllocation(const AllocationInst *AI) {
190190
AllocStackInst::AllocStackInst(SILDebugLocation Loc, SILType elementType,
191191
ArrayRef<SILValue> TypeDependentOperands,
192192
SILFunction &F, Optional<SILDebugVariable> Var,
193-
bool hasDynamicLifetime, bool isLexical)
193+
bool hasDynamicLifetime, bool isLexical,
194+
bool wasMoved)
194195
: InstructionBase(Loc, elementType.getAddressType()),
195196
SILDebugVariableSupplement(Var ? Var->DIExpr.getNumElements() : 0,
196197
Var ? Var->Type.hasValue() : false,
197198
Var ? Var->Loc.hasValue() : false,
198199
Var ? Var->Scope != nullptr : false),
199-
dynamicLifetime(hasDynamicLifetime), lexical(isLexical) {
200+
dynamicLifetime(hasDynamicLifetime), lexical(isLexical),
201+
wasMoved(wasMoved) {
200202
SILNode::Bits.AllocStackInst.NumOperands =
201203
TypeDependentOperands.size();
202204
assert(SILNode::Bits.AllocStackInst.NumOperands ==
@@ -221,15 +223,16 @@ AllocStackInst::AllocStackInst(SILDebugLocation Loc, SILType elementType,
221223
AllocStackInst *AllocStackInst::create(SILDebugLocation Loc,
222224
SILType elementType, SILFunction &F,
223225
Optional<SILDebugVariable> Var,
224-
bool hasDynamicLifetime,
225-
bool isLexical) {
226+
bool hasDynamicLifetime, bool isLexical,
227+
bool wasMoved) {
226228
SmallVector<SILValue, 8> TypeDependentOperands;
227229
collectTypeDependentOperands(TypeDependentOperands, F,
228230
elementType.getASTType());
229231
void *Buffer = allocateDebugVarCarryingInst<AllocStackInst>(
230232
F.getModule(), Var, TypeDependentOperands);
231-
return ::new (Buffer) AllocStackInst(Loc, elementType, TypeDependentOperands,
232-
F, Var, hasDynamicLifetime, isLexical);
233+
return ::new (Buffer)
234+
AllocStackInst(Loc, elementType, TypeDependentOperands, F, Var,
235+
hasDynamicLifetime, isLexical, wasMoved);
233236
}
234237

235238
VarDecl *AllocationInst::getDecl() const {
@@ -334,7 +337,8 @@ SILType AllocBoxInst::getAddressType() const {
334337
}
335338

336339
DebugValueInst::DebugValueInst(SILDebugLocation DebugLoc, SILValue Operand,
337-
SILDebugVariable Var, bool poisonRefs)
340+
SILDebugVariable Var, bool poisonRefs,
341+
bool wasMoved)
338342
: UnaryInstructionBase(DebugLoc, Operand),
339343
SILDebugVariableSupplement(Var.DIExpr.getNumElements(),
340344
Var.Type.hasValue(), Var.Loc.hasValue(),
@@ -346,26 +350,31 @@ DebugValueInst::DebugValueInst(SILDebugLocation DebugLoc, SILValue Operand,
346350
if (auto *VD = DebugLoc.getLocation().getAsASTNode<VarDecl>())
347351
VarInfo.setImplicit(VD->isImplicit() || VarInfo.isImplicit());
348352
setPoisonRefs(poisonRefs);
353+
if (wasMoved)
354+
markAsMoved();
349355
}
350356

351357
DebugValueInst *DebugValueInst::create(SILDebugLocation DebugLoc,
352358
SILValue Operand, SILModule &M,
353-
SILDebugVariable Var, bool poisonRefs) {
359+
SILDebugVariable Var, bool poisonRefs,
360+
bool wasMoved) {
354361
void *buf = allocateDebugVarCarryingInst<DebugValueInst>(M, Var);
355-
return ::new (buf) DebugValueInst(DebugLoc, Operand, Var, poisonRefs);
362+
return ::new (buf)
363+
DebugValueInst(DebugLoc, Operand, Var, poisonRefs, wasMoved);
356364
}
357365

358366
DebugValueInst *DebugValueInst::createAddr(SILDebugLocation DebugLoc,
359367
SILValue Operand, SILModule &M,
360-
SILDebugVariable Var) {
368+
SILDebugVariable Var,
369+
bool wasMoved) {
361370
// For alloc_stack, debug_value is used to annotate the associated
362371
// memory location, so we shouldn't attach op_deref.
363372
if (!isa<AllocStackInst>(Operand))
364373
Var.DIExpr.prependElements(
365374
{SILDIExprElement::createOperator(SILDIExprOperator::Dereference)});
366375
void *buf = allocateDebugVarCarryingInst<DebugValueInst>(M, Var);
367376
return ::new (buf) DebugValueInst(DebugLoc, Operand, Var,
368-
/*poisonRefs=*/false);
377+
/*poisonRefs=*/false, wasMoved);
369378
}
370379

371380
bool DebugValueInst::exprStartsWithDeref() const {

lib/SIL/IR/SILPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,8 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
13211321
*this << "[dynamic_lifetime] ";
13221322
if (AVI->isLexical())
13231323
*this << "[lexical] ";
1324+
if (AVI->getWasMoved())
1325+
*this << "[moved] ";
13241326
*this << AVI->getElementType();
13251327
printDebugVar(AVI->getVarInfo(),
13261328
&AVI->getModule().getASTContext().SourceMgr);
@@ -1681,6 +1683,8 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
16811683
void visitDebugValueInst(DebugValueInst *DVI) {
16821684
if (DVI->poisonRefs())
16831685
*this << "[poison] ";
1686+
if (DVI->getWasMoved())
1687+
*this << "[moved] ";
16841688
*this << getIDAndType(DVI->getOperand());
16851689
printDebugVar(DVI->getVarInfo(),
16861690
&DVI->getModule().getASTContext().SourceMgr);

0 commit comments

Comments
 (0)