Skip to content

Commit ff22da2

Browse files
committed
Debug Info: Encode let-bindings using DW_TAG_const_type.
This allows the debugger to distinguish constant "let" values from mutable "var" variables. rdar://problem/16042546
1 parent 56edd08 commit ff22da2

20 files changed

+168
-125
lines changed

lib/AST/Decl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5056,6 +5056,10 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
50565056
if (!isLet())
50575057
return supportsMutation();
50585058

5059+
// Debugger expression 'let's are initialized through a side-channel.
5060+
if (isDebuggerVar())
5061+
return false;
5062+
50595063
// We have a 'let'; we must be checking settability from a specific
50605064
// DeclContext to go on further.
50615065
if (UseDC == nullptr)

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
168168
void emitVariableDeclaration(IRBuilder &Builder,
169169
ArrayRef<llvm::Value *> Storage,
170170
DebugTypeInfo Ty, const SILDebugScope *DS,
171-
ValueDecl *VarDecl, StringRef Name,
172-
unsigned ArgNo = 0,
171+
ValueDecl *VarDecl, SILDebugVariable VarInfo,
173172
IndirectionKind = DirectValue,
174173
ArtificialKind = RealValue);
175174
void emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
@@ -2145,7 +2144,7 @@ void IRGenDebugInfoImpl::emitArtificialFunction(IRBuilder &Builder,
21452144

21462145
void IRGenDebugInfoImpl::emitVariableDeclaration(
21472146
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo DbgTy,
2148-
const SILDebugScope *DS, ValueDecl *VarDecl, StringRef Name, unsigned ArgNo,
2147+
const SILDebugScope *DS, ValueDecl *VarDecl, SILDebugVariable VarInfo,
21492148
IndirectionKind Indirection, ArtificialKind Artificial) {
21502149
assert(DS && "variable has no scope");
21512150

@@ -2165,19 +2164,21 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
21652164

21662165
// FIXME: this should be the scope of the type's declaration.
21672166
// If this is an argument, attach it to the current function scope.
2168-
if (ArgNo > 0) {
2167+
if (VarInfo.ArgNo > 0) {
21692168
while (isa<llvm::DILexicalBlock>(Scope))
21702169
Scope = cast<llvm::DILexicalBlock>(Scope)->getScope();
21712170
}
21722171
assert(Scope && isa<llvm::DIScope>(Scope) && "variable has no scope");
21732172
llvm::DIFile *Unit = getFile(Scope);
21742173
llvm::DIType *DITy = getOrCreateType(DbgTy);
21752174
assert(DITy && "could not determine debug type of variable");
2175+
if (VarInfo.Constant)
2176+
DITy = DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_const_type, DITy);
21762177

21772178
unsigned Line = Loc.Line;
21782179

21792180
// Self is always an artificial argument, so are variables without location.
2180-
if (!Line || (ArgNo > 0 && Name == IGM.Context.Id_self.str()))
2181+
if (!Line || (VarInfo.ArgNo > 0 && VarInfo.Name == IGM.Context.Id_self.str()))
21812182
Artificial = ArtificialValue;
21822183

21832184
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
@@ -2188,10 +2189,11 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
21882189
bool Optimized = false;
21892190
// Create the descriptor for the variable.
21902191
llvm::DILocalVariable *Var =
2191-
(ArgNo > 0) ? DBuilder.createParameterVariable(
2192-
Scope, Name, ArgNo, Unit, Line, DITy, Optimized, Flags)
2193-
: DBuilder.createAutoVariable(Scope, Name, Unit, Line, DITy,
2194-
Optimized, Flags);
2192+
(VarInfo.ArgNo > 0)
2193+
? DBuilder.createParameterVariable(Scope, VarInfo.Name, VarInfo.ArgNo,
2194+
Unit, Line, DITy, Optimized, Flags)
2195+
: DBuilder.createAutoVariable(Scope, VarInfo.Name, Unit, Line, DITy,
2196+
Optimized, Flags);
21952197

21962198
// Running variables for the current/previous piece.
21972199
bool IsPiece = Storage.size() > 1;
@@ -2275,16 +2277,22 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
22752277
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
22762278
return;
22772279

2278-
llvm::DIType *Ty = getOrCreateType(DbgTy);
2279-
if (Ty->isArtificial() || Ty == InternalType || !Loc)
2280+
llvm::DIType *DITy = getOrCreateType(DbgTy);
2281+
VarDecl *VD = nullptr;
2282+
if (Loc)
2283+
VD = dyn_cast_or_null<VarDecl>(Loc->getAsASTNode<Decl>());
2284+
if (!VD || VD->isLet())
2285+
DITy = DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_const_type, DITy);
2286+
2287+
if (DITy->isArtificial() || DITy == InternalType || !Loc)
22802288
// FIXME: Really these should be marked as artificial, but LLVM
22812289
// currently has no support for flags to be put on global
22822290
// variables. In the mean time, elide these variables, they
22832291
// would confuse both the user and LLDB.
22842292
return;
22852293

22862294
if (InFixedBuffer)
2287-
Ty = createFixedValueBufferStruct(Ty);
2295+
DITy = createFixedValueBufferStruct(DITy);
22882296

22892297
auto L = getStartLocation(Loc);
22902298
auto File = getOrCreateFile(L.Filename);
@@ -2294,7 +2302,7 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
22942302
if (!Var)
22952303
Expr = DBuilder.createConstantValueExpression(0);
22962304
auto *GV = DBuilder.createGlobalVariableExpression(
2297-
MainModule, Name, LinkageName, File, L.Line, Ty, IsLocalToUnit, Expr);
2305+
MainModule, Name, LinkageName, File, L.Line, DITy, IsLocalToUnit, Expr);
22982306
if (Var)
22992307
Var->addDebugInfo(GV);
23002308
}
@@ -2320,7 +2328,7 @@ void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF,
23202328
Metadata->getType(), Size(CI.getTargetInfo().getPointerWidth(0)),
23212329
Alignment(CI.getTargetInfo().getPointerAlign(0)));
23222330
emitVariableDeclaration(IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(),
2323-
nullptr, OS.str().str(), 0,
2331+
nullptr, {OS.str().str(), 0, false},
23242332
// swift.type is already a pointer type,
23252333
// having a shadow copy doesn't add another
23262334
// layer of indirection.
@@ -2419,11 +2427,10 @@ void IRGenDebugInfo::emitArtificialFunction(IRBuilder &Builder,
24192427

24202428
void IRGenDebugInfo::emitVariableDeclaration(
24212429
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo Ty,
2422-
const SILDebugScope *DS, ValueDecl *VarDecl, StringRef Name,
2423-
unsigned ArgNo, IndirectionKind Indirection,
2424-
ArtificialKind Artificial) {
2430+
const SILDebugScope *DS, ValueDecl *VarDecl, SILDebugVariable VarInfo,
2431+
IndirectionKind Indirection, ArtificialKind Artificial) {
24252432
static_cast<IRGenDebugInfoImpl *>(this)->emitVariableDeclaration(
2426-
Builder, Storage, Ty, DS, VarDecl, Name, ArgNo, Indirection, Artificial);
2433+
Builder, Storage, Ty, DS, VarDecl, VarInfo, Indirection, Artificial);
24272434
}
24282435

24292436
void IRGenDebugInfo::emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,

lib/IRGen/IRGenDebugInfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_IRGEN_DEBUGINFO_H
1818
#define SWIFT_IRGEN_DEBUGINFO_H
1919

20+
#include <swift/SIL/SILInstruction.h>
2021
#include "DebugTypeInfo.h"
2122
#include "IRGenFunction.h"
2223

@@ -133,8 +134,7 @@ class IRGenDebugInfo {
133134
void emitVariableDeclaration(IRBuilder &Builder,
134135
ArrayRef<llvm::Value *> Storage,
135136
DebugTypeInfo Ty, const SILDebugScope *DS,
136-
ValueDecl *VarDecl, StringRef Name,
137-
unsigned ArgNo = 0,
137+
ValueDecl *VarDecl, SILDebugVariable VarInfo,
138138
IndirectionKind Indirection = DirectValue,
139139
ArtificialKind Artificial = RealValue);
140140

lib/IRGen/IRGenSIL.cpp

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -761,13 +761,14 @@ class IRGenSILFunction :
761761

762762
/// Unconditionally emit a stack shadow copy of an \c llvm::Value.
763763
llvm::Value *emitShadowCopy(llvm::Value *Storage, const SILDebugScope *Scope,
764-
StringRef Name, unsigned ArgNo, Alignment Align) {
764+
SILDebugVariable VarInfo, Alignment Align) {
765765
if (Align.isZero())
766766
Align = IGM.getPointerAlignment();
767767

768-
auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, Name}}];
768+
unsigned ArgNo = VarInfo.ArgNo;
769+
auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, VarInfo.Name}}];
769770
if (!Alloca.isValid())
770-
Alloca = createAlloca(Storage->getType(), Align, Name+".debug");
771+
Alloca = createAlloca(Storage->getType(), Align, VarInfo.Name + ".debug");
771772
zeroInit(cast<llvm::AllocaInst>(Alloca.getAddress()));
772773

773774
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo.get(), Builder);
@@ -781,7 +782,7 @@ class IRGenSILFunction :
781782
/// shadow copies, we lose the precise lifetime.
782783
llvm::Value *emitShadowCopyIfNeeded(llvm::Value *Storage,
783784
const SILDebugScope *Scope,
784-
StringRef Name, unsigned ArgNo,
785+
SILDebugVariable VarInfo,
785786
bool IsAnonymous,
786787
Alignment Align = Alignment(0)) {
787788
// Never emit shadow copies when optimizing, or if already on the stack.
@@ -792,7 +793,7 @@ class IRGenSILFunction :
792793
return Storage;
793794

794795
// Always emit shadow copies for function arguments.
795-
if (ArgNo == 0)
796+
if (VarInfo.ArgNo == 0)
796797
// Otherwise only if debug value range extension is not feasible.
797798
if (!needsShadowCopy(Storage)) {
798799
// Mark for debug value range extension unless this is a constant, or
@@ -809,22 +810,22 @@ class IRGenSILFunction :
809810

810811
return Storage;
811812
}
812-
return emitShadowCopy(Storage, Scope, Name, ArgNo, Align);
813+
return emitShadowCopy(Storage, Scope, VarInfo, Align);
813814
}
814815

815816
/// Like \c emitShadowCopyIfNeeded() but takes an \c Address instead of an
816817
/// \c llvm::Value.
817818
llvm::Value *emitShadowCopyIfNeeded(Address Storage,
818819
const SILDebugScope *Scope,
819-
StringRef Name, unsigned ArgNo,
820+
SILDebugVariable VarInfo,
820821
bool IsAnonymous) {
821-
return emitShadowCopyIfNeeded(Storage.getAddress(), Scope, Name, ArgNo,
822+
return emitShadowCopyIfNeeded(Storage.getAddress(), Scope, VarInfo,
822823
IsAnonymous, Storage.getAlignment());
823824
}
824825

825826
/// Like \c emitShadowCopyIfNeeded() but takes an exploded value.
826827
void emitShadowCopyIfNeeded(SILValue &SILVal, const SILDebugScope *Scope,
827-
StringRef Name, unsigned ArgNo, bool IsAnonymous,
828+
SILDebugVariable VarInfo, bool IsAnonymous,
828829
llvm::SmallVectorImpl<llvm::Value *> &copy) {
829830
Explosion e = getLoweredExplosion(SILVal);
830831

@@ -840,13 +841,13 @@ class IRGenSILFunction :
840841
auto vals = e.claimAll();
841842
for (auto val : vals)
842843
copy.push_back(
843-
emitShadowCopyIfNeeded(val, Scope, Name, ArgNo, IsAnonymous));
844+
emitShadowCopyIfNeeded(val, Scope, VarInfo, IsAnonymous));
844845
return;
845846
}
846847

847848
SILType Type = SILVal->getType();
848849
auto &LTI = cast<LoadableTypeInfo>(IGM.getTypeInfo(Type));
849-
auto Alloca = LTI.allocateStack(*this, Type, Name+".debug");
850+
auto Alloca = LTI.allocateStack(*this, Type, VarInfo.Name + ".debug");
850851
zeroInit(cast<llvm::AllocaInst>(Alloca.getAddress().getAddress()));
851852
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo.get(), Builder);
852853
LTI.initialize(*this, e, Alloca.getAddress(), false /* isOutlined */);
@@ -867,22 +868,18 @@ class IRGenSILFunction :
867868

868869
/// Emit debug info for a function argument or a local variable.
869870
template <typename StorageType>
870-
void emitDebugVariableDeclaration(StorageType Storage,
871-
DebugTypeInfo Ty,
872-
SILType SILTy,
873-
const SILDebugScope *DS,
874-
VarDecl *VarDecl,
875-
StringRef Name,
876-
unsigned ArgNo = 0,
871+
void emitDebugVariableDeclaration(StorageType Storage, DebugTypeInfo Ty,
872+
SILType SILTy, const SILDebugScope *DS,
873+
VarDecl *VarDecl, SILDebugVariable VarInfo,
877874
IndirectionKind Indirection = DirectValue) {
878875
assert(IGM.DebugInfo && "debug info not enabled");
879-
if (ArgNo) {
876+
if (VarInfo.ArgNo) {
880877
PrologueLocation AutoRestore(IGM.DebugInfo.get(), Builder);
881878
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarDecl,
882-
Name, ArgNo, Indirection);
879+
VarInfo, Indirection);
883880
} else
884881
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarDecl,
885-
Name, 0, Indirection);
882+
VarInfo, Indirection);
886883
}
887884

888885
void emitFailBB() {
@@ -3649,17 +3646,16 @@ void IRGenSILFunction::emitErrorResultVar(SILResultInfo ErrorInfo,
36493646
auto ErrorResultSlot = getErrorResultSlot(IGM.silConv.getSILType(ErrorInfo));
36503647
auto Var = DbgValue->getVarInfo();
36513648
assert(Var && "error result without debug info");
3652-
auto Storage =
3653-
emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(), getDebugScope(),
3654-
Var->Name, Var->ArgNo, false);
3649+
auto Storage = emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(),
3650+
getDebugScope(), *Var, false);
36553651
if (!IGM.DebugInfo)
36563652
return;
36573653
auto DbgTy = DebugTypeInfo::getErrorResult(
36583654
ErrorInfo.getType(), ErrorResultSlot->getType(), IGM.getPointerSize(),
36593655
IGM.getPointerAlignment());
3660-
IGM.DebugInfo->emitVariableDeclaration(
3661-
Builder, Storage, DbgTy, getDebugScope(), nullptr, Var->Name, Var->ArgNo,
3662-
IndirectValue, ArtificialValue);
3656+
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, DbgTy,
3657+
getDebugScope(), nullptr, *Var,
3658+
IndirectValue, ArtificialValue);
36633659
}
36643660

36653661
void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
@@ -3680,30 +3676,30 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
36803676
}
36813677

36823678
bool IsAnonymous = false;
3683-
StringRef Name = getVarName(i, IsAnonymous);
3679+
VarInfo->Name = getVarName(i, IsAnonymous);
36843680
DebugTypeInfo DbgTy;
36853681
SILType SILTy = SILVal->getType();
36863682
auto RealTy = SILVal->getType().getASTType();
36873683
if (VarDecl *Decl = i->getDecl()) {
36883684
DbgTy = DebugTypeInfo::getLocalVariable(
36893685
Decl, RealTy, getTypeInfo(SILVal->getType()));
36903686
} else if (i->getFunction()->isBare() &&
3691-
!SILTy.hasArchetype() && !Name.empty()) {
3687+
!SILTy.hasArchetype() && !VarInfo->Name.empty()) {
36923688
// Preliminary support for .sil debug information.
36933689
DbgTy = DebugTypeInfo::getFromTypeInfo(RealTy, getTypeInfo(SILTy));
36943690
} else
36953691
return;
36963692

36973693
// Put the value into a stack slot at -Onone.
36983694
llvm::SmallVector<llvm::Value *, 8> Copy;
3699-
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), Name, VarInfo->ArgNo,
3700-
IsAnonymous, Copy);
3695+
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), *VarInfo, IsAnonymous,
3696+
Copy);
37013697
bindArchetypes(DbgTy.getType());
37023698
if (!IGM.DebugInfo)
37033699
return;
37043700

37053701
emitDebugVariableDeclaration(Copy, DbgTy, SILTy, i->getDebugScope(),
3706-
i->getDecl(), Name, VarInfo->ArgNo);
3702+
i->getDecl(), *VarInfo);
37073703
}
37083704

37093705
void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
@@ -3722,7 +3718,7 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
37223718
assert(VarInfo && "debug_value_addr without debug info");
37233719
bool IsAnonymous = false;
37243720
bool IsLoadablyByAddress = isa<AllocStackInst>(SILVal);
3725-
StringRef Name = getVarName(i, IsAnonymous);
3721+
VarInfo->Name = getVarName(i, IsAnonymous);
37263722
auto Addr = getLoweredAddress(SILVal).getAddress();
37273723
SILType SILTy = SILVal->getType();
37283724
auto RealType = SILTy.getASTType();
@@ -3736,9 +3732,8 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
37363732
// Put the value's address into a stack slot at -Onone and emit a debug
37373733
// intrinsic.
37383734
emitDebugVariableDeclaration(
3739-
emitShadowCopyIfNeeded(Addr, i->getDebugScope(), Name, VarInfo->ArgNo,
3740-
IsAnonymous),
3741-
DbgTy, SILType(), i->getDebugScope(), Decl, Name, VarInfo->ArgNo,
3735+
emitShadowCopyIfNeeded(Addr, i->getDebugScope(), *VarInfo, IsAnonymous),
3736+
DbgTy, SILType(), i->getDebugScope(), Decl, *VarInfo,
37423737
(IsLoadablyByAddress) ? DirectValue : IndirectValue);
37433738
}
37443739

@@ -4001,7 +3996,7 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
40013996
return;
40023997

40033998
bool IsAnonymous = false;
4004-
StringRef Name = getVarName(i, IsAnonymous);
3999+
VarInfo->Name = getVarName(i, IsAnonymous);
40054000

40064001
// At this point addr must be an alloca or an undef.
40074002
assert(isa<llvm::AllocaInst>(addr) || isa<llvm::UndefValue>(addr) ||
@@ -4012,8 +4007,7 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
40124007
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(addr))
40134008
if (!Alloca->isStaticAlloca()) {
40144009
// Store the address of the dynamic alloca on the stack.
4015-
addr = emitShadowCopy(addr, DS, Name, VarInfo->ArgNo,
4016-
IGM.getPointerAlignment());
4010+
addr = emitShadowCopy(addr, DS, *VarInfo, IGM.getPointerAlignment());
40174011
Indirection = IndirectValue;
40184012
}
40194013

@@ -4032,8 +4026,8 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
40324026

40334027
bindArchetypes(DbgTy.getType());
40344028
if (IGM.DebugInfo)
4035-
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, Name,
4036-
VarInfo->ArgNo, Indirection);
4029+
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, *VarInfo,
4030+
Indirection);
40374031
}
40384032

40394033
void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
@@ -4233,16 +4227,18 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) {
42334227
auto RealType = SILTy.getASTType();
42344228
auto DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type);
42354229

4230+
auto VarInfo = i->getVarInfo();
4231+
assert(VarInfo && "debug_value without debug info");
4232+
42364233
auto Storage = emitShadowCopyIfNeeded(
4237-
boxWithAddr.getAddress(), i->getDebugScope(), Name, 0, IsAnonymous);
4234+
boxWithAddr.getAddress(), i->getDebugScope(), *VarInfo, IsAnonymous);
42384235

42394236
if (!IGM.DebugInfo)
42404237
return;
42414238

4242-
IGM.DebugInfo->emitVariableDeclaration(
4243-
Builder,
4244-
Storage,
4245-
DbgTy, i->getDebugScope(), Decl, Name, 0, IndirectValue);
4239+
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, DbgTy,
4240+
i->getDebugScope(), Decl, *VarInfo,
4241+
IndirectValue);
42464242
}
42474243

42484244
void IRGenSILFunction::visitProjectBoxInst(swift::ProjectBoxInst *i) {

0 commit comments

Comments
 (0)