Skip to content

Commit ef84c81

Browse files
committed
Debug Info: Assign unique names to anonymous variables and arguments.
rdar://problem/18139663
1 parent fd6e8a9 commit ef84c81

File tree

3 files changed

+60
-44
lines changed

3 files changed

+60
-44
lines changed

lib/IRGen/IRGenSIL.cpp

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ class IRGenSILFunction :
295295
/// Keeps track of the mapping of source variables to -O0 shadow copy allocas.
296296
llvm::SmallDenseMap<std::pair<const SILDebugScope *, StringRef>, Address, 8>
297297
ShadowStackSlots;
298+
llvm::SmallDenseMap<Decl *, SmallString<4>, 8> AnonymousVariables;
299+
unsigned NumAnonVars = 0;
298300

299301
/// Accumulative amount of allocated bytes on the stack. Used to limit the
300302
/// size for stack promoted objects.
@@ -481,6 +483,26 @@ class IRGenSILFunction :
481483
return foundBB->second;
482484
}
483485

486+
StringRef getOrCreateAnonymousVarName(VarDecl *Decl) {
487+
llvm::SmallString<4> &Name = AnonymousVariables[Decl];
488+
if (Name.empty()) {
489+
{
490+
llvm::raw_svector_ostream S(Name);
491+
S << '_' << NumAnonVars++;
492+
}
493+
AnonymousVariables.insert({Decl, Name});
494+
}
495+
return Name;
496+
}
497+
498+
template <class DebugVarCarryingInst>
499+
StringRef getVarName(DebugVarCarryingInst *i) {
500+
StringRef Name = i->getVarInfo().Name;
501+
if (Name.empty() && i->getDecl())
502+
return getOrCreateAnonymousVarName(i->getDecl());
503+
return Name;
504+
}
505+
484506
/// At -O0, emit a shadow copy of an Address in an alloca, so the
485507
/// register allocator doesn't elide the dbg.value intrinsic when
486508
/// register pressure is high. There is a trade-off to this: With
@@ -587,6 +609,8 @@ class IRGenSILFunction :
587609

588610
void emitFunctionArgDebugInfo(SILBasicBlock *BB);
589611

612+
void emitDebugInfoForAllocStack(AllocStackInst *i, const TypeInfo &type,
613+
llvm::Value *addr);
590614
void visitAllocStackInst(AllocStackInst *i);
591615
void visitAllocRefInst(AllocRefInst *i);
592616
void visitAllocRefDynamicInst(AllocRefDynamicInst *i);
@@ -2949,7 +2973,7 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
29492973
if (isa<SILUndef>(SILVal))
29502974
return;
29512975

2952-
StringRef Name = i->getVarInfo().Name;
2976+
StringRef Name = getVarName(i);
29532977
DebugTypeInfo DbgTy;
29542978
SILType SILTy = SILVal.getType();
29552979
if (VarDecl *Decl = i->getDecl())
@@ -2983,7 +3007,7 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
29833007
if (isa<SILUndef>(SILVal))
29843008
return;
29853009

2986-
StringRef Name = i->getVarInfo().Name;
3010+
StringRef Name = getVarName(i);
29873011
auto Addr = getLoweredAddress(SILVal).getAddress();
29883012
DebugTypeInfo DbgTy(Decl, Decl->getType(), getTypeInfo(SILVal.getType()));
29893013
// Put the value into a stack slot at -Onone and emit a debug intrinsic.
@@ -3231,25 +3255,23 @@ static bool tryDeferFixedSizeBufferInitialization(IRGenSILFunction &IGF,
32313255
return false;
32323256
}
32333257

3234-
static void emitDebugDeclarationForAllocStack(IRGenSILFunction &IGF,
3235-
AllocStackInst *i,
3236-
const TypeInfo &type,
3237-
llvm::Value *addr) {
3258+
void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
3259+
const TypeInfo &type,
3260+
llvm::Value *addr) {
32383261
VarDecl *Decl = i->getDecl();
3239-
if (IGF.IGM.DebugInfo && Decl) {
3262+
if (IGM.DebugInfo && Decl) {
32403263
auto *Pattern = Decl->getParentPattern();
32413264
if (!Pattern || !Pattern->isImplicit()) {
32423265
auto DbgTy = DebugTypeInfo(Decl, type);
32433266
// Discard any inout or lvalue qualifiers. Since the object itself
32443267
// is stored in the alloca, emitting it as a reference type would
32453268
// be wrong.
32463269
DbgTy.unwrapLValueOrInOutType();
3247-
auto Name = i->getVarInfo().Name.empty() ? "_" : i->getVarInfo().Name;
3248-
auto DS = i->getDebugScope();
3249-
if (DS) {
3250-
assert(DS->SILFn == IGF.CurSILFn || DS->InlinedCallSite);
3251-
IGF.emitDebugVariableDeclaration(addr, DbgTy, DS, Name,
3252-
i->getVarInfo().ArgNo);
3270+
StringRef Name = getVarName(i);
3271+
if (auto DS = i->getDebugScope()) {
3272+
assert(DS->SILFn == CurSILFn || DS->InlinedCallSite);
3273+
emitDebugVariableDeclaration(addr, DbgTy, DS, Name,
3274+
i->getVarInfo().ArgNo);
32533275
}
32543276
}
32553277
}
@@ -3263,7 +3285,7 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
32633285
StringRef dbgname;
32643286
# ifndef NDEBUG
32653287
// If this is a DEBUG build, use pretty names for the LLVM IR.
3266-
dbgname = i->getVarInfo().Name;
3288+
dbgname = getVarName(i);
32673289
# endif
32683290

32693291
(void) Decl;
@@ -3280,10 +3302,8 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
32803302
auto addr = type.allocateStack(*this,
32813303
i->getElementType(),
32823304
dbgname);
3283-
3284-
emitDebugDeclarationForAllocStack(*this, i, type,
3285-
addr.getAddress().getAddress());
3286-
3305+
3306+
emitDebugInfoForAllocStack(i, type, addr.getAddress().getAddress());
32873307
setLoweredAddress(i->getContainerResult(), addr.getContainer());
32883308
setLoweredAddress(i->getAddressResult(), addr.getAddress());
32893309
}
@@ -3377,7 +3397,7 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) {
33773397

33783398
// Derive name from SIL location.
33793399
VarDecl *Decl = i->getDecl();
3380-
StringRef Name = i->getVarInfo().Name;
3400+
StringRef Name = getVarName(i);
33813401
StringRef DbgName =
33823402
# ifndef NDEBUG
33833403
// If this is a DEBUG build, use pretty names for the LLVM IR.
@@ -4332,15 +4352,15 @@ void IRGenSILFunction::visitWitnessMethodInst(swift::WitnessMethodInst *i) {
43324352

43334353
void IRGenSILFunction::setAllocatedAddressForBuffer(SILValue v,
43344354
const Address &allocedAddress) {
4335-
assert(getLoweredValue(v).kind == LoweredValue::Kind::UnallocatedAddressInBuffer
4336-
&& "not an unallocated address");
4337-
4355+
assert(getLoweredValue(v).kind ==
4356+
LoweredValue::Kind::UnallocatedAddressInBuffer &&
4357+
"not an unallocated address");
4358+
43384359
overwriteLoweredAddress(v, allocedAddress);
43394360
// Emit the debug info for the variable if any.
43404361
if (auto allocStack = dyn_cast<AllocStackInst>(v)) {
4341-
emitDebugDeclarationForAllocStack(*this, allocStack,
4342-
getTypeInfo(v.getType()),
4343-
allocedAddress.getAddress());
4362+
emitDebugInfoForAllocStack(allocStack, getTypeInfo(v.getType()),
4363+
allocedAddress.getAddress());
43444364
}
43454365
}
43464366

lib/SILGen/SILGenProlog.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,17 @@ struct ArgumentInitVisitor :
324324
++ArgNo;
325325
auto PD = P->getDecl();
326326
if (!PD->hasName()) {
327+
ManagedValue argrv = makeArgument(P->getType(), &*f.begin(), PD);
328+
// Emit debug information for the argument.
329+
SILLocation loc(PD);
330+
loc.markAsPrologue();
331+
if (argrv.getType().isAddress())
332+
gen.B.createDebugValueAddr(loc, argrv.getValue(), {PD->isLet(), ArgNo});
333+
else
334+
gen.B.createDebugValue(loc, argrv.getValue(), {PD->isLet(), ArgNo});
335+
327336
// A value bound to _ is unused and can be immediately released.
328337
Scope discardScope(gen.Cleanups, CleanupLocation(P));
329-
makeArgument(P->getType(), &*f.begin(), PD);
330338
// Popping the scope destroys the value.
331339
} else {
332340
makeArgumentIntoBinding(P->getType(), &*f.begin(), PD);

test/DebugInfo/anonymous.swift

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,10 @@
11
// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | FileCheck %s
22

3-
// Don't crash when emitting debug info for anonymous variables.
4-
// CHECK: !DILocalVariable(name: "_"
3+
// CHECK: !DILocalVariable(name: "_0", arg: 1
4+
// CHECK: !DILocalVariable(name: "_1", arg: 2
5+
// CHECK: !DILocalVariable(name: "_2", arg: 3
6+
// CHECK: !DILocalVariable(name: "x4", arg: 4
57

6-
func markUsed<T>(t: T) {}
7-
8-
protocol F_ {
9-
func successor() -> Self
10-
}
11-
12-
protocol F : F_ {
13-
func ~> (_: Self, _: (_Distance, (Self))) -> Int64
14-
}
15-
16-
struct _Distance {}
17-
18-
func ~> <I: F_>(self_:I, _: (_Distance, (I))) -> Int64 {
19-
self_.successor()
20-
markUsed("F")
21-
return 0
8+
public func fourth<T>(_: T, _: T, _: T, x4 : T) -> T {
9+
return x4
2210
}

0 commit comments

Comments
 (0)