Skip to content

[DebugInfo] Salvage debug info for tuples #72860

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 2 commits into from
Apr 6, 2024
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
1 change: 0 additions & 1 deletion docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4297,7 +4297,6 @@ less verbose.
debug-var-attr ::= 'let'
debug-var-attr ::= 'name' string-literal
debug-var-attr ::= 'argno' integer-literal
debug-var-attr ::= 'implicit'

There are a number of attributes that provide details about the source
variable that is being described, including the name of the
Expand Down
16 changes: 7 additions & 9 deletions include/swift/SIL/SILDebugVariable.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ struct SILDebugVariable {
StringRef Name;
unsigned ArgNo : 16;
unsigned Constant : 1;
unsigned Implicit : 1;
unsigned isDenseMapSingleton : 2;
std::optional<SILType> Type;
std::optional<SILLocation> Loc;
Expand All @@ -58,17 +57,17 @@ struct SILDebugVariable {
}

SILDebugVariable()
: ArgNo(0), Constant(false), Implicit(false), isDenseMapSingleton(0),
: ArgNo(0), Constant(false), isDenseMapSingleton(0),
Scope(nullptr) {}
SILDebugVariable(bool Constant, uint16_t ArgNo)
: ArgNo(ArgNo), Constant(Constant), Implicit(false),
: ArgNo(ArgNo), Constant(Constant),
isDenseMapSingleton(0), Scope(nullptr) {}
SILDebugVariable(StringRef Name, bool Constant, unsigned ArgNo,
bool IsImplicit = false, std::optional<SILType> AuxType = {},
std::optional<SILType> AuxType = {},
std::optional<SILLocation> DeclLoc = {},
const SILDebugScope *DeclScope = nullptr,
llvm::ArrayRef<SILDIExprElement> ExprElements = {})
: Name(Name), ArgNo(ArgNo), Constant(Constant), Implicit(IsImplicit),
: Name(Name), ArgNo(ArgNo), Constant(Constant),
isDenseMapSingleton(0), Type(AuxType), Loc(DeclLoc), Scope(DeclScope),
DIExpr(ExprElements) {}

Expand All @@ -85,9 +84,8 @@ struct SILDebugVariable {
// it in this class so that's it's easier to carry DIExpr around.
bool operator==(const SILDebugVariable &V) const {
return ArgNo == V.ArgNo && Constant == V.Constant && Name == V.Name &&
Implicit == V.Implicit && Type == V.Type && Loc == V.Loc &&
Scope == V.Scope && isDenseMapSingleton == V.isDenseMapSingleton &&
DIExpr == V.DIExpr;
Type == V.Type && Loc == V.Loc && Scope == V.Scope &&
isDenseMapSingleton == V.isDenseMapSingleton && DIExpr == V.DIExpr;
}

SILDebugVariable withoutDIExpr() const {
Expand All @@ -103,7 +101,7 @@ struct SILDebugVariable {

/// Returns the hashcode for the new projection path.
inline llvm::hash_code hash_value(const SILDebugVariable &P) {
return llvm::hash_combine(P.ArgNo, P.Constant, P.Name, P.Implicit,
return llvm::hash_combine(P.ArgNo, P.Constant, P.Name,
P.isDenseMapSingleton, P.Type, P.Loc, P.Scope,
P.DIExpr);
}
Expand Down
11 changes: 3 additions & 8 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1849,12 +1849,10 @@ class TailAllocatedDebugVariable {
int_type HasValue : 1;
/// True if this is a let-binding.
int_type Constant : 1;
/// True if this variable is created by compiler
int_type Implicit : 1;
/// When this is nonzero there is a tail-allocated string storing
/// variable name present. This typically only happens for
/// instructions that were created from parsing SIL assembler.
int_type NameLength : 13;
int_type NameLength : 14;
/// The source function argument position from left to right
/// starting with 1 or 0 if this is a local variable.
int_type ArgNo : 16;
Expand All @@ -1876,9 +1874,6 @@ class TailAllocatedDebugVariable {
StringRef getName(const char *buf) const;
bool isLet() const { return Bits.Data.Constant; }

bool isImplicit() const { return Bits.Data.Implicit; }
void setImplicit(bool V = true) { Bits.Data.Implicit = V; }

std::optional<SILDebugVariable>
get(VarDecl *VD, const char *buf, std::optional<SILType> AuxVarType = {},
std::optional<SILLocation> DeclLoc = {},
Expand All @@ -1890,8 +1885,8 @@ class TailAllocatedDebugVariable {
StringRef name = getName(buf);
if (VD && name.empty())
name = VD->getName().str();
return SILDebugVariable(name, isLet(), getArgNo(), isImplicit(), AuxVarType,
DeclLoc, DeclScope, DIExprElements);
return SILDebugVariable(name, isLet(), getArgNo(), AuxVarType, DeclLoc,
DeclScope, DIExprElements);
}
};
static_assert(sizeof(TailAllocatedDebugVariable) == 4,
Expand Down
7 changes: 0 additions & 7 deletions lib/SIL/IR/SILInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ TailAllocatedDebugVariable::TailAllocatedDebugVariable(
Bits.Data.HasValue = true;
Bits.Data.Constant = Var->Constant;
Bits.Data.ArgNo = Var->ArgNo;
Bits.Data.Implicit = Var->Implicit;
Bits.Data.NameLength = Var->Name.size();
assert(Bits.Data.ArgNo == Var->ArgNo && "Truncation");
assert(Bits.Data.NameLength == Var->Name.size() && "Truncation");
Expand Down Expand Up @@ -256,10 +255,6 @@ AllocStackInst::AllocStackInst(
assert(sharedUInt32().AllocStackInst.numOperands ==
TypeDependentOperands.size() &&
"Truncation");
auto *VD = Loc.getLocation().getAsASTNode<VarDecl>();
if (Var && VD) {
VarInfo.setImplicit(VD->isImplicit() || VarInfo.isImplicit());
}
TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
TypeDependentOperands);
}
Expand Down Expand Up @@ -454,8 +449,6 @@ DebugValueInst::DebugValueInst(
getTrailingObjects<SILLocation>(),
getTrailingObjects<const SILDebugScope *>(),
getTrailingObjects<SILDIExprElement>()) {
if (auto *VD = DebugLoc.getLocation().getAsASTNode<VarDecl>())
VarInfo.setImplicit(VD->isImplicit() || VarInfo.isImplicit());
setPoisonRefs(poisonRefs);
if (usesMoveableValueDebugInfo || Operand->getType().isMoveOnly())
setUsesMoveableValueDebugInfo();
Expand Down
2 changes: 0 additions & 2 deletions lib/SIL/IR/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1424,8 +1424,6 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {

if (Var->ArgNo)
*this << ", argno " << Var->ArgNo;
if (Var->Implicit)
*this << ", implicit";
if (Var->Type) {
*this << ", type ";
Var->Type->print(PrintState.OS, PrintState.ASTOptions);
Expand Down
2 changes: 0 additions & 2 deletions lib/SIL/Parser/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1677,8 +1677,6 @@ bool SILParser::parseSILDebugVar(SILDebugVariable &Var) {
Var.Constant = false;
} else if (Key == "loc") {
Var.Constant = false;
} else if (Key == "implicit") {
Var.Implicit = true;
} else {
P.diagnose(P.Tok, diag::sil_dbg_unknown_key, Key);
return true;
Expand Down
35 changes: 28 additions & 7 deletions lib/SILOptimizer/Utils/InstOptUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,7 @@ bool swift::hasOnlyEndOfScopeOrEndOfLifetimeUses(SILInstruction *inst) {
// Include debug uses only in Onone mode.
if (isDebugUser && inst->getFunction()->getEffectiveOptimizationMode() <=
OptimizationMode::NoOptimization)
if (auto DbgVarInst = DebugVarCarryingInst(user)) {
auto VarInfo = DbgVarInst.getVarInfo();
if (VarInfo && !VarInfo->Implicit)
return false;
}
return false;
}
}
return true;
Expand Down Expand Up @@ -1848,8 +1844,8 @@ void swift::salvageDebugInfo(SILInstruction *I) {
}
// If a `struct` SIL instruction is "unwrapped" and removed,
// for instance, in favor of using its enclosed value directly,
// we need to make sure any of its related `debug_value` instruction
// is preserved.
// we need to make sure any of its related `debug_value` instructions
// are preserved.
if (auto *STI = dyn_cast<StructInst>(I)) {
auto STVal = STI->getResult(0);
llvm::ArrayRef<VarDecl *> FieldDecls =
Expand All @@ -1875,6 +1871,31 @@ void swift::salvageDebugInfo(SILInstruction *I) {
}
}
}
// Similarly, if a `tuple` SIL instruction is "unwrapped" and removed,
// we need to make sure any of its related `debug_value` instructions
// are preserved.
if (auto *TTI = dyn_cast<TupleInst>(I)) {
auto TTVal = TTI->getResult(0);
for (Operand *U : getDebugUses(TTVal)) {
auto *DbgInst = cast<DebugValueInst>(U->getUser());
auto VarInfo = DbgInst->getVarInfo();
if (!VarInfo)
continue;
TupleType *TT = TTI->getTupleType();
for (auto i : indices(TT->getElements())) {
SILDebugVariable NewVarInfo = *VarInfo;
auto FragDIExpr = SILDebugInfoExpression::createTupleFragment(TT, i);
NewVarInfo.DIExpr.append(FragDIExpr);

if (!NewVarInfo.Type)
NewVarInfo.Type = TTI->getType();

// Create a new debug_value
SILBuilder(TTI, DbgInst->getDebugScope())
.createDebugValue(DbgInst->getLoc(), TTI->getElement(i), NewVarInfo);
}
}
}

if (auto *IA = dyn_cast<IndexAddrInst>(I)) {
if (IA->getBase() && IA->getIndex())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ struct MyModel: Differentiable {
@differentiable(reverse)
mutating func member4() {
// CHECK-LABEL: // pullback of MyModel.member4()
// CHECK-NOT: debug_value %{{.*}} : $MyModel.TangentVector, var, name %{{.*}}, argno 1, implicit, scope
// CHECK-NOT: debug_value %{{.*}} : $MyModel.TangentVector, var, name %{{.*}}, argno 1, scope
// CHECK: bb0(%{{.*}} : $_AD__$s4main7MyModelV7member4yyF_bb3__Pred__src_0_wrt_0):
// CHECK: debug_value %{{.*}} : $MyModel.TangentVector, var, name "derivative of 'self' in scope at {{.*}} (scope #1)", implicit, scope
// CHECK: debug_value %{{.*}} : $MyModel.TangentVector, var, name "derivative of 'self' in scope at {{.*}} (scope #1)", scope
// Must be a differentiable type.
var localVar: Float = 0

Expand Down
4 changes: 2 additions & 2 deletions test/Concurrency/transfernonsendable.sil
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ bb3(%4 : @owned $FakeOptional<NonSendableKlass>):

sil [ossa] @warningIfCallingGetter : $@convention(method) @async (@sil_isolated @guaranteed MyActor) -> () {
bb0(%0 : @guaranteed $MyActor):
debug_value %0 : $MyActor, let, name "self", argno 1, implicit
debug_value %0 : $MyActor, let, name "self", argno 1
hop_to_executor %0 : $MyActor
%3 = class_method %0 : $MyActor, #MyActor.klass!getter : (isolated MyActor) -> () -> NonSendableKlass, $@convention(method) (@sil_isolated @guaranteed MyActor) -> @owned NonSendableKlass
%4 = apply %3(%0) : $@convention(method) (@sil_isolated @guaranteed MyActor) -> @owned NonSendableKlass
Expand All @@ -301,7 +301,7 @@ bb0(%0 : @guaranteed $MyActor):

sil [ossa] @assignIntoSetter : $@convention(method) @async (@sil_isolated @guaranteed MyActor) -> () {
bb0(%0 : @guaranteed $MyActor):
debug_value %0 : $MyActor, let, name "self", argno 1, implicit
debug_value %0 : $MyActor, let, name "self", argno 1
hop_to_executor %0 : $MyActor
%4 = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
%5 = apply %4() : $@convention(thin) () -> @owned NonSendableKlass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1680,7 +1680,7 @@ bb0(%arg : $Builtin.Word):

sil hidden [ossa] @test_unconditional_checked_cast : $@convention(method) (@guaranteed ChildClass) -> @owned ChildClass {
bb0(%0 : @guaranteed $ChildClass):
debug_value %0 : $ChildClass, let, name "self", argno 1, implicit
debug_value %0 : $ChildClass, let, name "self", argno 1
%2 = copy_value %0 : $ChildClass
%3 = upcast %2 : $ChildClass to $ParentClass
%4 = function_ref @copyParentClass : $@convention(thin) (@guaranteed ParentClass) -> @owned ParentClass
Expand All @@ -1693,4 +1693,4 @@ bb0(%0 : @guaranteed $ChildClass):
%11 = copy_value %8 : $ChildClass
destroy_value %8 : $ChildClass
return %11 : $ChildClass
}
}
2 changes: 1 addition & 1 deletion test/DebugInfo/catch_error.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ open class Cache<T> {
let value = try creationBlock()
return value
} catch {
// CHECK: debug_value {{.*}} : $any Error, let, name "error", implicit, loc "{{.*}}":[[@LINE-1]]:13, scope [[SCOPE:[0-9]+]]
// CHECK: debug_value {{.*}} : $any Error, let, name "error", loc "{{.*}}":[[@LINE-1]]:13, scope [[SCOPE:[0-9]+]]
// CHECK: alloc_stack $@opened({{.*}}, any Error) Self, loc{{.*}}, scope [[SCOPE]]

_negativeCache.setObject(error, forKey: NSNumber(1))
Expand Down
48 changes: 32 additions & 16 deletions test/DebugInfo/constant_propagation.sil
Original file line number Diff line number Diff line change
@@ -1,41 +1,57 @@
// RUN: %target-sil-opt -enable-sil-verify-all -sil-print-debuginfo -diagnostic-constant-propagation %s | %FileCheck %s
// REQUIRES: CPU=arm64 || CPU=x86_64

sil_stage canonical

import Builtin
import Swift
import SwiftShims

func foo(x: Int, y: Int) -> Int

sil_scope 1 { loc "file.swift":1:6 parent @foo : $@convention(thin) (Int, Int) -> Int }
sil_scope 1 { loc "file.swift":1:6 parent @foo : $@convention(thin) (Int64, Int64) -> Int64 }

// Test if debug_value got preserved when %16 is removed in favor of directly using %13
// CHECK-LABEL: sil {{.*}} @foo
sil hidden @foo : $@convention(thin) (Int, Int) -> Int {
bb0(%0 : $Int, %1 : $Int):
sil hidden @foo : $@convention(thin) (Int64, Int64) -> Int64 {
bb0(%0 : $Int64, %1 : $Int64):
%4 = integer_literal $Builtin.Int64, 87, loc "file.swift":2:17, scope 1
%9 = struct_extract %0 : $Int, #Int._value, loc "file.swift":2:15, scope 1
%9 = struct_extract %0 : $Int64, #Int64._value, loc "file.swift":2:15, scope 1
%11 = integer_literal $Builtin.Int1, -1, loc "file.swift":2:15, scope 1
// CHECK: %[[ADD:.+]] = builtin "sadd_with_overflow
%12 = builtin "sadd_with_overflow_Int64"(%9 : $Builtin.Int64, %4 : $Builtin.Int64, %11 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1), loc "file.swift":2:15, scope 1
// CHECK: (%[[RESULT:.+]], %{{.*}}) = destructure_tuple %[[ADD]]
(%13, %14) = destructure_tuple %12 : $(Builtin.Int64, Builtin.Int1), loc "file.swift":2:15, scope 1
%16 = struct $Int (%13 : $Builtin.Int64), loc "file.swift":2:15, scope 1
%16 = struct $Int64 (%13 : $Builtin.Int64), loc "file.swift":2:15, scope 1
// In addition to checking if `op_fragment` is generated, we're also checking if "z"'s declared
// source location, as well as `debug_value`'s instruction source location are preserved.
// CHECK: debug_value %[[RESULT]] : $Builtin.Int{{[0-9]+}}, let, name "z"
// CHECK-SAME: type $Int
// CHECK-SAME: expr op_fragment:#Int._value
// CHECK: debug_value %[[RESULT]] : $Builtin.Int64, let, name "z"
// CHECK-SAME: type $Int64
// CHECK-SAME: expr op_fragment:#Int64._value
// CHECK-SAME: loc "file.swift":2:9, scope 1
debug_value %16 : $Int, let, name "z", loc "file.swift":2:9, scope 1
%19 = struct_extract %16 : $Int, #Int._value, loc "file.swift":3:14, scope 1
%20 = struct_extract %1 : $Int, #Int._value, loc "file.swift":3:14, scope 1
debug_value %16 : $Int64, let, name "z", loc "file.swift":2:9, scope 1
%19 = struct_extract %16 : $Int64, #Int64._value, loc "file.swift":3:14, scope 1
%20 = struct_extract %1 : $Int64, #Int64._value, loc "file.swift":3:14, scope 1
%21 = integer_literal $Builtin.Int1, -1, loc "file.swift":3:14, scope 1
%22 = builtin "sadd_with_overflow_Int64"(%19 : $Builtin.Int64, %20 : $Builtin.Int64, %21 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1), loc "file.swift":3:14, scope 1
(%23, %24) = destructure_tuple %22 : $(Builtin.Int64, Builtin.Int1), loc "file.swift":3:14, scope 1
%26 = struct $Int (%23 : $Builtin.Int64), loc "file.swift":3:14, scope 1
return %26 : $Int, loc "file.swift":3:5, scope 1
%26 = struct $Int64 (%23 : $Builtin.Int64), loc "file.swift":3:14, scope 1
return %26 : $Int64, loc "file.swift":3:5, scope 1
} // end sil function 'foo'

sil_scope 2 { loc "file.swift":1:6 parent @bar : $@convention(thin) (Int64, Int64) -> Int64 }

// Test if debug_value got preserved when %5 is folded into %0, and %3 removed
// CHECK-LABEL: sil {{.*}} @bar
sil hidden @bar : $@convention(thin) (Int64, Int64) -> Int64 {
bb0(%0 : $Int64, %1 : $Int64):
%3 = tuple $(low: Int64, high: Int64) (%0, %1), loc "file.swift":14:5, scope 2
// CHECK: debug_value %0 : $Int64, let, name "newValue"
// CHECK-SAME: type $(low: Int64, high: Int64)
// CHECK-SAME: expr op_tuple_fragment:$(low: Int64, high: Int64):0
// CHECK-SAME: "file.swift":14:5, scope 2
// CHECK: debug_value %1 : $Int64, let, name "newValue"
// CHECK-SAME: type $(low: Int64, high: Int64)
// CHECK-SAME: expr op_tuple_fragment:$(low: Int64, high: Int64):1
// CHECK-SAME: "file.swift":14:5, scope 2
debug_value %3 : $(low: Int64, high: Int64), let, name "newValue", argno 1, loc "file.swift":14:5, scope 2
(%5, %6) = destructure_tuple %3 : $(low: Int64, high: Int64), loc "file.swift":15:5, scope 2
return %5 : $Int64, loc "file.swift":15:5, scope 2
} // end sil function 'bar'
2 changes: 1 addition & 1 deletion test/DebugInfo/debug_value_addr.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func use<T>(_ t : T) {}
// CHECK-SIL: sil hidden @$s16debug_value_addr11GenericSelfV1xACyxGx_tcfC : $@convention(method) <T> (@in T, @thin GenericSelf<T>.Type) -> GenericSelf<T> {
// CHECK-SIL: bb0(%0 : $*T, %1 : $@thin GenericSelf<T>.Type):
//
// CHECK-SIL-NEXT: alloc_stack [var_decl] $GenericSelf<T>, var, name "self", implicit, loc {{.*}}
// CHECK-SIL-NEXT: alloc_stack [var_decl] $GenericSelf<T>, var, name "self", loc {{.*}}
// CHECK-SIL-NEXT: debug_value %0 : $*T, let, name "x", argno 1, expr op_deref, loc {{.*}}
struct GenericSelf<T> {
init(x: T) {
Expand Down
12 changes: 0 additions & 12 deletions test/DebugInfo/implicit_variable.swift

This file was deleted.

10 changes: 5 additions & 5 deletions test/DebugInfo/nested_salvage_struct.sil
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ sil private @pop : $@convention(method) (UInt64, Wrapper) -> Wrapper {
[global: ]
bb0(%0 : $UInt64, %1 : $Wrapper):
debug_value %0 : $UInt64, let, name "numBits", argno 1, scope 3
debug_value %1 : $Wrapper, let, name "self", argno 2, implicit, scope 3
debug_value %1 : $Wrapper, let, name "self", argno 2, scope 3
%4 = struct_extract %1 : $Wrapper, #Wrapper.bytes, scope 3
%5 = struct_extract %4 : $UInt64, #UInt64._value, scope 3
%6 = struct_extract %0 : $UInt64, #UInt64._value, scope 3
Expand All @@ -46,15 +46,15 @@ sil hidden @maker : $@convention(method) (UInt64, @thin Wrapper.Type) -> Wrapper
bb0(%0 : $UInt64, %1 : $@thin Wrapper.Type):
// CHECK: debug_value %0 : $UInt64, let, name "bits", argno 1
debug_value %0 : $UInt64, let, name "bits", argno 1, scope 7
// CHECK: debug_value %1 : $@thin Wrapper.Type, let, name "self", argno 2, implicit
debug_value %1 : $@thin Wrapper.Type, let, name "self", argno 2, implicit, scope 7
// CHECK: debug_value %1 : $@thin Wrapper.Type, let, name "self", argno 2
debug_value %1 : $@thin Wrapper.Type, let, name "self", argno 2, scope 7
%4 = integer_literal $Builtin.Int64, 3735928559, scope 7
%5 = struct $UInt64 (%4 : $Builtin.Int64), scope 7
%6 = struct $Wrapper (%5 : $UInt64), loc * "e.swift":3:8
// CHECK-DAG: debug_value %0 : $UInt64, let, name "numBits", argno 1
debug_value %0 : $UInt64, let, name "numBits", argno 1, scope 11
// CHECK-DAG: debug_value %{{.*}} : $Builtin.Int64, let, name "self", {{.*}}, implicit, type $Wrapper, expr op_fragment:#Wrapper.bytes:op_fragment:#UInt64._value
debug_value %6 : $Wrapper, let, name "self", argno 2, implicit, scope 11
// CHECK-DAG: debug_value %{{.*}} : $Builtin.Int64, let, name "self", {{.*}}, type $Wrapper, expr op_fragment:#Wrapper.bytes:op_fragment:#UInt64._value
debug_value %6 : $Wrapper, let, name "self", argno 2, scope 11
%9 = struct_extract %6 : $Wrapper, #Wrapper.bytes, scope 11
%10 = struct_extract %9 : $UInt64, #UInt64._value, scope 11
%11 = struct_extract %0 : $UInt64, #UInt64._value, scope 11
Expand Down
21 changes: 21 additions & 0 deletions test/DebugInfo/property-setter-implicit-tuple.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s

// This is a test for rdar://125939953 (Implicit variables are removed at Onone)

struct UInt128 {
var low: UInt64
var high: UInt64

var components: (low: UInt64, high: UInt64) {
get {
return (low, high)
}
// CHECK-LABEL: define {{.+}} @"$s4main7UInt128V10componentss6UInt64V3low_AF4hightvs"
set {
// CHECK: call void @llvm.dbg.declare(metadata ptr {{.+}}, metadata ![[NEW_VALUE:[0-9]+]]
(self.low, self.high) = (newValue.high, newValue.low)
}
}
}

//CHECK: ![[NEW_VALUE]] = !DILocalVariable(name: "newValue", arg: 1
Loading