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
4243namespace 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
419536inline 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".
431561inline StringRef getDebugVarName (SILValue value) {
432562 auto inst = DebugVarCarryingInst::getFromValue (value);
433563 return DebugVarCarryingInst::getName (inst);
0 commit comments