Skip to content

Commit eb895e7

Browse files
authored
Merge pull request #64475 from gottesmm/sil-noncopyable-debuginfo
[move-only] Initial commit of debug info for noncopyable types
2 parents b123204 + c94d72d commit eb895e7

27 files changed

+594
-195
lines changed

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ public struct Builder {
8484
}
8585

8686
public func createAllocStack(_ type: Type, hasDynamicLifetime: Bool = false,
87-
isLexical: Bool = false, wasMoved: Bool = false) -> AllocStackInst {
87+
isLexical: Bool = false,
88+
usesMoveableValueDebugInfo: Bool = false) -> AllocStackInst {
8889
let dr = SILBuilder_createAllocStack(bridged, type.bridged, hasDynamicLifetime ? 1 : 0,
89-
isLexical ? 1 : 0, wasMoved ? 1 : 0)
90+
isLexical ? 1 : 0, usesMoveableValueDebugInfo ? 1 : 0)
9091
return notifyNew(dr.getAs(AllocStackInst.self))
9192
}
9293

docs/SIL.rst

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3745,7 +3745,10 @@ alloc_stack
37453745
```````````
37463746
::
37473747

3748-
sil-instruction ::= 'alloc_stack' '[dynamic_lifetime]'? '[lexical]'? '[moved]'? sil-type (',' debug-var-attr)*
3748+
sil-instruction ::= 'alloc_stack' alloc-stack-option* sil-type (',' debug-var-attr)*
3749+
alloc-stack-option ::= '[dynamic_lifetime]'
3750+
alloc-stack-option ::= '[lexical]'
3751+
alloc-stack-option ::= '[moveable_value_debuginfo]'
37493752

37503753
%1 = alloc_stack $T
37513754
// %1 has type $*T
@@ -3767,11 +3770,11 @@ This is the case, e.g. for conditionally initialized objects.
37673770
The optional ``lexical`` attribute specifies that the storage corresponds to a
37683771
local variable in the Swift source.
37693772

3770-
The optional ``moved`` attribute specifies that at the source level, the
3771-
variable associated with this alloc_stack was moved and furthermore that at the
3772-
SIL level it passed move operator checking. This means that one can not assume
3773-
that the value in the alloc_stack can be semantically valid over the entire
3774-
function frame when emitting debug info.
3773+
The optional ``moveable_value_debuginfo`` attribute specifies that when emitting
3774+
debug info, the code generator can not assume that the value in the alloc_stack
3775+
can be semantically valid over the entire function frame when emitting debug
3776+
info. NOTE: This is implicitly set to true if the alloc_stack's type is
3777+
noncopyable. This is just done to make SIL less verbose.
37753778

37763779
The memory is not retainable. To allocate a retainable box for a value
37773780
type, use ``alloc_box``.
@@ -3865,7 +3868,8 @@ alloc_box
38653868
`````````
38663869
::
38673870

3868-
sil-instruction ::= 'alloc_box' sil-type (',' debug-var-attr)*
3871+
sil-instruction ::= 'alloc_box' alloc-box-option* sil-type (',' debug-var-attr)*
3872+
alloc-box-option ::= moveable_value_debuginfo
38693873

38703874
%1 = alloc_box $T
38713875
// %1 has type $@box T
@@ -3883,6 +3887,12 @@ Releasing a box is undefined behavior if the box's value is uninitialized.
38833887
To deallocate a box whose value has not been initialized, ``dealloc_box``
38843888
should be used.
38853889

3890+
The optional ``moveable_value_debuginfo`` attribute specifies that when emitting
3891+
debug info, the code generator can not assume that the value in the alloc_stack
3892+
can be semantically valid over the entire function frame when emitting debug
3893+
info. NOTE: This is implicitly set to true if the alloc_stack's type is
3894+
noncopyable. This is just done to make SIL less verbose.
3895+
38863896
alloc_global
38873897
````````````
38883898

@@ -4155,7 +4165,10 @@ debug_value
41554165

41564166
::
41574167

4158-
sil-instruction ::= debug_value '[poison]'? '[moved]'? '[trace]'? sil-operand (',' debug-var-attr)* advanced-debug-var-attr* (',' 'expr' debug-info-expr)?
4168+
sil-instruction ::= debug_value sil-debug-value-option* sil-operand (',' debug-var-attr)* advanced-debug-var-attr* (',' 'expr' debug-info-expr)?
4169+
sil-debug-value-option ::= [poison]
4170+
sil-debug-value-option ::= [moveable_value_debuginfo]
4171+
sil-debug-value-option ::= [trace]
41594172

41604173
debug_value %1 : $Int
41614174

@@ -4164,10 +4177,12 @@ specified operand. The declaration in question is identified by either the
41644177
SILLocation attached to the debug_value instruction or the SILLocation specified
41654178
in the advanced debug variable attributes.
41664179

4167-
If the '[moved]' flag is set, then one knows that the debug_value's operand is
4168-
moved at some point of the program, so one can not model the debug_value using
4169-
constructs that assume that the value is live for the entire function (e.x.:
4170-
llvm.dbg.declare).
4180+
If the ``moveable_value_debuginfo`` flag is set, then one knows that the
4181+
debug_value's operand is moved at some point of the program, so one can not
4182+
model the debug_value using constructs that assume that the value is live for
4183+
the entire function (e.x.: llvm.dbg.declare). NOTE: This is implicitly set to
4184+
true if the alloc_stack's type is noncopyable. This is just done to make SIL
4185+
less verbose.
41714186

41724187
::
41734188

include/swift/SIL/DebugUtils.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#define SWIFT_SIL_DEBUGUTILS_H
3838

3939
#include "swift/SIL/SILBasicBlock.h"
40+
#include "swift/SIL/SILBuilder.h"
4041
#include "swift/SIL/SILGlobalVariable.h"
4142
#include "swift/SIL/SILInstruction.h"
4243

@@ -460,13 +461,14 @@ struct DebugVarCarryingInst : VarDeclCarryingInst {
460461
case Kind::Invalid:
461462
llvm_unreachable("Invalid?!");
462463
case Kind::DebugValue:
463-
cast<DebugValueInst>(**this)->markAsMoved();
464+
cast<DebugValueInst>(**this)->setUsesMoveableValueDebugInfo();
464465
break;
465466
case Kind::AllocStack:
466-
cast<AllocStackInst>(**this)->markAsMoved();
467+
cast<AllocStackInst>(**this)->markUsesMoveableValueDebugInfo();
467468
break;
468469
case Kind::AllocBox:
469-
llvm_unreachable("Not implemented");
470+
cast<AllocBoxInst>(**this)->setUsesMoveableValueDebugInfo();
471+
break;
470472
}
471473
}
472474

@@ -476,12 +478,11 @@ struct DebugVarCarryingInst : VarDeclCarryingInst {
476478
case Kind::Invalid:
477479
llvm_unreachable("Invalid?!");
478480
case Kind::DebugValue:
479-
return cast<DebugValueInst>(**this)->getWasMoved();
481+
return cast<DebugValueInst>(**this)->getUsesMoveableValueDebugInfo();
480482
case Kind::AllocStack:
481-
return cast<AllocStackInst>(**this)->getWasMoved();
483+
return cast<AllocStackInst>(**this)->getUsesMoveableValueDebugInfo();
482484
case Kind::AllocBox:
483-
// We do not support moving alloc box today, so we always return false.
484-
return false;
485+
return cast<AllocBoxInst>(**this)->getUsesMoveableValueDebugInfo();
485486
}
486487
}
487488

@@ -500,7 +501,7 @@ struct DebugVarCarryingInst : VarDeclCarryingInst {
500501
case Kind::AllocStack:
501502
return cast<AllocStackInst>(**this);
502503
case Kind::AllocBox:
503-
llvm_unreachable("Not implemented");
504+
return cast<AllocBoxInst>(**this);
504505
}
505506
}
506507

include/swift/SIL/SILBuilder.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -444,22 +444,26 @@ class SILBuilder {
444444
AllocBoxInst *createAllocBox(SILLocation loc, SILType fieldType,
445445
Optional<SILDebugVariable> Var = None,
446446
bool hasDynamicLifetime = false,
447-
bool reflection = false) {
447+
bool reflection = false,
448+
bool usesMoveableValueDebugInfo = false) {
448449
return createAllocBox(loc, SILBoxType::get(fieldType.getASTType()), Var,
449-
hasDynamicLifetime, reflection);
450+
hasDynamicLifetime, reflection,
451+
usesMoveableValueDebugInfo);
450452
}
451453

452454
AllocBoxInst *createAllocBox(SILLocation Loc, CanSILBoxType BoxType,
453455
Optional<SILDebugVariable> Var = None,
454456
bool hasDynamicLifetime = false,
455-
bool reflection = false) {
457+
bool reflection = false,
458+
bool usesMoveableValueDebugInfo = false) {
456459
llvm::SmallString<4> Name;
457460
Loc.markAsPrologue();
458461
assert((!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
459462
"location is a VarDecl, but SILDebugVariable is empty");
460463
return insert(AllocBoxInst::create(getSILDebugLocation(Loc), BoxType, *F,
461464
substituteAnonymousArgs(Name, Var, Loc),
462-
hasDynamicLifetime, reflection));
465+
hasDynamicLifetime, reflection,
466+
usesMoveableValueDebugInfo));
463467
}
464468

465469
AllocExistentialBoxInst *

include/swift/SIL/SILCloner.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,8 @@ SILCloner<ImplClass>::visitAllocStackInst(AllocStackInst *Inst) {
893893
}
894894
auto *NewInst = getBuilder().createAllocStack(
895895
Loc, getOpType(Inst->getElementType()), VarInfo,
896-
Inst->hasDynamicLifetime(), Inst->isLexical(), Inst->getWasMoved());
896+
Inst->hasDynamicLifetime(), Inst->isLexical(),
897+
Inst->getUsesMoveableValueDebugInfo());
897898
remapDebugVarInfo(DebugVarCarryingInst(NewInst));
898899
recordClonedInstruction(Inst, NewInst);
899900
}
@@ -1380,7 +1381,8 @@ SILCloner<ImplClass>::visitDebugValueInst(DebugValueInst *Inst) {
13801381
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
13811382
auto *NewInst = getBuilder().createDebugValue(
13821383
Inst->getLoc(), getOpValue(Inst->getOperand()), VarInfo,
1383-
Inst->poisonRefs(), Inst->getWasMoved(), Inst->hasTrace());
1384+
Inst->poisonRefs(), Inst->getUsesMoveableValueDebugInfo(),
1385+
Inst->hasTrace());
13841386
remapDebugVarInfo(DebugVarCarryingInst(NewInst));
13851387
recordClonedInstruction(Inst, NewInst);
13861388
}

include/swift/SIL/SILInstruction.h

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,12 +2094,12 @@ class AllocStackInst final
20942094
AllocStackInst(SILDebugLocation Loc, SILType elementType,
20952095
ArrayRef<SILValue> TypeDependentOperands, SILFunction &F,
20962096
Optional<SILDebugVariable> Var, bool hasDynamicLifetime,
2097-
bool isLexical, bool wasMoved);
2097+
bool isLexical, bool usesMoveableValueDebugInfo);
20982098

20992099
static AllocStackInst *create(SILDebugLocation Loc, SILType elementType,
21002100
SILFunction &F, Optional<SILDebugVariable> Var,
21012101
bool hasDynamicLifetime, bool isLexical,
2102-
bool wasMoved);
2102+
bool usesMoveableValueDebugInfo);
21032103

21042104
SIL_DEBUG_VAR_SUPPLEMENT_TRAILING_OBJS_IMPL()
21052105

@@ -2116,11 +2116,15 @@ class AllocStackInst final
21162116
}
21172117
}
21182118

2119-
void markAsMoved() { sharedUInt8().AllocStackInst.wasMoved = true; }
2119+
void markUsesMoveableValueDebugInfo() {
2120+
sharedUInt8().AllocStackInst.usesMoveableValueDebugInfo = true;
2121+
}
21202122

21212123
/// Set to true if this alloc_stack's memory location was passed to _move at
21222124
/// any point of the program.
2123-
bool getWasMoved() const { return sharedUInt8().AllocStackInst.wasMoved; }
2125+
bool getUsesMoveableValueDebugInfo() const {
2126+
return sharedUInt8().AllocStackInst.usesMoveableValueDebugInfo;
2127+
}
21242128

21252129
/// Set to true that this alloc_stack contains a value whose lifetime can not
21262130
/// be ascertained from uses.
@@ -2452,39 +2456,53 @@ class AllocBoxInst final
24522456

24532457
TailAllocatedDebugVariable VarInfo;
24542458

2455-
unsigned HasDynamicLifetime : 1;
2456-
unsigned Reflection : 1;
2459+
USE_SHARED_UINT8;
24572460

24582461
AllocBoxInst(SILDebugLocation DebugLoc, CanSILBoxType BoxType,
24592462
ArrayRef<SILValue> TypeDependentOperands, SILFunction &F,
24602463
Optional<SILDebugVariable> Var, bool hasDynamicLifetime,
2461-
bool reflection = false);
2464+
bool reflection = false,
2465+
bool usesMoveableValueDebugInfo = false);
24622466

24632467
static AllocBoxInst *create(SILDebugLocation Loc, CanSILBoxType boxType,
2464-
SILFunction &F,
2465-
Optional<SILDebugVariable> Var,
2466-
bool hasDynamicLifetime,
2467-
bool reflection = false);
2468+
SILFunction &F, Optional<SILDebugVariable> Var,
2469+
bool hasDynamicLifetime, bool reflection = false,
2470+
bool usesMoveableValueDebugInfo = false);
24682471

24692472
public:
24702473
CanSILBoxType getBoxType() const {
24712474
return getType().castTo<SILBoxType>();
24722475
}
24732476

2474-
void setDynamicLifetime() { HasDynamicLifetime = true; }
2475-
bool hasDynamicLifetime() const { return HasDynamicLifetime; }
2477+
void setDynamicLifetime() {
2478+
sharedUInt8().AllocBoxInst.dynamicLifetime = true;
2479+
}
2480+
2481+
bool hasDynamicLifetime() const {
2482+
return sharedUInt8().AllocBoxInst.dynamicLifetime;
2483+
}
24762484

24772485
/// True if the box should be emitted with reflection metadata for its
24782486
/// contents.
2479-
bool emitReflectionMetadata() const { return Reflection; }
2480-
2487+
bool emitReflectionMetadata() const {
2488+
return sharedUInt8().AllocBoxInst.reflection;
2489+
}
2490+
24812491
// Return the type of the memory stored in the alloc_box.
24822492
SILType getAddressType() const;
24832493

24842494
/// Return the debug variable information attached to this instruction.
24852495
Optional<SILDebugVariable> getVarInfo() const {
24862496
return VarInfo.get(getDecl(), getTrailingObjects<char>());
24872497
};
2498+
2499+
void setUsesMoveableValueDebugInfo() {
2500+
sharedUInt8().AllocBoxInst.usesMoveableValueDebugInfo = true;
2501+
}
2502+
2503+
bool getUsesMoveableValueDebugInfo() const {
2504+
return sharedUInt8().AllocBoxInst.usesMoveableValueDebugInfo;
2505+
}
24882506
};
24892507

24902508
/// This represents the allocation of a heap box for an existential container.
@@ -5012,14 +5030,17 @@ class DebugValueInst final
50125030
size_t numTrailingObjects(OverloadToken<char>) const { return 1; }
50135031

50145032
public:
5015-
void markAsMoved() { sharedUInt8().DebugValueInst.operandWasMoved = true; }
5033+
/// Sets a bool that states this debug_value is supposed to use the
5034+
void setUsesMoveableValueDebugInfo() {
5035+
sharedUInt8().DebugValueInst.usesMoveableValueDebugInfo = true;
5036+
}
50165037

50175038
/// True if this debug_value is on an SSA value that was moved.
50185039
///
50195040
/// IRGen uses this information to determine if we should use llvm.dbg.addr or
50205041
/// llvm.dbg.declare.
5021-
bool getWasMoved() const {
5022-
return sharedUInt8().DebugValueInst.operandWasMoved;
5042+
bool getUsesMoveableValueDebugInfo() const {
5043+
return sharedUInt8().DebugValueInst.usesMoveableValueDebugInfo;
50235044
}
50245045

50255046
/// Return the underlying variable declaration that this denotes,

include/swift/SIL/SILNode.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class alignas(8) SILNode :
174174
#define SHARED_TEMPLATE4_FIELD(T1, T2, T3, T4, I, ...) \
175175
class { template <T1, T2, T3, T4> friend class I; __VA_ARGS__; } I;
176176

177+
// clang-format off
177178
union SharedUInt8Fields {
178179
uint8_t opaque;
179180

@@ -203,15 +204,20 @@ class alignas(8) SILNode :
203204
SHARED_FIELD(BeginCOWMutationInst, bool native);
204205

205206
SHARED_FIELD(DebugValueInst, uint8_t
206-
poisonRefs : 1,
207-
operandWasMoved : 1,
208-
trace : 1);
207+
poisonRefs : 1,
208+
usesMoveableValueDebugInfo : 1,
209+
trace : 1);
209210

210211
SHARED_FIELD(AllocStackInst, uint8_t
211-
dynamicLifetime : 1,
212-
lexical : 1,
213-
wasMoved : 1,
214-
hasInvalidatedVarInfo : 1);
212+
dynamicLifetime : 1,
213+
lexical : 1,
214+
usesMoveableValueDebugInfo : 1,
215+
hasInvalidatedVarInfo : 1);
216+
217+
SHARED_FIELD(AllocBoxInst, uint8_t
218+
dynamicLifetime : 1,
219+
reflection : 1,
220+
usesMoveableValueDebugInfo : 1);
215221

216222
SHARED_FIELD(AllocRefInstBase, uint8_t
217223
objC : 1,
@@ -243,10 +249,12 @@ class alignas(8) SILNode :
243249

244250
// Do not use `_sharedUInt8_private` outside of SILNode.
245251
} _sharedUInt8_private;
252+
// clang-format on
246253

247254
static_assert(sizeof(SharedUInt8Fields) == sizeof(uint8_t),
248255
"A SILNode's shared uint8 field is too large");
249256

257+
// clang-format off
250258
union SharedUInt32Fields {
251259
uint32_t opaque;
252260

@@ -272,6 +280,7 @@ class alignas(8) SILNode :
272280

273281
// Do not use `_sharedUInt32_private` outside of SILNode.
274282
} _sharedUInt32_private;
283+
// clang-format on
275284

276285
static_assert(sizeof(SharedUInt32Fields) == sizeof(uint32_t),
277286
"A SILNode's shared uint32 field is too large");

0 commit comments

Comments
 (0)