37
37
#define SWIFT_SIL_DEBUGUTILS_H
38
38
39
39
#include " swift/SIL/SILBasicBlock.h"
40
+ #include " swift/SIL/SILGlobalVariable.h"
40
41
#include " swift/SIL/SILInstruction.h"
41
42
42
43
namespace swift {
@@ -237,31 +238,39 @@ bool hasNonTrivialNonDebugTransitiveUsers(
237
238
PointerUnion<SILInstruction *, SILArgument *> V);
238
239
239
240
// / 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:
246
247
enum class Kind : uint8_t {
247
248
Invalid = 0 ,
248
249
DebugValue,
249
250
AllocStack,
250
251
AllocBox,
252
+ GlobalAddr,
253
+ RefElementAddr,
251
254
};
252
255
256
+ protected:
253
257
SILInstruction *inst;
254
258
Kind kind;
255
259
uintptr_t spareBits : (sizeof (uintptr_t ) - sizeof (Kind)) * 8 ;
256
260
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)
259
264
: inst(dvi), kind(Kind::DebugValue), spareBits(0 ) {}
260
- DebugVarCarryingInst (AllocStackInst *asi)
265
+ VarDeclCarryingInst (AllocStackInst *asi)
261
266
: inst(asi), kind(Kind::AllocStack), spareBits(0 ) {}
262
- DebugVarCarryingInst (AllocBoxInst *abi)
267
+ VarDeclCarryingInst (AllocBoxInst *abi)
263
268
: 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)
265
274
: inst(nullptr ), kind(Kind::Invalid), spareBits(0 ) {
266
275
switch (newInst->getKind ()) {
267
276
default :
@@ -275,6 +284,12 @@ struct DebugVarCarryingInst {
275
284
case SILInstructionKind::AllocBoxInst:
276
285
kind = Kind::AllocBox;
277
286
break ;
287
+ case SILInstructionKind::GlobalAddrInst:
288
+ kind = Kind::GlobalAddr;
289
+ break ;
290
+ case SILInstructionKind::RefElementAddrInst:
291
+ kind = Kind::RefElementAddr;
292
+ break ;
278
293
}
279
294
inst = newInst;
280
295
}
@@ -288,18 +303,23 @@ struct DebugVarCarryingInst {
288
303
// / '->'. This keeps the wrapper light weight.
289
304
SILInstruction *operator ->() const { return inst; }
290
305
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 {
292
310
return kind == other.kind && inst == other.inst &&
293
311
spareBits == other.spareBits ;
294
312
}
295
313
296
- bool operator !=(const DebugVarCarryingInst &other) const {
314
+ bool operator !=(const VarDeclCarryingInst &other) const {
297
315
return !(*this == other);
298
316
}
299
317
300
318
// / Add support for this struct in `if` statement.
301
319
explicit operator bool () const { return bool (kind); }
302
320
321
+ Kind getKind () const { return kind; }
322
+
303
323
VarDecl *getDecl () const {
304
324
switch (kind) {
305
325
case Kind::Invalid:
@@ -310,48 +330,140 @@ struct DebugVarCarryingInst {
310
330
return cast<AllocStackInst>(inst)->getDecl ();
311
331
case Kind::AllocBox:
312
332
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 ();
313
337
}
314
338
llvm_unreachable (" covered switch" );
315
339
}
316
340
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
+
317
429
Optional<SILDebugVariable> getVarInfo () const {
318
- switch (kind ) {
430
+ switch (getKind () ) {
319
431
case Kind::Invalid:
320
432
llvm_unreachable (" Invalid?!" );
321
433
case Kind::DebugValue:
322
- return cast<DebugValueInst>(inst )->getVarInfo ();
434
+ return cast<DebugValueInst>(** this )->getVarInfo ();
323
435
case Kind::AllocStack:
324
- return cast<AllocStackInst>(inst )->getVarInfo ();
436
+ return cast<AllocStackInst>(** this )->getVarInfo ();
325
437
case Kind::AllocBox:
326
- return cast<AllocBoxInst>(inst )->getVarInfo ();
438
+ return cast<AllocBoxInst>(** this )->getVarInfo ();
327
439
}
328
440
llvm_unreachable (" covered switch" );
329
441
}
330
442
331
443
void setDebugVarScope (const SILDebugScope *NewDS) {
332
- switch (kind ) {
444
+ switch (getKind () ) {
333
445
case Kind::Invalid:
334
446
llvm_unreachable (" Invalid?!" );
335
447
case Kind::DebugValue:
336
- cast<DebugValueInst>(inst )->setDebugVarScope (NewDS);
448
+ cast<DebugValueInst>(** this )->setDebugVarScope (NewDS);
337
449
break ;
338
450
case Kind::AllocStack:
339
- cast<AllocStackInst>(inst )->setDebugVarScope (NewDS);
451
+ cast<AllocStackInst>(** this )->setDebugVarScope (NewDS);
340
452
break ;
341
453
case Kind::AllocBox:
342
454
llvm_unreachable (" Not implemented" );
343
455
}
344
456
}
345
457
346
458
void markAsMoved () {
347
- switch (kind ) {
459
+ switch (getKind () ) {
348
460
case Kind::Invalid:
349
461
llvm_unreachable (" Invalid?!" );
350
462
case Kind::DebugValue:
351
- cast<DebugValueInst>(inst )->markAsMoved ();
463
+ cast<DebugValueInst>(** this )->markAsMoved ();
352
464
break ;
353
465
case Kind::AllocStack:
354
- cast<AllocStackInst>(inst )->markAsMoved ();
466
+ cast<AllocStackInst>(** this )->markAsMoved ();
355
467
break ;
356
468
case Kind::AllocBox:
357
469
llvm_unreachable (" Not implemented" );
@@ -360,13 +472,13 @@ struct DebugVarCarryingInst {
360
472
361
473
// / Returns true if this DebugVarCarryingInst was moved.
362
474
bool getWasMoved () const {
363
- switch (kind ) {
475
+ switch (getKind () ) {
364
476
case Kind::Invalid:
365
477
llvm_unreachable (" Invalid?!" );
366
478
case Kind::DebugValue:
367
- return cast<DebugValueInst>(inst )->getWasMoved ();
479
+ return cast<DebugValueInst>(** this )->getWasMoved ();
368
480
case Kind::AllocStack:
369
- return cast<AllocStackInst>(inst )->getWasMoved ();
481
+ return cast<AllocStackInst>(** this )->getWasMoved ();
370
482
case Kind::AllocBox:
371
483
// We do not support moving alloc box today, so we always return false.
372
484
return false ;
@@ -380,13 +492,13 @@ struct DebugVarCarryingInst {
380
492
// / For a debug_value, we just return the actual operand, otherwise we return
381
493
// / the pointer address.
382
494
SILValue getOperandForDebugValueClone () const {
383
- switch (kind ) {
495
+ switch (getKind () ) {
384
496
case Kind::Invalid:
385
497
llvm_unreachable (" Invalid?!" );
386
498
case Kind::DebugValue:
387
- return cast<DebugValueInst>(inst )->getOperand ();
499
+ return cast<DebugValueInst>(** this )->getOperand ();
388
500
case Kind::AllocStack:
389
- return cast<AllocStackInst>(inst );
501
+ return cast<AllocStackInst>(** this );
390
502
case Kind::AllocBox:
391
503
llvm_unreachable (" Not implemented" );
392
504
}
@@ -397,6 +509,17 @@ struct DebugVarCarryingInst {
397
509
// / DebugVarCarryingInst.
398
510
static DebugVarCarryingInst getFromValue (SILValue value);
399
511
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
+
400
523
// / Take in \p inst, a potentially invalid DebugVarCarryingInst, and returns a
401
524
// / name for it. If we have an invalid value or don't find var info or a decl,
402
525
// / return "unknown".
@@ -406,28 +529,35 @@ struct DebugVarCarryingInst {
406
529
static StringRef getName (DebugVarCarryingInst inst) {
407
530
if (!inst)
408
531
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 ();
416
533
}
417
534
};
418
535
419
536
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
+ }
422
552
423
553
if (auto *use = getSingleDebugUse (value))
424
554
return DebugVarCarryingInst (use->getUser ());
425
555
426
556
return DebugVarCarryingInst ();
427
557
}
428
558
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".
431
561
inline StringRef getDebugVarName (SILValue value) {
432
562
auto inst = DebugVarCarryingInst::getFromValue (value);
433
563
return DebugVarCarryingInst::getName (inst);
0 commit comments