Skip to content

Commit 2d9e429

Browse files
authored
Merge pull request #14573 from adrian-prantl/36663932
2 parents abe6a6d + 3c96333 commit 2d9e429

File tree

4 files changed

+116
-43
lines changed

4 files changed

+116
-43
lines changed

lib/IRGen/IRGenSIL.cpp

Lines changed: 79 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -715,18 +715,35 @@ class IRGenSILFunction :
715715
isa<llvm::PHINode>(Storage);
716716
}
717717

718+
/// Unconditionally emit a stack shadow copy of an \c llvm::Value.
719+
llvm::Value *emitShadowCopy(llvm::Value *Storage, const SILDebugScope *Scope,
720+
StringRef Name, unsigned ArgNo, Alignment Align) {
721+
if (Align.isZero())
722+
Align = IGM.getPointerAlignment();
723+
724+
auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, Name}}];
725+
if (!Alloca.isValid())
726+
Alloca = createAlloca(Storage->getType(), Align, Name+".addr");
727+
728+
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo, Builder);
729+
Builder.CreateStore(Storage, Alloca.getAddress(), Align);
730+
return Alloca.getAddress();
731+
}
732+
718733
/// At -Onone, emit a shadow copy of an Address in an alloca, so the
719734
/// register allocator doesn't elide the dbg.value intrinsic when
720735
/// register pressure is high. There is a trade-off to this: With
721736
/// shadow copies, we lose the precise lifetime.
722-
llvm::Value *emitShadowCopy(llvm::Value *Storage, const SILDebugScope *Scope,
723-
StringRef Name, unsigned ArgNo, bool IsAnonymous,
724-
Alignment Align = Alignment(0)) {
725-
auto Ty = Storage->getType();
737+
llvm::Value *emitShadowCopyIfNeeded(llvm::Value *Storage,
738+
const SILDebugScope *Scope,
739+
StringRef Name, unsigned ArgNo,
740+
bool IsAnonymous,
741+
Alignment Align = Alignment(0)) {
726742
// Never emit shadow copies when optimizing, or if already on the stack.
743+
// No debug info is emitted for refcounts either.
727744
if (IGM.IRGen.Opts.shouldOptimize() || IsAnonymous ||
728745
isa<llvm::AllocaInst>(Storage) || isa<llvm::UndefValue>(Storage) ||
729-
Ty == IGM.RefCountedPtrTy) // No debug info is emitted for refcounts.
746+
Storage->getType() == IGM.RefCountedPtrTy)
730747
return Storage;
731748

732749
// Always emit shadow copies for function arguments.
@@ -739,29 +756,23 @@ class IRGenSILFunction :
739756
ValueDomPoints.push_back({Value, getActiveDominancePoint()});
740757
return Storage;
741758
}
742-
743-
if (Align.isZero())
744-
Align = IGM.getPointerAlignment();
745-
746-
auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, Name}}];
747-
if (!Alloca.isValid())
748-
Alloca = createAlloca(Ty, Align, Name+".addr");
749-
750-
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo, Builder);
751-
Builder.CreateStore(Storage, Alloca.getAddress(), Align);
752-
return Alloca.getAddress();
759+
return emitShadowCopy(Storage, Scope, Name, ArgNo, Align);
753760
}
754761

755-
llvm::Value *emitShadowCopy(Address Storage, const SILDebugScope *Scope,
756-
StringRef Name, unsigned ArgNo,
757-
bool IsAnonymous) {
758-
return emitShadowCopy(Storage.getAddress(), Scope, Name, ArgNo, IsAnonymous,
759-
Storage.getAlignment());
762+
/// Like \c emitShadowCopyIfNeeded() but takes an \c Address instead of an
763+
/// \c llvm::Value.
764+
llvm::Value *emitShadowCopyIfNeeded(Address Storage,
765+
const SILDebugScope *Scope,
766+
StringRef Name, unsigned ArgNo,
767+
bool IsAnonymous) {
768+
return emitShadowCopyIfNeeded(Storage.getAddress(), Scope, Name, ArgNo,
769+
IsAnonymous, Storage.getAlignment());
760770
}
761771

762-
void emitShadowCopy(SILValue &SILVal, const SILDebugScope *Scope,
763-
StringRef Name, unsigned ArgNo, bool IsAnonymous,
764-
llvm::SmallVectorImpl<llvm::Value *> &copy) {
772+
/// Like \c emitShadowCopyIfNeeded() but takes an exploded value.
773+
void emitShadowCopyIfNeeded(SILValue &SILVal, const SILDebugScope *Scope,
774+
StringRef Name, unsigned ArgNo, bool IsAnonymous,
775+
llvm::SmallVectorImpl<llvm::Value *> &copy) {
765776
Explosion e = getLoweredExplosion(SILVal);
766777

767778
// Only do this at -O0.
@@ -775,7 +786,8 @@ class IRGenSILFunction :
775786
if (e.size() <= 1) {
776787
auto vals = e.claimAll();
777788
for (auto val : vals)
778-
copy.push_back(emitShadowCopy(val, Scope, Name, ArgNo, IsAnonymous));
789+
copy.push_back(
790+
emitShadowCopyIfNeeded(val, Scope, Name, ArgNo, IsAnonymous));
779791
return;
780792
}
781793

@@ -3578,8 +3590,9 @@ void IRGenSILFunction::emitErrorResultVar(SILResultInfo ErrorInfo,
35783590
return;
35793591
auto ErrorResultSlot = getErrorResultSlot(IGM.silConv.getSILType(ErrorInfo));
35803592
SILDebugVariable Var = DbgValue->getVarInfo();
3581-
auto Storage = emitShadowCopy(ErrorResultSlot.getAddress(), getDebugScope(),
3582-
Var.Name, Var.ArgNo, false);
3593+
auto Storage =
3594+
emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(), getDebugScope(),
3595+
Var.Name, Var.ArgNo, false);
35833596
DebugTypeInfo DTI(nullptr, nullptr, ErrorInfo.getType(),
35843597
ErrorResultSlot->getType(), IGM.getPointerSize(),
35853598
IGM.getPointerAlignment(), true);
@@ -3625,7 +3638,8 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
36253638
// Put the value into a stack slot at -Onone.
36263639
llvm::SmallVector<llvm::Value *, 8> Copy;
36273640
unsigned ArgNo = i->getVarInfo().ArgNo;
3628-
emitShadowCopy(SILVal, i->getDebugScope(), Name, ArgNo, IsAnonymous, Copy);
3641+
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), Name, ArgNo, IsAnonymous,
3642+
Copy);
36293643
emitDebugVariableDeclaration(Copy, DbgTy, SILTy, i->getDebugScope(),
36303644
i->getDecl(), Name, ArgNo);
36313645
}
@@ -3665,8 +3679,9 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
36653679
// intrinsic.
36663680
unsigned ArgNo = i->getVarInfo().ArgNo;
36673681
emitDebugVariableDeclaration(
3668-
emitShadowCopy(Addr, i->getDebugScope(), Name, ArgNo, IsAnonymous), DbgTy,
3669-
SILType(), i->getDebugScope(), Decl, Name, ArgNo,
3682+
emitShadowCopyIfNeeded(Addr, i->getDebugScope(), Name, ArgNo,
3683+
IsAnonymous),
3684+
DbgTy, SILType(), i->getDebugScope(), Decl, Name, ArgNo,
36703685
(IsLoadablyByAddress || DbgTy.isImplicitlyIndirect()) ? DirectValue
36713686
: IndirectValue);
36723687
}
@@ -3871,6 +3886,31 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
38713886
const TypeInfo &type,
38723887
llvm::Value *addr) {
38733888
VarDecl *Decl = i->getDecl();
3889+
// Describe the underlying alloca. This way an llvm.dbg.declare instrinsic
3890+
// is used, which is valid for the entire lifetime of the alloca.
3891+
if (auto *BitCast = dyn_cast<llvm::BitCastInst>(addr))
3892+
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(BitCast->getOperand(0)))
3893+
addr = Alloca;
3894+
3895+
auto DS = i->getDebugScope();
3896+
if (!DS)
3897+
return;
3898+
3899+
bool IsAnonymous = false;
3900+
unsigned ArgNo = i->getVarInfo().ArgNo;
3901+
StringRef Name = getVarName(i, IsAnonymous);
3902+
3903+
// At this point addr must be an alloca or an undef.
3904+
assert(isa<llvm::AllocaInst>(addr) || isa<llvm::UndefValue>(addr));
3905+
auto Indirection = DirectValue;
3906+
if (!IGM.IRGen.Opts.shouldOptimize())
3907+
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(addr))
3908+
if (!Alloca->isStaticAlloca()) {
3909+
// Store the address of the dynamic alloca on the stack.
3910+
addr = emitShadowCopy(addr, DS, Name, ArgNo, IGM.getPointerAlignment());
3911+
Indirection = IndirectValue;
3912+
}
3913+
38743914
if (IGM.DebugInfo && Decl) {
38753915
// Ignore compiler-generated patterns but not optional bindings.
38763916
if (auto *Pattern = Decl->getParentPattern())
@@ -3883,11 +3923,13 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
38833923
auto DbgTy = DebugTypeInfo::getLocalVariable(
38843924
CurSILFn->getDeclContext(), CurSILFn->getGenericEnvironment(), Decl,
38853925
RealType, type, false);
3886-
bool IsAnonymous = false;
3887-
StringRef Name = getVarName(i, IsAnonymous);
3888-
if (auto DS = i->getDebugScope())
3889-
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, Name,
3890-
i->getVarInfo().ArgNo);
3926+
3927+
// FIXME: This is working around the inverse special case in LLDB.
3928+
if (DbgTy.isImplicitlyIndirect())
3929+
Indirection = DirectValue;
3930+
3931+
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, Name, ArgNo,
3932+
Indirection);
38913933
}
38923934
}
38933935

@@ -4095,8 +4137,8 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) {
40954137

40964138
IGM.DebugInfo->emitVariableDeclaration(
40974139
Builder,
4098-
emitShadowCopy(boxWithAddr.getAddress(), i->getDebugScope(), Name, 0,
4099-
IsAnonymous),
4140+
emitShadowCopyIfNeeded(boxWithAddr.getAddress(), i->getDebugScope(),
4141+
Name, 0, IsAnonymous),
41004142
DbgTy, i->getDebugScope(), Decl, Name, 0,
41014143
DbgTy.isImplicitlyIndirect() ? DirectValue : IndirectValue);
41024144
}

test/DebugInfo/generic_enum_closure.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ struct CErrorOr<T>
88
// CHECK: define hidden {{.*}}void @"$S20generic_enum_closure8CErrorOrV1xACyxGAA14__CurrentErrnoV_tcfC"
99
// CHECK-NOT: define
1010
// This is a SIL-level debug_value_addr instruction.
11-
// CHECK: call void @llvm.dbg.value({{.*}}, metadata ![[SELF:.*]], metadata !DIExpression())
11+
// CHECK: call void @llvm.dbg.declare
12+
// Self is in a dynamic alloca, hence the shadow copy.
13+
// CHECK: call void @llvm.dbg.declare(
14+
// CHECK-SAME: metadata i8** %[[SHADOW:.*]], metadata ![[SELF:.*]], meta
15+
// CHECK-SAME: !DIExpression(DW_OP_deref))
16+
// CHECK: alloca
17+
// CHECK: %[[DYN:.*]] = alloca i8, i{{32|64}} %
18+
// CHECK: store i8* %[[DYN]], i8** %[[SHADOW]]
1219
// CHECK: ![[T1:.*]] = !DICompositeType({{.*}}, identifier: "$S20generic_enum_closure8CErrorOrVyACQq_GD")
13-
// CHECK: ![[SELF]] = !DILocalVariable(name: "self", scope: {{.*}}, type: ![[T1]])
20+
// CHECK: ![[SELF]] = !DILocalVariable(name: "self", scope:
21+
// CHECK-SAME: type: ![[T1]])
1422
value = .none
1523
}
16-
func isError() -> Bool {
17-
assert(value != nil, "the object should not contain an error")
18-
return false
19-
}
2024
}

test/DebugInfo/resilience.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -g -emit-module -enable-resilience \
3+
// RUN: -emit-module-path=%t/resilient_struct.swiftmodule \
4+
// RUN: -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
5+
// RUN: %target-swift-frontend -g -I %t -emit-ir -enable-resilience %s \
6+
// RUN: | %FileCheck %s
7+
import resilient_struct
8+
9+
func use<T>(_ t: T) {}
10+
11+
public func f() {
12+
let s1 = Size(w: 1, h: 2)
13+
use(s1)
14+
// CHECK: %[[ADDR:.*]] = alloca i8*
15+
// CHECK: call void @llvm.dbg.declare(metadata i8** %[[ADDR]],
16+
// CHECK-SAME: metadata ![[V1:[0-9]+]],
17+
// CHECK-SAME: metadata !DIExpression(DW_OP_deref))
18+
// CHECK: %[[USE_BUFFER:.*]] = alloca i8,
19+
// CHECK: %[[S1:.*]] = alloca i8,
20+
// CHECK: store i8* %[[S1]], i8** %[[ADDR]]
21+
// CHECK: ![[V1]] = !DILocalVariable(name: "s1", {{.*}}type: ![[TY:[0-9]+]])
22+
// CHECK: ![[TY]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Size",
23+
// FIXME-NOT: size:
24+
// CHECK: =
25+
}

test/IRGen/generic_tuples.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ func dup<T>(_ x: T) -> (T, T) { var x = x; return (x,x) }
2222
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
2323
// CHECK: [[X_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16
2424
// CHECK: [[X_TMP:%.*]] = bitcast i8* [[X_ALLOCA]] to %swift.opaque*
25+
// Debug info shadow copy.
26+
// CHECK-NEXT: store i8* [[X_ALLOCA]]
2527
// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 2
2628
// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]], align 8
2729
// CHECK-NEXT: [[INITIALIZE_WITH_COPY:%.*]] = bitcast i8* [[WITNESS]] to [[OPAQUE]]* ([[OPAQUE]]*, [[OPAQUE]]*, [[TYPE]]*)*

0 commit comments

Comments
 (0)