Skip to content

Zero-initialize -Onone debug shadow copies for exploded values #19333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 12 additions & 17 deletions lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,31 +720,25 @@ class IRGenSILFunction :
}

/// To make it unambiguous whether a `var` binding has been initialized,
/// zero-initialize the first pointer-sized field. LLDB uses this to
/// recognize to detect uninitizialized variables. This can be removed once
/// swiftc switches to @llvm.dbg.addr() intrinsics.
/// zero-initialize the shadow copy alloca. LLDB uses the first pointer-sized
/// field to recognize to detect uninitizialized variables. This can be
/// removed once swiftc switches to @llvm.dbg.addr() intrinsics.
void zeroInit(llvm::AllocaInst *AI) {
if (!AI)
return;

// Only do this at -Onone.
if (IGM.IRGen.Opts.shouldOptimize())
return;

auto &DL = IGM.DataLayout;
if (DL.getTypeSizeInBits(AI->getAllocatedType()) <
DL.getPointerSizeInBits())
uint64_t Size = *AI->getAllocationSizeInBits(IGM.DataLayout) / 8;
if (IGM.IRGen.Opts.shouldOptimize() || !Size)
return;

llvm::IRBuilder<> ZeroInitBuilder(AI->getNextNode());

// No debug location is how LLVM marks prologue instructions.
ZeroInitBuilder.SetCurrentDebugLocation(nullptr);
auto *BC =
ZeroInitBuilder.CreateBitCast(AI, IGM.OpaquePtrTy->getPointerTo());
ZeroInitBuilder.CreateAlignedStore(
llvm::ConstantPointerNull::get(IGM.OpaquePtrTy), BC,
IGM.getPointerAlignment().getValue());
ZeroInitBuilder.CreateMemSet(
AI, llvm::ConstantInt::get(IGM.Int8Ty, 0),
Size, AI->getAlignment());
}

/// Account for bugs in LLVM.
Expand All @@ -769,8 +763,8 @@ class IRGenSILFunction :

auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, Name}}];
if (!Alloca.isValid())
Alloca = createAlloca(Storage->getType(), Align, Name+".addr");
zeroInit(dyn_cast<llvm::AllocaInst>(Alloca.getAddress()));
Alloca = createAlloca(Storage->getType(), Align, Name+".debug");
zeroInit(cast<llvm::AllocaInst>(Alloca.getAddress()));

ArtificialLocation AutoRestore(Scope, IGM.DebugInfo, Builder);
Builder.CreateStore(Storage, Alloca.getAddress(), Align);
Expand Down Expand Up @@ -848,7 +842,8 @@ class IRGenSILFunction :

SILType Type = SILVal->getType();
auto &LTI = cast<LoadableTypeInfo>(IGM.getTypeInfo(Type));
auto Alloca = LTI.allocateStack(*this, Type, "debug.copy");
auto Alloca = LTI.allocateStack(*this, Type, Name+".debug");
zeroInit(cast<llvm::AllocaInst>(Alloca.getAddress().getAddress()));
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo, Builder);
LTI.initialize(*this, e, Alloca.getAddress(), false /* isOutlined */);
copy.push_back(Alloca.getAddressPointer());
Expand Down
6 changes: 3 additions & 3 deletions test/DebugInfo/dbgvalue-insertpt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// FIXME: This test should be testing a non-shadow-copied value instead.
for i in 0 ..< 3 {
// CHECK: %[[ALLOCA:[0-9]+]] = alloca %TSiSg
// CHECK: %i.addr = alloca i{{32|64}}
// CHECK-NEXT: call void @llvm.dbg.declare(metadata i{{32|64}}* %i.addr,
// CHECK: %i.debug = alloca i{{32|64}}
// CHECK-NEXT: call void @llvm.dbg.declare(metadata i{{32|64}}* %i.debug,
// CHECK-SAME: metadata ![[I:[0-9]+]],
// CHECK: call swiftcc{{.*}} @{{.*}}next{{.*}}
// CHECK: %[[LD:[0-9]+]] = load i{{32|64}}, i{{32|64}}*
Expand All @@ -14,6 +14,6 @@ for i in 0 ..< 3 {
//
// CHECK: ; <label>:[[NEXT_BB]]:
// CHECK: %[[PHI_VAL:.*]] = phi i{{32|64}} [ %[[LD]], %[[SUCCESS]] ]
// CHECK: store i{{32|64}} %[[PHI_VAL]], i{{32|64}}* %i.addr
// CHECK: store i{{32|64}} %[[PHI_VAL]], i{{32|64}}* %i.debug
// CHECK: ![[I]] = !DILocalVariable(name: "i",
}
2 changes: 1 addition & 1 deletion test/DebugInfo/generic_arg2.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s

// CHECK: define hidden swiftcc void @"$S12generic_arg25ClassC3foo{{.*}}, %swift.type* %U
// CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** %y.addr, metadata ![[U:.*]], metadata !DIExpression())
// CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** %y.debug, metadata ![[U:.*]], metadata !DIExpression())
// Make sure there is no conflicting dbg.value for this variable.x
// CHECK-NOT: dbg.value{{.*}}metadata ![[U]]
class Class <T> {
Expand Down
33 changes: 18 additions & 15 deletions test/DebugInfo/guard-let.swift
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s
// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s --check-prefix=CHECK2
// RUN: %target-swift-frontend %s -c -emit-ir -g -o - | \
// RUN: %FileCheck %s --check-prefix=CHECK1
// RUN: %target-swift-frontend %s -c -emit-ir -g -o - | \
// RUN: %FileCheck %s --check-prefix=CHECK2

// UNSUPPORTED: OS=watchos

func use<T>(_ t: T) {}

public func f(_ i : Int?)
{
// CHECK: define {{.*}}@"$S4main1fyySiSgF"
// CHECK1: %debug.copy = alloca %TSiSg
// CHECK1: @llvm.dbg.declare(metadata %TSiSg* %debug.copy
// CHECK1: @llvm.dbg.declare(metadata {{(i32|i64)}}* %val.addr, {{.*}}, !dbg ![[DBG0:.*]]
// CHECK1: %5 = bitcast %TSiSg* %debug.copy to i64*, !dbg
// CHECK1: store i64 %0, i64* %5, align 8, !dbg
// CHECK1-LABEL: define {{.*}}@"$S4main1fyySiSgF"
// CHECK1: %i.debug = alloca %TSiSg
// CHECK1: @llvm.dbg.declare(metadata %TSiSg* %i.debug
// CHECK1: %[[BITCAST:.*]] = bitcast %TSiSg* %i.debug to i8*
// CHECK1: call void @llvm.memset{{.*}}(i8* align {{(4|8)}} %[[BITCAST]],
// CHECK1-SAME: i8 0, i64 {{(5|9)}}, i1 false){{$}}
// CHECK1: @llvm.dbg.declare(metadata {{(i32|i64)}}* %val.debug,
// CHECK1-SAME: !dbg ![[DBG0:.*]]
// CHECK1-LABEL: define {{.*}}@"$S4main1gyySSSgF"
// CHECK1: ![[F:.*]] = distinct !DISubprogram(name: "f",
// CHECK1: ![[BLK:.*]] = distinct !DILexicalBlock(scope: ![[F]],
// CHECK1: ![[DBG0]] = !DILocation(line: [[@LINE+2]],
// CHECK1: ![[DBG1]] = !DILocation(line: 0, scope: ![[BLK]])
// CHECK1: ![[DBG0]] = !DILocation(line: [[@LINE+1]],
guard let val = i else { return }
use(val)
}
Expand All @@ -32,13 +36,12 @@ public func f(_ i : Int?)
public func g(_ s : String?)
{
// CHECK2: define {{.*}}@"$S4main1gyySSSgF"
// CHECK2: %debug.copy = alloca %TSSSg
// CHECK2: %s.debug = alloca %TSSSg
// CHECK2: @llvm.dbg.declare(metadata %TSSSg*
// CHECK2: %debug.copy1 = alloca %TSS
// CHECK2: %val.debug = alloca %TSS
// CHECK2: @llvm.dbg.declare(metadata %TSS*
// CHECK2: %4 = bitcast %TSSSg* %debug.copy to {{.*}}*, !dbg
// CHECK2: %5 = getelementptr inbounds {{.*}}, {{.*}}* %4, i32 0, i32 0, !dbg
// CHECK2: store {{.*}} %0, {{.*}}* %5, align 8, !dbg
// CHECK2: %[[BITCAST:.*]] = bitcast %TSS* %val.debug to i8*{{$}}
// CHECK2: call void @llvm.memset.{{.*}}(i8* align {{(4|8)}} %[[BITCAST]], i8 0
// CHECK2: ![[G:.*]] = distinct !DISubprogram(name: "g"
guard let val = s else { return }
use(val)
Expand Down
6 changes: 3 additions & 3 deletions test/DebugInfo/linetable-codeview.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ func foo() {
// NOTE: The point of this test is to trigger IRGenSIL::emitShadowCopy()
// and IRGenSIL::emitShadowCopyIfNeeded(). It may be worthwhile to
// simplify this testcase.
// CHECK: store float %0, float* %myArg.addr, {{.*}}, !dbg ![[PROLOGUE:[0-9]+]]
// CHECK: store float {{.*}}, float* %debug.copy.myVal1._value, {{.*}}, !dbg ![[PROLOGUE]]
// CHECK: store float %0, float* %myArg.debug, {{.*}}, !dbg ![[PROLOGUE:[0-9]+]]
// CHECK: store float {{.*}}, float* %self.debug.myVal1._value, {{.*}}, !dbg ![[PROLOGUE]]

// func myLoop() {
// CHECK: define {{.*}} @"$S4main6myLoopyyF"
// CHECK: call void @llvm.dbg.declare(metadata i64* %index.addr, {{.*}}), !dbg ![[FORLOOP:[0-9]+]]
// CHECK: call void @llvm.dbg.declare(metadata i64* %index.debug, {{.*}}), !dbg ![[FORLOOP:[0-9]+]]
// CHECK: phi i64 [ %{{.[0-9]+}}, %{{.[0-9]+}} ], !dbg ![[FORLOOP]]
// CHECK: call {{.*}} @"$S4main8markUsedyyxlF"{{.*}}, !dbg ![[FORBODY:[0-9]+]]
// CHECK: ret void
Expand Down
4 changes: 2 additions & 2 deletions test/DebugInfo/shadowcopy-linetable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ func foo(_ x: inout Int64) {
// not.
// CHECK: %[[X:.*]] = alloca %Ts5Int64V*, align {{(4|8)}}
// CHECK-NEXT: call void @llvm.dbg.declare
// CHECK-NEXT: [[ZEROED:%[0-9]+]] = bitcast %Ts5Int64V** %[[X]] to %swift.opaque**
// CHECK-NEXT: store %swift.opaque* null, %swift.opaque** [[ZEROED]], align {{(4|8)}}
// CHECK-NEXT: %[[ZEROED:[0-9]+]] = bitcast %Ts5Int64V** %[[X]] to i8*{{$}}
// CHECK-NEXT: call void @llvm.memset.{{.*}}(i8* align {{(4|8)}} %[[ZEROED]], i8 0
// CHECK: store %Ts5Int64V* %0, %Ts5Int64V** %[[X]], align {{(4|8)}}
// CHECK-SAME: !dbg ![[LOC0:.*]]
// CHECK-NEXT: getelementptr inbounds %Ts5Int64V, %Ts5Int64V* %0, i32 0, i32 0,
Expand Down
18 changes: 10 additions & 8 deletions test/DebugInfo/uninitialized.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s
// RUN: %target-swift-frontend %s -O -emit-ir -g -o - | %FileCheck %s --check-prefix=OPT
// RUN: %target-swift-frontend %s -c -emit-ir -g -o - | %FileCheck %s
// RUN: %target-swift-frontend %s -O -c -emit-ir -g -o - | %FileCheck %s --check-prefix=OPT
class MyClass {}

// CHECK-LABEL: define {{.*}} @"$S13uninitialized1fyyF"
Expand All @@ -8,9 +8,10 @@ public func f() {
var object: MyClass
// CHECK: %[[OBJ:.*]] = alloca %[[T1:.*]]*, align
// CHECK: call void @llvm.dbg.declare(metadata %[[T1]]** %[[OBJ]],
// CHECK: %[[BC1:.*]] = bitcast %[[T1]]** %[[OBJ]] to %swift.opaque**
// CHECK: store %swift.opaque* null, %swift.opaque** %[[BC1]], align {{.*}}
// OPT-NOT: store
// CHECK: %[[BC1:.*]] = bitcast %[[T1]]** %[[OBJ]] to i8*{{$}}
// CHECK: void @llvm.memset.{{.*}}(i8* align {{(4|8)}} %[[BC1]], i8 0,
// CHECK-SAME: ){{$}}
// OPT-NOT: @llvm.memset
// OPT: ret
}

Expand All @@ -20,8 +21,9 @@ public func g() {
var dict: Dictionary<Int64, Int64>
// CHECK: %[[DICT:.*]] = alloca %[[T2:.*]], align
// CHECK: call void @llvm.dbg.declare(metadata %[[T2]]* %[[DICT]],
// CHECK: %[[BC2:.*]] = bitcast %[[T2]]* %[[DICT]] to %swift.opaque**
// CHECK: store %swift.opaque* null, %swift.opaque** %[[BC2]], align {{.*}}
// OPT-NOT: store
// CHECK: %[[BC2:.*]] = bitcast %[[T2]]* %[[DICT]] to i8*
// CHECK: void @llvm.memset.{{.*}}(i8* align {{(4|8)}} %[[BC2]], i8 0,
// CHECK-SAME: ){{$}}
// OPT-NOT: @llvm.memset
// OPT: ret
}
2 changes: 1 addition & 1 deletion test/IRGen/alloc_box.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ func f() -> Bool? { return nil }
})()

// CHECK-LABEL: @"$S9alloc_boxyyXEfU_"
// CHECK: <label>:8:
// CHECK: <label>:9:
// CHECK-NOT: call void @swift_setDeallocating
// CHECK: call void @swift_deallocUninitializedObject

1 change: 1 addition & 0 deletions test/IRGen/builtins.swift
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ func unsafeGuaranteed_test(_ x: Builtin.NativeObject) -> Builtin.NativeObject {
// CHECK-LABEL: define {{.*}} @{{.*}}unsafeGuaranteedEnd_test
// CHECK-NEXT: {{.*}}:
// CHECK-NEXT: alloca
// CHECK-NEXT: memset
// CHECK-NEXT: store
// CHECK-NEXT: ret void
func unsafeGuaranteedEnd_test(_ x: Builtin.Int8) {
Expand Down
2 changes: 1 addition & 1 deletion test/IRGen/class_bounded_generics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ func archetype_with_generic_class_constraint<T, U>(t: T) where T : A<U> {

// CHECK-LABEL: define hidden swiftcc void @"$S22class_bounded_generics029calls_archetype_with_generic_A11_constraint1ayAA1ACyxG_tlF"(%T22class_bounded_generics1AC*) #0 {
// CHECK: alloca
// CHECK: store
// CHECK: memset
// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T22class_bounded_generics1AC, %T22class_bounded_generics1AC* %0, i32 0, i32 0, i32 0
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
// CHECK: [[ISA_PTR:%.*]] = bitcast %swift.type* [[ISA]] to %swift.type**
Expand Down
2 changes: 1 addition & 1 deletion test/IRGen/objc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func test1(_ cell: Blammo) {}
// CHECK-NEXT: entry
// CHECK-NEXT: alloca
// CHECK-NEXT: bitcast
// CHECK-NEXT: store
// CHECK-NEXT: memset
// CHECK-NEXT: store
// CHECK-NEXT: ret void

Expand Down
2 changes: 1 addition & 1 deletion test/IRGen/struct_resilience.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public func functionWithMyResilientTypesSize(_ s: __owned MySize, f: (__owned My
// CHECK: bitcast
// CHECK: llvm.lifetime.start
// CHECK: bitcast
// CHECK: [[COPY:%.*]] = bitcast %T17struct_resilience6MySizeV* %4 to i8*
// CHECK: [[COPY:%.*]] = bitcast %T17struct_resilience6MySizeV* %5 to i8*
// CHECK: [[ARG:%.*]] = bitcast %T17struct_resilience6MySizeV* %1 to i8*
// CHECK: call void @llvm.memcpy{{.*}}(i8* align {{4|8}} [[COPY]], i8* align {{4|8}} [[ARG]], {{i32 8|i64 16}}, i1 false)
// CHECK: [[FN:%.*]] = bitcast i8* %2
Expand Down