Skip to content

Commit a4fc911

Browse files
authored
Merge pull request #63577 from gottesmm/pr-afe5ea6bd7ed4135b577a80d00a7c74a78dfe73c
[debug-info] Add a new super class of DebugVarCarryingInst called VarDeclCarryingInst
2 parents c4a503f + cec4896 commit a4fc911

File tree

3 files changed

+180
-50
lines changed

3 files changed

+180
-50
lines changed

include/swift/SIL/DebugUtils.h

Lines changed: 170 additions & 40 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/SILGlobalVariable.h"
4041
#include "swift/SIL/SILInstruction.h"
4142

4243
namespace swift {
@@ -237,31 +238,39 @@ bool hasNonTrivialNonDebugTransitiveUsers(
237238
PointerUnion<SILInstruction *, SILArgument *> V);
238239

239240
/// A light weight abstraction on top of an instruction that carries within it
240-
/// information about a debug variable. This allows one to write high level code
241-
/// over the set of such instructions with greater correctness by using
242-
/// exhaustive switches, methods, and keeping it light weight by using *, ->
243-
/// operators to access functionality from the underlying instruction when
244-
/// needed.
245-
struct DebugVarCarryingInst {
241+
/// information about a VarDecl. This allows one to write high level code over
242+
/// the set of such instructions with greater correctness by using exhaustive
243+
/// switches, methods, and keeping it light weight by using *, -> operators to
244+
/// access functionality from the underlying instruction when eneded.
245+
class VarDeclCarryingInst {
246+
public:
246247
enum class Kind : uint8_t {
247248
Invalid = 0,
248249
DebugValue,
249250
AllocStack,
250251
AllocBox,
252+
GlobalAddr,
253+
RefElementAddr,
251254
};
252255

256+
protected:
253257
SILInstruction *inst;
254258
Kind kind;
255259
uintptr_t spareBits : (sizeof(uintptr_t) - sizeof(Kind)) * 8;
256260

257-
DebugVarCarryingInst() : inst(nullptr), kind(Kind::Invalid), spareBits(0) {}
258-
DebugVarCarryingInst(DebugValueInst *dvi)
261+
public:
262+
VarDeclCarryingInst() : inst(nullptr), kind(Kind::Invalid), spareBits(0) {}
263+
VarDeclCarryingInst(DebugValueInst *dvi)
259264
: inst(dvi), kind(Kind::DebugValue), spareBits(0) {}
260-
DebugVarCarryingInst(AllocStackInst *asi)
265+
VarDeclCarryingInst(AllocStackInst *asi)
261266
: inst(asi), kind(Kind::AllocStack), spareBits(0) {}
262-
DebugVarCarryingInst(AllocBoxInst *abi)
267+
VarDeclCarryingInst(AllocBoxInst *abi)
263268
: inst(abi), kind(Kind::AllocBox), spareBits(0) {}
264-
DebugVarCarryingInst(SILInstruction *newInst)
269+
VarDeclCarryingInst(GlobalAddrInst *gai)
270+
: inst(gai), kind(Kind::GlobalAddr), spareBits(0) {}
271+
VarDeclCarryingInst(RefElementAddrInst *reai)
272+
: inst(reai), kind(Kind::RefElementAddr), spareBits(0) {}
273+
VarDeclCarryingInst(SILInstruction *newInst)
265274
: inst(nullptr), kind(Kind::Invalid), spareBits(0) {
266275
switch (newInst->getKind()) {
267276
default:
@@ -275,6 +284,12 @@ struct DebugVarCarryingInst {
275284
case SILInstructionKind::AllocBoxInst:
276285
kind = Kind::AllocBox;
277286
break;
287+
case SILInstructionKind::GlobalAddrInst:
288+
kind = Kind::GlobalAddr;
289+
break;
290+
case SILInstructionKind::RefElementAddrInst:
291+
kind = Kind::RefElementAddr;
292+
break;
278293
}
279294
inst = newInst;
280295
}
@@ -288,18 +303,23 @@ struct DebugVarCarryingInst {
288303
/// '->'. This keeps the wrapper light weight.
289304
SILInstruction *operator->() const { return inst; }
290305

291-
bool operator==(const DebugVarCarryingInst &other) const {
306+
unsigned getSpareBits() const { return spareBits; }
307+
void setSpareBits(unsigned newSpareBits) { spareBits = newSpareBits; }
308+
309+
bool operator==(const VarDeclCarryingInst &other) const {
292310
return kind == other.kind && inst == other.inst &&
293311
spareBits == other.spareBits;
294312
}
295313

296-
bool operator!=(const DebugVarCarryingInst &other) const {
314+
bool operator!=(const VarDeclCarryingInst &other) const {
297315
return !(*this == other);
298316
}
299317

300318
/// Add support for this struct in `if` statement.
301319
explicit operator bool() const { return bool(kind); }
302320

321+
Kind getKind() const { return kind; }
322+
303323
VarDecl *getDecl() const {
304324
switch (kind) {
305325
case Kind::Invalid:
@@ -310,48 +330,140 @@ struct DebugVarCarryingInst {
310330
return cast<AllocStackInst>(inst)->getDecl();
311331
case Kind::AllocBox:
312332
return cast<AllocBoxInst>(inst)->getDecl();
333+
case Kind::GlobalAddr:
334+
return cast<GlobalAddrInst>(inst)->getReferencedGlobal()->getDecl();
335+
case Kind::RefElementAddr:
336+
return cast<RefElementAddrInst>(inst)->getField();
313337
}
314338
llvm_unreachable("covered switch");
315339
}
316340

341+
/// If \p value is an alloc_stack, alloc_box use that. Otherwise, see if \p
342+
/// value has a single debug user, return that. Otherwise return the invalid
343+
/// VarDeclCarryingInst.
344+
static VarDeclCarryingInst getFromValue(SILValue value);
345+
346+
StringRef getName() const {
347+
assert(kind != Kind::Invalid);
348+
StringRef varName = "unknown";
349+
if (auto *decl = getDecl()) {
350+
varName = decl->getBaseName().userFacingName();
351+
}
352+
return varName;
353+
}
354+
355+
/// Take in \p inst, a potentially invalid VarDeclCarryingInst, and returns a
356+
/// name for it. If we have an invalid value or don't find var info or a decl,
357+
/// return "unknown".
358+
///
359+
/// The reason this isn't a method is that in all the other parts of
360+
/// VarDeclCarryingInst, we use Invalid to signal early error.
361+
static StringRef getName(VarDeclCarryingInst inst) {
362+
if (!inst)
363+
return "unknown";
364+
return inst.getName();
365+
}
366+
};
367+
368+
inline VarDeclCarryingInst VarDeclCarryingInst::getFromValue(SILValue value) {
369+
if (auto *svi = dyn_cast<SingleValueInstruction>(value)) {
370+
if (auto result = VarDeclCarryingInst(svi)) {
371+
return result;
372+
}
373+
}
374+
375+
return VarDeclCarryingInst();
376+
}
377+
378+
/// A light weight abstraction on top of an instruction that carries within it
379+
/// information about a debug variable. This allows one to write high level code
380+
/// over the set of such instructions with greater correctness by using
381+
/// exhaustive switches, methods, and keeping it light weight by using *, ->
382+
/// operators to access functionality from the underlying instruction when
383+
/// needed.
384+
struct DebugVarCarryingInst : VarDeclCarryingInst {
385+
#ifdef SET_TO_SUPER_ENUM_KIND
386+
#error "Cannot reuse this macro"
387+
#endif
388+
#define SET_TO_SUPER_ENUM_KIND(X) \
389+
X = std::underlying_type<VarDeclCarryingInst::Kind>::type( \
390+
VarDeclCarryingInst::Kind::X)
391+
enum class Kind : uint8_t {
392+
SET_TO_SUPER_ENUM_KIND(Invalid),
393+
SET_TO_SUPER_ENUM_KIND(DebugValue),
394+
SET_TO_SUPER_ENUM_KIND(AllocStack),
395+
SET_TO_SUPER_ENUM_KIND(AllocBox),
396+
};
397+
#undef SET_TO_SUPER_ENUM_KIND
398+
static_assert(
399+
std::is_same<
400+
std::underlying_type<VarDeclCarryingInst::Kind>::type,
401+
std::underlying_type<DebugVarCarryingInst::Kind>::type>::value,
402+
"DebugVarCarryingInst and VarDeclCarryingInst must have the "
403+
"same underlying type");
404+
405+
DebugVarCarryingInst() : VarDeclCarryingInst() {}
406+
DebugVarCarryingInst(DebugValueInst *dvi) : VarDeclCarryingInst(dvi) {}
407+
DebugVarCarryingInst(AllocStackInst *asi) : VarDeclCarryingInst(asi) {}
408+
DebugVarCarryingInst(AllocBoxInst *abi) : VarDeclCarryingInst(abi) {}
409+
DebugVarCarryingInst(SILInstruction *newInst)
410+
: VarDeclCarryingInst() {
411+
switch (newInst->getKind()) {
412+
default:
413+
return;
414+
case SILInstructionKind::DebugValueInst:
415+
kind = VarDeclCarryingInst::Kind::DebugValue;
416+
break;
417+
case SILInstructionKind::AllocStackInst:
418+
kind = VarDeclCarryingInst::Kind::AllocStack;
419+
break;
420+
case SILInstructionKind::AllocBoxInst:
421+
kind = VarDeclCarryingInst::Kind::AllocBox;
422+
break;
423+
}
424+
inst = newInst;
425+
}
426+
427+
Kind getKind() const { return Kind(VarDeclCarryingInst::getKind()); }
428+
317429
Optional<SILDebugVariable> getVarInfo() const {
318-
switch (kind) {
430+
switch (getKind()) {
319431
case Kind::Invalid:
320432
llvm_unreachable("Invalid?!");
321433
case Kind::DebugValue:
322-
return cast<DebugValueInst>(inst)->getVarInfo();
434+
return cast<DebugValueInst>(**this)->getVarInfo();
323435
case Kind::AllocStack:
324-
return cast<AllocStackInst>(inst)->getVarInfo();
436+
return cast<AllocStackInst>(**this)->getVarInfo();
325437
case Kind::AllocBox:
326-
return cast<AllocBoxInst>(inst)->getVarInfo();
438+
return cast<AllocBoxInst>(**this)->getVarInfo();
327439
}
328440
llvm_unreachable("covered switch");
329441
}
330442

331443
void setDebugVarScope(const SILDebugScope *NewDS) {
332-
switch (kind) {
444+
switch (getKind()) {
333445
case Kind::Invalid:
334446
llvm_unreachable("Invalid?!");
335447
case Kind::DebugValue:
336-
cast<DebugValueInst>(inst)->setDebugVarScope(NewDS);
448+
cast<DebugValueInst>(**this)->setDebugVarScope(NewDS);
337449
break;
338450
case Kind::AllocStack:
339-
cast<AllocStackInst>(inst)->setDebugVarScope(NewDS);
451+
cast<AllocStackInst>(**this)->setDebugVarScope(NewDS);
340452
break;
341453
case Kind::AllocBox:
342454
llvm_unreachable("Not implemented");
343455
}
344456
}
345457

346458
void markAsMoved() {
347-
switch (kind) {
459+
switch (getKind()) {
348460
case Kind::Invalid:
349461
llvm_unreachable("Invalid?!");
350462
case Kind::DebugValue:
351-
cast<DebugValueInst>(inst)->markAsMoved();
463+
cast<DebugValueInst>(**this)->markAsMoved();
352464
break;
353465
case Kind::AllocStack:
354-
cast<AllocStackInst>(inst)->markAsMoved();
466+
cast<AllocStackInst>(**this)->markAsMoved();
355467
break;
356468
case Kind::AllocBox:
357469
llvm_unreachable("Not implemented");
@@ -360,13 +472,13 @@ struct DebugVarCarryingInst {
360472

361473
/// Returns true if this DebugVarCarryingInst was moved.
362474
bool getWasMoved() const {
363-
switch (kind) {
475+
switch (getKind()) {
364476
case Kind::Invalid:
365477
llvm_unreachable("Invalid?!");
366478
case Kind::DebugValue:
367-
return cast<DebugValueInst>(inst)->getWasMoved();
479+
return cast<DebugValueInst>(**this)->getWasMoved();
368480
case Kind::AllocStack:
369-
return cast<AllocStackInst>(inst)->getWasMoved();
481+
return cast<AllocStackInst>(**this)->getWasMoved();
370482
case Kind::AllocBox:
371483
// We do not support moving alloc box today, so we always return false.
372484
return false;
@@ -380,13 +492,13 @@ struct DebugVarCarryingInst {
380492
/// For a debug_value, we just return the actual operand, otherwise we return
381493
/// the pointer address.
382494
SILValue getOperandForDebugValueClone() const {
383-
switch (kind) {
495+
switch (getKind()) {
384496
case Kind::Invalid:
385497
llvm_unreachable("Invalid?!");
386498
case Kind::DebugValue:
387-
return cast<DebugValueInst>(inst)->getOperand();
499+
return cast<DebugValueInst>(**this)->getOperand();
388500
case Kind::AllocStack:
389-
return cast<AllocStackInst>(inst);
501+
return cast<AllocStackInst>(**this);
390502
case Kind::AllocBox:
391503
llvm_unreachable("Not implemented");
392504
}
@@ -397,6 +509,17 @@ struct DebugVarCarryingInst {
397509
/// DebugVarCarryingInst.
398510
static DebugVarCarryingInst getFromValue(SILValue value);
399511

512+
StringRef getName() const {
513+
assert(getKind() != Kind::Invalid);
514+
StringRef varName = "unknown";
515+
if (auto varInfo = getVarInfo()) {
516+
varName = varInfo->Name;
517+
} else if (auto *decl = getDecl()) {
518+
varName = decl->getBaseName().userFacingName();
519+
}
520+
return varName;
521+
}
522+
400523
/// Take in \p inst, a potentially invalid DebugVarCarryingInst, and returns a
401524
/// name for it. If we have an invalid value or don't find var info or a decl,
402525
/// return "unknown".
@@ -406,28 +529,35 @@ struct DebugVarCarryingInst {
406529
static StringRef getName(DebugVarCarryingInst inst) {
407530
if (!inst)
408531
return "unknown";
409-
StringRef varName = "unknown";
410-
if (auto varInfo = inst.getVarInfo()) {
411-
varName = varInfo->Name;
412-
} else if (auto *decl = inst.getDecl()) {
413-
varName = decl->getBaseName().userFacingName();
414-
}
415-
return varName;
532+
return inst.getName();
416533
}
417534
};
418535

419536
inline DebugVarCarryingInst DebugVarCarryingInst::getFromValue(SILValue value) {
420-
if (isa<AllocStackInst>(value) || isa<AllocBoxInst>(value))
421-
return DebugVarCarryingInst(cast<SingleValueInstruction>(value));
537+
if (auto *svi = dyn_cast<SingleValueInstruction>(value)) {
538+
if (auto result = VarDeclCarryingInst(svi)) {
539+
switch (result.getKind()) {
540+
case VarDeclCarryingInst::Kind::Invalid:
541+
llvm_unreachable("ShouldKind have never seen this");
542+
case VarDeclCarryingInst::Kind::DebugValue:
543+
case VarDeclCarryingInst::Kind::AllocStack:
544+
case VarDeclCarryingInst::Kind::AllocBox:
545+
return DebugVarCarryingInst(svi);
546+
case VarDeclCarryingInst::Kind::GlobalAddr:
547+
case VarDeclCarryingInst::Kind::RefElementAddr:
548+
return DebugVarCarryingInst();
549+
}
550+
}
551+
}
422552

423553
if (auto *use = getSingleDebugUse(value))
424554
return DebugVarCarryingInst(use->getUser());
425555

426556
return DebugVarCarryingInst();
427557
}
428558

429-
/// Attempt to discover a StringRef varName for the value \p value. If we fail,
430-
/// we return the name "unknown".
559+
/// Attempt to discover a StringRef varName for the value \p value based only
560+
/// off of debug var information. If we fail, we return the name "unknown".
431561
inline StringRef getDebugVarName(SILValue value) {
432562
auto inst = DebugVarCarryingInst::getFromValue(value);
433563
return DebugVarCarryingInst::getName(inst);

lib/SILOptimizer/Mandatory/ConsumeOperatorCopyableAddressesChecker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,7 +1508,7 @@ bool DataflowState::cleanupAllDestroyAddr(
15081508
dbgValueInsertBuilder.setCurrentDebugScope(
15091509
addressDebugInst->getDebugScope());
15101510
dbgValueInsertBuilder.createDebugValue(
1511-
addressDebugInst.inst->getLoc(),
1511+
(*addressDebugInst)->getLoc(),
15121512
SILUndef::get(address->getType(), dvi->getModule()), *varInfo,
15131513
false,
15141514
/*was moved*/ true);
@@ -1550,7 +1550,7 @@ bool DataflowState::cleanupAllDestroyAddr(
15501550
// be defined before the value.
15511551
SILBuilderWithScope reinitBuilder((*reinit)->getNextInstruction());
15521552
reinitBuilder.setCurrentDebugScope(addressDebugInst->getDebugScope());
1553-
reinitBuilder.createDebugValue(addressDebugInst.inst->getLoc(), address,
1553+
reinitBuilder.createDebugValue((*addressDebugInst)->getLoc(), address,
15541554
*varInfo, false,
15551555
/*was moved*/ true);
15561556
}

0 commit comments

Comments
 (0)