Skip to content

Commit 2c7a698

Browse files
committed
Emits a DW_OP_deref for global variables in a fixed size buffer.
Note that this is only correct unless the variable uses inline storage. This makes the majority of resilient types in Foundation work as global variables. The correct solution would be for LLDB to poke at the runtime to figure out whether the storage is inline or not, but until then this is the next best thing. rdar://problem/39722386
1 parent 3a99f3b commit 2c7a698

File tree

6 files changed

+73
-36
lines changed

6 files changed

+73
-36
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,7 +1943,7 @@ bool LinkInfo::isUsed(llvm::GlobalValue::LinkageTypes Linkage,
19431943
llvm::GlobalVariable *swift::irgen::createVariable(
19441944
IRGenModule &IGM, LinkInfo &linkInfo, llvm::Type *storageType,
19451945
Alignment alignment, DebugTypeInfo DbgTy, Optional<SILLocation> DebugLoc,
1946-
StringRef DebugName) {
1946+
StringRef DebugName, bool inFixedBuffer) {
19471947
auto name = linkInfo.getName();
19481948
llvm::GlobalValue *existingValue = IGM.Module.getNamedGlobal(name);
19491949
if (existingValue) {
@@ -1975,7 +1975,7 @@ llvm::GlobalVariable *swift::irgen::createVariable(
19751975
if (IGM.DebugInfo && !DbgTy.isNull() && linkInfo.isForDefinition())
19761976
IGM.DebugInfo->emitGlobalVariableDeclaration(
19771977
var, DebugName.empty() ? name : DebugName, name, DbgTy,
1978-
var->hasInternalLinkage(), DebugLoc);
1978+
var->hasInternalLinkage(), inFixedBuffer, DebugLoc);
19791979

19801980
return var;
19811981
}
@@ -2111,6 +2111,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
21112111
llvm::Type *storageType;
21122112
Size fixedSize;
21132113
Alignment fixedAlignment;
2114+
bool inFixedBuffer = false;
21142115

21152116
if (var->isInitializedObject()) {
21162117
assert(ti.isFixedSize(expansion));
@@ -2140,6 +2141,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
21402141
} else {
21412142
// Allocate a fixed-size buffer and possibly heap-allocate a payload at
21422143
// runtime if the runtime size of the type does not fit in the buffer.
2144+
inFixedBuffer = true;
21432145
storageType = getFixedBufferTy();
21442146
fixedSize = Size(DataLayout.getTypeAllocSize(storageType));
21452147
fixedAlignment = Alignment(DataLayout.getABITypeAlignment(storageType));
@@ -2170,20 +2172,21 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
21702172
gvar = createVariable(*this, link, storageTypeWithContainer,
21712173
fixedAlignment);
21722174
} else {
2173-
auto DbgTy = DebugTypeInfo::getGlobal(var, storageTypeWithContainer,
2174-
fixedSize, fixedAlignment);
2175+
StringRef name;
2176+
Optional<SILLocation> loc;
21752177
if (var->getDecl()) {
2176-
// If we have the VarDecl, use it for more accurate debugging information.
2177-
gvar = createVariable(*this, link, storageTypeWithContainer,
2178-
fixedAlignment, DbgTy, SILLocation(var->getDecl()),
2179-
var->getDecl()->getName().str());
2178+
// Use the VarDecl for more accurate debugging information.
2179+
loc = var->getDecl();
2180+
name = var->getDecl()->getName().str();
21802181
} else {
2181-
Optional<SILLocation> loc;
21822182
if (var->hasLocation())
21832183
loc = var->getLocation();
2184-
gvar = createVariable(*this, link, storageTypeWithContainer,
2185-
fixedAlignment, DbgTy, loc, var->getName());
2184+
name = var->getName();
21862185
}
2186+
auto DbgTy = DebugTypeInfo::getGlobal(var, storageTypeWithContainer,
2187+
fixedSize, fixedAlignment);
2188+
gvar = createVariable(*this, link, storageTypeWithContainer,
2189+
fixedAlignment, DbgTy, loc, name, inFixedBuffer);
21872190
}
21882191
/// Add a zero initializer.
21892192
if (forDefinition)

lib/IRGen/GenDecl.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,11 @@ namespace irgen {
4646
OptimizationMode FuncOptMode =
4747
OptimizationMode::NotSet);
4848

49-
llvm::GlobalVariable *createVariable(IRGenModule &IGM,
50-
LinkInfo &linkInfo,
51-
llvm::Type *objectType,
52-
Alignment alignment,
53-
DebugTypeInfo DebugType=DebugTypeInfo(),
54-
Optional<SILLocation> DebugLoc = None,
55-
StringRef DebugName = StringRef());
49+
llvm::GlobalVariable *
50+
createVariable(IRGenModule &IGM, LinkInfo &linkInfo, llvm::Type *objectType,
51+
Alignment alignment, DebugTypeInfo DebugType = DebugTypeInfo(),
52+
Optional<SILLocation> DebugLoc = None,
53+
StringRef DebugName = StringRef(), bool heapAllocated = false);
5654

5755
void disableAddressSanitizer(IRGenModule &IGM, llvm::GlobalVariable *var);
5856
}

lib/IRGen/GenInit.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ void IRGenModule::emitSILGlobalVariable(SILGlobalVariable *var) {
4545
auto DbgTy = DebugTypeInfo::getGlobal(var, Int8Ty, Size(0), Alignment(1));
4646
DebugInfo->emitGlobalVariableDeclaration(
4747
nullptr, var->getDecl()->getName().str(), "", DbgTy,
48-
var->getLinkage() != SILLinkage::Public, SILLocation(var->getDecl()));
48+
var->getLinkage() != SILLinkage::Public,
49+
IRGenDebugInfo::NotHeapAllocated, SILLocation(var->getDecl()));
4950
}
5051
return;
5152
}

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
154154
void emitGlobalVariableDeclaration(llvm::GlobalVariable *Storage,
155155
StringRef Name, StringRef LinkageName,
156156
DebugTypeInfo DebugType,
157-
bool IsLocalToUnit,
157+
bool IsLocalToUnit, bool InFixedBuffer,
158158
Optional<SILLocation> Loc);
159159
void emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata,
160160
StringRef Name);
@@ -1989,7 +1989,8 @@ void IRGenDebugInfoImpl::emitDbgIntrinsic(
19891989

19901990
void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
19911991
llvm::GlobalVariable *Var, StringRef Name, StringRef LinkageName,
1992-
DebugTypeInfo DbgTy, bool IsLocalToUnit, Optional<SILLocation> Loc) {
1992+
DebugTypeInfo DbgTy, bool IsLocalToUnit, bool InFixedBuffer,
1993+
Optional<SILLocation> Loc) {
19931994
if (Opts.DebugInfoKind <= IRGenDebugInfoKind::LineTables)
19941995
return;
19951996

@@ -2005,7 +2006,16 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
20052006
auto File = getOrCreateFile(L.Filename);
20062007

20072008
// Emit it as global variable of the current module.
2008-
auto *Expr = Var ? nullptr : DBuilder.createConstantValueExpression(0);
2009+
llvm::DIExpression *Expr = nullptr;
2010+
if (!Var)
2011+
Expr = DBuilder.createConstantValueExpression(0);
2012+
else if (InFixedBuffer)
2013+
// FIXME: This is *not* generally correct, but LLDB at the moment cannot
2014+
// poke to runtime to figure out whether a resilient value has inline
2015+
// storage, so this is assuming that it doesn't to get the majority of
2016+
// resilient Foundation types.
2017+
Expr =
2018+
DBuilder.createExpression(ArrayRef<uint64_t>(llvm::dwarf::DW_OP_deref));
20092019
auto *GV = DBuilder.createGlobalVariableExpression(
20102020
MainModule, Name, LinkageName, File, L.Line, Ty, IsLocalToUnit, Expr);
20112021
if (Var)
@@ -2129,9 +2139,10 @@ void IRGenDebugInfo::emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
21292139

21302140
void IRGenDebugInfo::emitGlobalVariableDeclaration(
21312141
llvm::GlobalVariable *Storage, StringRef Name, StringRef LinkageName,
2132-
DebugTypeInfo DebugType, bool IsLocalToUnit, Optional<SILLocation> Loc) {
2142+
DebugTypeInfo DebugType, bool IsLocalToUnit, bool InFixedBuffer,
2143+
Optional<SILLocation> Loc) {
21332144
static_cast<IRGenDebugInfoImpl *>(this)->emitGlobalVariableDeclaration(
2134-
Storage, Name, LinkageName, DebugType, IsLocalToUnit, Loc);
2145+
Storage, Name, LinkageName, DebugType, IsLocalToUnit, InFixedBuffer, Loc);
21352146
}
21362147

21372148
void IRGenDebugInfo::emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata,

lib/IRGen/IRGenDebugInfo.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,13 @@ class IRGenDebugInfo {
136136
unsigned Line, unsigned Col, llvm::DILocalScope *Scope,
137137
const SILDebugScope *DS);
138138

139+
enum { NotHeapAllocated = false };
140+
139141
/// Create debug metadata for a global variable.
140142
void emitGlobalVariableDeclaration(llvm::GlobalVariable *Storage,
141143
StringRef Name, StringRef LinkageName,
142144
DebugTypeInfo DebugType,
143-
bool IsLocalToUnit,
145+
bool IsLocalToUnit, bool InFixedBuffer,
144146
Optional<SILLocation> Loc);
145147

146148
/// Emit debug metadata for type metadata (for generic types). So meta.

test/DebugInfo/resilience.swift

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,25 @@
1313
// RUN: -enable-resilience-bypass | %FileCheck %s --check-prefix=CHECK-LLDB
1414
import resilient_struct
1515

16-
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S10resilience1fyyF"()
17-
// CHECK-LLDB-LABEL: define{{( protected)?}} swiftcc void @"$S10resilience1fyyF"()
18-
public func f() {
16+
let fixed = Point(x: 1, y: 2)
17+
let non_fixed = Size(w: 1, h: 2)
18+
let int = ResilientInt(i: 1)
19+
// CHECK: @"$S10resilience5fixed16resilient_struct5PointVvp" =
20+
// CHECK-SAME: !dbg ![[FIXED:[0-9]+]]
21+
// CHECK: @"$S10resilience9non_fixed16resilient_struct4SizeVvp" =
22+
// CHECK-SAME: !dbg ![[NON_FIXED:[0-9]+]]
23+
// CHECK: @"$S10resilience3int16resilient_struct12ResilientIntVvp" =
24+
// CHECK-SAME: !dbg ![[INT:[0-9]+]]
25+
// CHECK-LABEL: define{{.*}}main
26+
27+
// CHECK-LABEL: define{{.*}} swiftcc void @"$S10resilience9takesSizeyy16resilient_struct0C0VF"(%swift.opaque* noalias nocapture)
28+
// CHECK-LLDB-LABEL: define{{.*}} swiftcc void @"$S10resilience9takesSizeyy16resilient_struct0C0VF"(%T16resilient_struct4SizeV* noalias nocapture dereferenceable({{8|16}}))
29+
public func takesSize(_ s: Size) {}
30+
31+
32+
// CHECK-LABEL: define{{.*}} swiftcc void @"$S10resilience1fyyF"()
33+
// CHECK-LLDB-LABEL: define{{.*}} swiftcc void @"$S10resilience1fyyF"()
34+
func f() {
1935
let s1 = Size(w: 1, h: 2)
2036
takesSize(s1)
2137
// CHECK: %[[ADDR:.*]] = alloca i8*
@@ -30,15 +46,21 @@ public func f() {
3046
// CHECK-LLDB-SAME: metadata ![[V1:[0-9]+]],
3147
// CHECK-LLDB-SAME: metadata !DIExpression())
3248
}
49+
f()
3350

51+
// Note that these DW_OP_deref are not necessarily correct, but it's the best
52+
// approxmiation we have until LLDB can query the runtime for whether a relient
53+
// type's storage is inline or not.
54+
// CHECK: ![[FIXED]] = !DIGlobalVariableExpression(
55+
// CHECK-SAME: expr: !DIExpression())
56+
// CHECK: ![[NON_FIXED]] = !DIGlobalVariableExpression(
57+
// CHECK-SAME: expr: !DIExpression(DW_OP_deref))
58+
// CHECK: ![[TY:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Size",
59+
// CHECK: ![[INT]] = !DIGlobalVariableExpression(
60+
// CHECK-SAME: expr: !DIExpression(DW_OP_deref))
3461

35-
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S10resilience9takesSizeyy16resilient_struct0C0VF"(%swift.opaque* noalias nocapture)
36-
// CHECK-LLDB-LABEL: define{{( protected)?}} swiftcc void @"$S10resilience9takesSizeyy16resilient_struct0C0VF"(%T16resilient_struct4SizeV* noalias nocapture dereferenceable({{8|16}}))
37-
public func takesSize(_ s: Size) {}
38-
62+
// CHECK: ![[V1]] = !DILocalVariable(name: "s1", {{.*}}type: ![[TY]])
3963

40-
// CHECK: ![[V1]] = !DILocalVariable(name: "s1", {{.*}}type: ![[TY:[0-9]+]])
41-
// CHECK: ![[TY]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Size",
64+
// CHECK-LLDB: ![[TY:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Size",
65+
// CHECK-LLDB: ![[V1]] = !DILocalVariable(name: "s1", {{.*}}type: ![[TY]])
4266

43-
// CHECK-LLDB: ![[V1]] = !DILocalVariable(name: "s1", {{.*}}type: ![[TY:[0-9]+]])
44-
// CHECK-LLDB: ![[TY]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Size",

0 commit comments

Comments
 (0)