Skip to content
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

[SR-13263] Invalid Debug Information Generation #55703

Closed
compnerd opened this issue Jul 21, 2020 · 28 comments · Fixed by #66744
Closed

[SR-13263] Invalid Debug Information Generation #55703

compnerd opened this issue Jul 21, 2020 · 28 comments · Fixed by #66744
Assignees
Labels
assertion failure Bug → crash: An assertion failure bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software debug info Area → compiler → IRGen: Debug information emission IRGen LLVM IR generation swift 5.9

Comments

@compnerd
Copy link
Collaborator

compnerd commented Jul 21, 2020

Previous ID SR-13263
Radar None
Original Reporter @compnerd
Type Bug

Attachment: Download

Additional Detail from JIRA
Votes 3
Component/s
Labels Bug
Assignee @adrian-prantl
Priority Medium

md5: 1cf1abd3137f286141ea88df6a315030

Issue Description:

lit test reproducer:

// RUN: %empty-directory(%t)
// RUN: %target-swiftc_driver -DM -emit-module -emit-module-path %t/M.swiftmodule %s -module-name M
// RUN: not --crash %target-swiftc_driver -O -g -I %t -c %s -o /dev/null

#if M
import _Differentiation

public struct S<T> {
  class C {}
  let c: C
  internal var b: Bool
}

extension S: AdditiveArithmetic {
  public static var zero: S { fatalError() }

  public static func == (_ lhs: S, _ rhs: S) -> Bool { fatalError() }
  public static func + (_ lhs: S, _ rhs: S) -> S { fatalError() }
  public static func - (_ lhs: S, _ rhs: S) -> S { fatalError() }
}

extension S: Differentiable {
  public typealias TangentVector = S
}

#else
import _Differentiation
import M

struct T: Differentiable {
  var u1: U
  var u2: U
}

struct U: Differentiable {
  var s: S<Float>
  var v: V
}

struct V: Differentiable {
  var s: S<Float>
}
#endif

Crash:

swift-frontend: swift-dev/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp:572: void llvm::DwarfExpression::addFragmentOffset(const llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits && "overlapping or duplicate fragments"' failed.
Stack dump:
1.  Swift version 5.3-dev (LLVM 6d510c802af0d59, Swift 3e090b483352b3c)
2.  Running pass 'Function Pass Manager' on module '/dev/null'.
3.  Running pass 'X86 Assembly Printer' on function '@"$s4null1TV4move5alongyAC13TangentVectorV_tF"'
@swift-ci
Copy link
Collaborator

Comment by Mustafa YALCIN (JIRA)

3

@compnerd
Copy link
Collaborator Author

Building this with the toolchain from master (swift: e9c3157ef666a1ed8eb106e805b03ce35b8ec586, llvm: e966de21c9ff9edcb098d508e1c206b3f5098373) with experimental differentiable programming support (mostly because reducing it further without the synthesized methods is difficult), seems to generate invalid debug information in the swift frontend.

Doing this in multiple phases (.swift -> .sil -> .o) seems to trigger the Debug Info validation:

conflicting debug info for argument 
 call void @llvm.dbg.value(metadata %T1M1SV1CCySf_G* %0, metadata !289, metadata !DIExpression(DW_OP_LLVM_fragment
, 0, 64)), !dbg !288 
!286 = !DILocalVariable(name: "self", arg: 1, scope: !283, file: !1, type: !287, flags: DIFlagArtificial) 
!289 = !DILocalVariable(name: "self", arg: 1, scope: !283, file: !1, type: !290, flags: DIFlagArtificial)

Doing it in a single phase triggers an LLVM assertion about the overlapping debug info fragment generated from this:

swift-frontend: /SourceCache/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp:572: void llvm::DwarfExpr
ession::addFragmentOffset(const llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits && "overlapping or duplicate fragments"' failed.

It seems that -sil-verify-all doesn't actually catch the issue, which makes this a bit trickier to isolate.

+ @adrian-prantl @eeckstein @dan-zheng

@swift-ci
Copy link
Collaborator

Comment by Mustafa YALCIN (JIRA)

3

7 similar comments
@swift-ci
Copy link
Collaborator

Comment by Mustafa YALCIN (JIRA)

3

@swift-ci
Copy link
Collaborator

Comment by Mustafa YALCIN (JIRA)

3

@swift-ci
Copy link
Collaborator

Comment by Mustafa YALCIN (JIRA)

3

@swift-ci
Copy link
Collaborator

Comment by Mustafa YALCIN (JIRA)

3

@swift-ci
Copy link
Collaborator

Comment by Mustafa YALCIN (JIRA)

3

@swift-ci
Copy link
Collaborator

Comment by Mustafa YALCIN (JIRA)

3

@swift-ci
Copy link
Collaborator

Comment by Mustafa YALCIN (JIRA)

3

@eeckstein
Copy link
Member

@compnerd I could not reproduce the issue. Can you add a more self contained test case, e.g. with full expanded invocation lines? Also I had to fix some obvious syntax errors in the test file.

Also, how did you build the swift compiler? Is this reproducible on Mac?

@dan-zheng
Copy link
Collaborator

@eeckstein: the issue should be directly reproducible from the test case (which is a lit test) on both macOS and Linux.


I pushed the test case to dan-zheng@SR-13263 so it's easier to reproduce.

The crash is an LLVM assertion about overlapping debug info fragments:

swift-frontend: /SourceCache/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp:572: void llvm::DwarfExpr
ession::addFragmentOffset(const llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits && "overlapping or duplicate fragments"' failed.

test/DebugInfo/sr13263.swift has a bunch of details. The issue is only reproducible with a two file test case and swiftc -O -g. The issue not reproducible if any of the following are true:

  1. If Swift optimizations are disabled (-Onone).

  2. If debug info is disabled (no -g).

  3. If LoadableByAddress is disabled.

  4. If code synthesized by `Differentiable` derived conformances are written out by hand.

  5. If reproducer is compiled as one file instead of two files.


Could someone please help take a look? @compnerd and I are reaching the limits of our debugging ability, so any help would be greatly appreciated!

@eeckstein @adrian-prantl

@dan-zheng
Copy link
Collaborator

One thing that looks suspicious is multiple calls to @llvm.dbg.declare with the exact metadata arguments (file):

;; LLVM IR for the problematic function in SR-13263.

define hidden swiftcc void @"$s4main1TV4move5alongyAC13TangentVectorV_tF"(%T4main1TV13TangentVectorV* noalias nocapture dereferenceable(57) %0, %T4main1TV* nocapture swiftself dereferenceable(57) %1) #&#8203;0 !dbg !583 {
entry:
 %2 = alloca %T4main1VV13TangentVectorV, align 8
 call void @llvm.dbg.declare(metadata %T4main1VV13TangentVectorV* %2, metadata !586, metadata !DIExpression()), !dbg !590
 %3 = alloca %T4main1UV13TangentVectorV, align 8
 call void @llvm.dbg.declare(metadata %T4main1UV13TangentVectorV* %3, metadata !598, metadata !DIExpression()), !dbg !599
 %4 = alloca %T4main1VV13TangentVectorV, align 8
 call void @llvm.dbg.declare(metadata %T4main1VV13TangentVectorV* %4, metadata !586, metadata !DIExpression()), !dbg !600
 %5 = alloca %T4main1UV13TangentVectorV, align 8
 call void @llvm.dbg.declare(metadata %T4main1UV13TangentVectorV* %5, metadata !598, metadata !DIExpression()), !dbg !599

This is lowered from the following SIL post-LoadableByAddress (file):

 *** SIL module after #&#8203;99, stage IRGen Preparation, pass 1: LoadableByAddress (loadable-address)
// T.move(along:)
sil hidden @$s4main1TV4move5alongyAC13TangentVectorV_tF : $@convention(method) (@in_guaranteed T.TangentVector, @inout T) -> () {
// %0 "direction" // users: %6, %8, %41
// %1 "self" // users: %10, %43, %7
bb0(%0 : $*T.TangentVector, %1 : $*T):
 %2 = alloc_stack $V.TangentVector // users: %38, %28, %30, %26, %76
 %3 = alloc_stack $U.TangentVector // users: %11, %13, %25, %9, %75
 %4 = alloc_stack $V.TangentVector // users: %69, %59, %61, %57, %74
 %5 = alloc_stack $U.TangentVector // users: %44, %46, %56, %42, %73
 debug_value_addr %0 : $*T.TangentVector, let, name "direction", argno 1 // id: %6
 debug_value_addr %1 : $*T, var, name "self", argno 2 // id: %7

%8 = struct_element_addr %0 : $*T.TangentVector, #T.TangentVector.u1 // user: %9
 copy_addr [take] %8 to [initialization] %3 : $*U.TangentVector // id: %9
 %10 = struct_element_addr %1 : $*T, #T.u1 // users: %27, %15, %12
 debug_value_addr %3 : $*U.TangentVector, let, name "direction", argno 1 // id: %11
 debug_value_addr %10 : $*U, var, name "self", argno 2 // id: %12

...
 %25 = struct_element_addr %3 : $*U.TangentVector, #U.TangentVector.v // user: %26
 copy_addr [take] %25 to [initialization] %2 : $*V.TangentVector // id: %26
 %27 = struct_element_addr %10 : $*U, #U.v // users: %40, %32, %29
 debug_value_addr %2 : $*V.TangentVector, let, name "direction", argno 1 // id: %28
 debug_value_addr %27 : $*V, var, name "self", argno 2 // id: %29

...
 %41 = struct_element_addr %0 : $*T.TangentVector, #T.TangentVector.u2 // user: %42
 copy_addr [take] %41 to [initialization] %5 : $*U.TangentVector // id: %42
 %43 = struct_element_addr %1 : $*T, #T.u2 // users: %58, %48, %45
 debug_value_addr %5 : $*U.TangentVector, let, name "direction", argno 1 // id: %44
 debug_value_addr %43 : $*U, var, name "self", argno 2 // id: %45

...
 %56 = struct_element_addr %5 : $*U.TangentVector, #U.TangentVector.v // user: %57
 copy_addr [take] %56 to [initialization] %4 : $*V.TangentVector // id: %57
 %58 = struct_element_addr %43 : $*U, #U.v // users: %71, %63, %60
 debug_value_addr %4 : $*V.TangentVector, let, name "direction", argno 1 // id: %59
 debug_value_addr %58 : $*V, var, name "self", argno 2 // id: %60

...
} // end sil function '$s4main1TV4move5alongyAC13TangentVectorV_tF'

Is it legal to have multiple debug_value_addr of different SIL addresses (aggregates and their projections) with the same type/name/argno? It seems like this may be a conflict, resulting in the LLVM "overlapping fragments" assertion failure.

@eeckstein
Copy link
Member

@adrian-prantl any thoughts?

@compnerd
Copy link
Collaborator Author

@dan-zheng I think that the reason might be that _Differentiation is not enabled by default. Some how it was enabled when I built - which might have been an artifact of a partial clean build on my build.

@eeckstein it just needs build-script --extra-cmake-options="-DSWIFT_ENABLE_EXPERIMENTAL_DIFFERENTIABLE_PROGRAMMING=YES". Sorry about that, I thought was default due to my build.

@compnerd
Copy link
Collaborator Author

Assertion failure:

swift-frontend: /SourceCache/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp:572: void llvm::DwarfExpression::addFragmentOffset(const llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits && "overlapping or duplicate fragments"' failed.
...
3.      Running pass 'X86 Assembly Printer' on function '@"$s4main1TV4move5alongyAC13TangentVectorV_tF"'

This is using the current trunk build of swiftc to ensure that -disable-llvm-optzns still lowers the coroutine IR to allow using LLVM tooling.

swiftc -parse-as-library -O -g -I /tmp -emit-ir /tmp/reduced.swift -o - -module-name main -Xfrontend -disable-llvm-optzns

This results in the following extracted IR:

define hidden swiftcc void @"$s4main1TV4move5alongyAC13TangentVectorV_tF"(%T4main1TV13TangentVectorV* noalias nocapture dereferenceable(57) %0, %T4main1TV* nocapture swiftself dereferenceable(57) %1) #&#8203;0 !dbg !541 {
entry:
  ...
   %3 = alloca %T4main1UV13TangentVectorV, align 8 
 call void @llvm.dbg.declare(metadata %T4main1UV13TangentVectorV* %3, metadata !556, metadata !DIExpression()), !dbg !557
  ...
  %5 = alloca %T4main1UV13TangentVectorV, align 8 
 call void @llvm.dbg.declare(metadata %T4main1UV13TangentVectorV* %5, metadata !556, metadata !DIExpression()), !dbg !557
  ...
}
...
!0 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !1, producer: "Swift version 5.3-dev (LLVM cd34624440cb40a, Swift 44ac558e3243ea3)", isOptimized: true, runtimeVersion: 5, emissionKind: FullDebug, enums: !2, imports: !3)
!1 = !DIFile(filename: "/tmp/reduced.swift", directory: "/SourceCache") 
!2 = !{}
!3 = !{!4, !6, !8, !10}  
!4 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !1, entity: !5, file: !1)
!5 = !DIModule(scope: null, name: "main", includePath: "/tmp")                   
!6 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !1, entity: !7, file: !1)
!7 = !DIModule(scope: null, name: "Swift", includePath: "/BinaryCache/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/linux/Swift.swiftmodule/x86_64-unknown-linux-gnu.swiftmodule")
!8 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !1, entity: !9, file: !1, line: 27)
!9 = !DIModule(scope: null, name: "_Differentiation", includePath: "/BinaryCache/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/linux/_Differentiation.swiftmodule/x86_64-unknown-linux-gnu.swiftmodule")
!10 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !1, entity: !11, file: !1, line: 28)
!11 = !DIModule(scope: null, name: "M", includePath: "/tmp/M.swiftmodule")
...
!127 = !DIFile(filename: "<compiler-generated>", directory: "")
...
!131 = !DICompositeType(tag: DW_TAG_structure_type, name: "U", scope: !5, file: !1, size: 200, elements: !2, runtimeLang: DW_LANG_Swift, identifier: "$s4main1UVD")
...
!139 = !DICompositeType(tag: DW_TAG_structure_type, name: "$sytD", file: !1, elements: !2, runtimeLang: DW_LANG_Swift, identifier: "$sytD")
...
!181 = !DICompositeType(tag: DW_TAG_structure_type, name: "TangentVector", scope: !131, file: !1, size: 200, elements: !2, runtimeLang: DW_LANG_Swift, identifier: "$s4main1UV13TangentVectorVD")
...
!242 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !181)
...
!551 = distinct !DISubprogram(name: "move", linkageName: "$s4main1UV4move5alongyAC13TangentVectorV_tF", scope: !131, file: !127, type: !552, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!552 = !DISubroutineType(types: !553)                                            
!553 = !{!139, !181, !131} 
...
!556 = !DILocalVariable(name: "direction", arg: 1, scope: !551, file: !1, type: !242, flags: DIFlagArtificial)

The interesting thing here is that there are two local variable definitions %3 and %5 which have the same type and name (!556) which indicate that both allocations are the same argument (though the synthesis here is artificial). Is this permitted in the metadata? Creating two separate stack allocations for the variable and copying into the storage is reasonable, but I don't know if the debug information structure is setup to accommodate something like that, but would explain the resulting conflicting fragments if they are both sliced the same way. If this is permitted, then it is likely that SRoA is not expecting something like this (or the assertion is overly strict). If this is not permitted, it would be an issue for the frontend to ensure that the IR is well formed.

@vedantk
Copy link
Member

vedantk commented Jul 29, 2020

If the same variable (identified by ![](DILocalVariable metadata) is indeed mapped to two different allocas, I believe that's a frontend bug. I'd expect fresh )DILocalVariables to be set up for the allocas %3 and %5. Otherwise, this is saying that the same variable lives in two different stack slots.

@compnerd
Copy link
Collaborator Author

@adrian-prantl - opt -sroa reduced.ll | llc -dwarf-format 4 -o /dev/null should reproduce the assertion with SRoA. However, I'm no longer convinced that the IR itself is well formed as two {{alloca}}s are mapping to the same variable.

@adrian-prantl
Copy link
Member

@vedantk Interesting point. I was thinking that this could be legal if an object is passed into an inlined function by reference and thus the inlined function's byref variable shares the memory with the original object in the caller. But you are right that the input could already be wrong, too.

@adrian-prantl
Copy link
Member

@compnerd Do you know which pass inserts the debug_value(_addr) that turns into the duplicate dbg.declare? Is it something differention-related?

@dan-zheng
Copy link
Collaborator

@adrian-prantl: LoadableByAddress inserts the duplicate debug_value_addr instructions - the issue seems not really related to differentiation.

Here is the SIL before and after LoadableByAddress: https://github.com/dan-zheng/swift/blob/SR-13263/test/DebugInfo/sr13263.sil-print#L72. The SIL after LoadableByAddress looks very similar to the LLVM IR with duplicate dbg.declare:

 *** SIL module after #&#8203;99, stage IRGen Preparation, pass 1: LoadableByAddress (loadable-address)
// T.move(along:)
sil hidden @$s4main1TV4move5alongyAC13TangentVectorV_tF : $@convention(method) (@in_guaranteed T.TangentVector, @inout T) -> () {
// %0 "direction" // users: %6, %8, %41
// %1 "self" // users: %10, %43, %7
bb0(%0 : $*T.TangentVector, %1 : $*T):
 %2 = alloc_stack $V.TangentVector // users: %38, %28, %30, %26, %76
 %3 = alloc_stack $U.TangentVector // users: %11, %13, %25, %9, %75
 %4 = alloc_stack $V.TangentVector // users: %69, %59, %61, %57, %74
 %5 = alloc_stack $U.TangentVector // users: %44, %46, %56, %42, %73
 debug_value_addr %0 : $*T.TangentVector, let, name "direction", argno 1 // id: %6
 debug_value_addr %1 : $*T, var, name "self", argno 2 // id: %7

 %8 = struct_element_addr %0 : $*T.TangentVector, #T.TangentVector.u1 // user: %9
 copy_addr [take] %8 to [initialization] %3 : $*U.TangentVector // id: %9
 %10 = struct_element_addr %1 : $*T, #T.u1 // users: %27, %15, %12
 debug_value_addr %3 : $*U.TangentVector, let, name "direction", argno 1 // id: %11
 debug_value_addr %10 : $*U, var, name "self", argno 2 // id: %12

  ...
 %25 = struct_element_addr %3 : $*U.TangentVector, #U.TangentVector.v // user: %26
 copy_addr [take] %25 to [initialization] %2 : $*V.TangentVector // id: %26
 %27 = struct_element_addr %10 : $*U, #U.v // users: %40, %32, %29
 debug_value_addr %2 : $*V.TangentVector, let, name "direction", argno 1 // id: %28
 debug_value_addr %27 : $*V, var, name "self", argno 2 // id: %29

  ...
 %41 = struct_element_addr %0 : $*T.TangentVector, #T.TangentVector.u2 // user: %42
 copy_addr [take] %41 to [initialization] %5 : $*U.TangentVector // id: %42
 %43 = struct_element_addr %1 : $*T, #T.u2 // users: %58, %48, %45
 debug_value_addr %5 : $*U.TangentVector, let, name "direction", argno 1 // id: %44
 debug_value_addr %43 : $*U, var, name "self", argno 2 // id: %45

  ...
 %56 = struct_element_addr %5 : $*U.TangentVector, #U.TangentVector.v // user: %57
 copy_addr [take] %56 to [initialization] %4 : $*V.TangentVector // id: %57
 %58 = struct_element_addr %43 : $*U, #U.v // users: %71, %63, %60
 debug_value_addr %4 : $*V.TangentVector, let, name "direction", argno 1 // id: %59
 debug_value_addr %58 : $*V, var, name "self", argno 2 // id: %60

  ...
} // end sil function '$s4main1TV4move5alongyAC13TangentVectorV_tF'

We confirmed that disabling LoadableByAddress fixes the LLVM "overlapping debug info fragments" assertion failure. Specifically, commenting out these lines from LoadableByAddress fixes the assertion failure:

SILBuilderWithScope debugBuilder(instr);
debugBuilder.createDebugValueAddr(instr->getLoc(), currOperand,
*instr->getVarInfo());
.

Is this info useful to you? Could there be a bug in the LBA debug info propagation (or a bad interaction with inlining)?

@eeckstein
Copy link
Member

I could reproduce it now, thanks!
I don't know what's really wrong with the debug info here. LBA only converts debug_value into debug_value_addr (which should have the same semantics, just a different representation of the value).

@adrian-prantl Can you please take a look?

@compnerd
Copy link
Collaborator Author

@eeckstein I thought there is a small semantic difference between debug_value and debug_value_addr in that the former is an assignment and the latter is a declaration and needs to be indirected (e.g. via a GEP). Is that understanding flawed?

@adrian-prantl the odd debug information appears with the LBA pass.

@eeckstein
Copy link
Member

Well, ``debug_value_addr`` is just the address-version of ``debug_value``. The only difference should be that with the first, the value is in memory, with the second, the value is an SSA-value.
(maybe that's what you meant, anyway)

@vedantk
Copy link
Member

vedantk commented Jul 30, 2020

@eeckstein Whichever SIL debug intrinsic is used (debug_value/debug_value_addr), if the storage for the variable is an alloca, the expectation is that there is a single/unique alloca for the variable that's live throughout the function. If that's not compatible with swift optimizations, we can find a way to fix that: llvm has a way to describe a variable whose address changes.

Stepping back a bit, I'm not sure that the pre-pass SIL is correct. It looks like there are two assignments to the variable "direction", but they have different types (`$T.TangentVector` vs. `$U.TangentVector`).

```
bb0(%0 : $T.TangentVector, %1 : $*T):
debug_value %0 : $T.TangentVector, let, name "direction", argno 1 // id: %2
%4 = struct_extract %0 : $T.TangentVector, #T.TangentVector.u1 // users: %19, %8, %6
debug_value %4 : $U.TangentVector, let, name "direction", argno 1 // id: %6
```

What's the intended meaning? Is there supposed to be one variable ("direction") that changes value to `struct_extract %0`? Would it be preferable to simply omit the first `debug_value`?

@dan-zheng
Copy link
Collaborator

@vedantk: thanks for the catch about the pre-LoadableByAddress SIL.

The multiple debug_value instructions appear after inlining, when U.move(along: ) is inlined into T.move(along: ). Full SIL here:

  *** SIL function after  #&#8203;6270, stage HighLevel,Function+EarlyLoopOpt, pass 18: EarlyInliner (early-inline)
// T.move(along:)
sil hidden @$s4main1TV4move5alongyAC13TangentVectorV_tF : $@convention(method) (@guaranteed T.TangentVector, @inout T) -> () {
// %0 "direction"                                 // users: %36, %4, %2
// %1 "self"                                      // users: %5, %37, %3
bb0(%0 : $T.TangentVector, %1 : $*T):
  debug_value %0 : $T.TangentVector, let, name "direction", argno 1 // id: %2
  debug_value_addr %1 : $*T, var, name "self", argno 2 // id: %3
  %4 = struct_extract %0 : $T.TangentVector, #T.TangentVector.u1 // users: %20, %8, %6
  %5 = struct_element_addr %1 : $*T, #T.u1        // users: %21, %9, %7
  debug_value %4 : $U.TangentVector, let, name "direction", argno 1 // id: %6
  debug_value_addr %5 : $*U, var, name "self", argno 2 // id: %7

U.move(along: ) and T.move(along: ) both have parameters named self and direction.

Is it right for inlining to preserve these SIL debug_value/debug_value_addr instructions, or do the instructions conflict (because they have the same name and argno but different types)?
If there is a conflict, does anyone know the proper way to fix it? @adrian-prantl


Here's what the relevant part of the original Swift code looks like (with manually written versions of compiler-synthesized code).

@eeckstein
Copy link
Member

@vedantkI'm not really familiar with the debug info model. This would be a question for @adrian-prantl

@swift-ci
Copy link
Collaborator

Comment by Fan Jiang (JIRA)

Encountered the same bug today when I try to build swift-apis from TensorFlow. debuginfo is indeed generated twice.

philipturner added a commit to philipturner/s4tf that referenced this issue Jul 5, 2022
philipturner added a commit to s4tf/s4tf that referenced this issue Jul 6, 2022
* Initial support for release toolchains

* Fix typo

* Remove fatal error

* Comment out x10_training_loop for Colab

* Make `Mergeable.stack` differentiable, working around apple/swift#59876

* Remove #available(macOS 9999, *) restriction

* Enable RNN tests

* Re-enable tensorflow#1162

* Allow Array replaceSubrange

* Fit within 100 spaces

* Type fix "partecipating" -> "participating"

* Remove redundant same-type constraint

* Remove deprecated Dataset API and reposition Zip2TensorGroup

* Refactor tests

* Refactor X10 tests

* Fix failing tests on macOS + arm64

* Remove workarounds for apple/swift#55703 (SR-13263)

* Enable ops_test.swift

* Optimize ops_test.swift

* Optimize more tests

* Rename gradient(at:in) to gradient(at:of:)

* Rename argument label in withoutDerivative

* Enable tests blocked by reflection crash

* Workaround for apple/swift#59135 on dev toolchains

* Fix tests for Colab

* Attempt to speed up tests on Colab

* Revert changes to tests

* Fix tests on Colab NVIDIA GPU

* Revert specializations for NVIDIA GPUs
asavonic added a commit to asavonic/swift that referenced this issue Jun 19, 2023
LLVM seems to determine a variable instance as a combination of DILocalVariable
and DILocation. Therefore if multiple llvm.dbg.declare have the same
variable/location parameters, they are considered to be referencing the same
instance of variable.

Swift IRGen emits a set of llvm.dbg.declare calls for every variable
instance (with unique SILDebugScope), so it is important that these calls have
distinct variable/location parameters. Otherwise their DIExpression may be
incorrect when treated as referencing the same variable. For example, if they
have a DIExpression with fragments, we will see this as multiple declarations of
the same fragment. LLVM detects this and crashes with assertion failure:

DwarfExpression.cpp:679: void llvm::DwarfExpression::addFragmentOffset(const
llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits &&
"overlapping or duplicate fragments"' failed.

The patch resolves apple#55703. The LIT test (debug_scope_distinct.swift) is the
reproducer from that issue.
asavonic added a commit to asavonic/swift that referenced this issue Jun 22, 2023
LLVM seems to determine a variable instance as a combination of DILocalVariable
and DILocation. Therefore if multiple llvm.dbg.declare have the same
variable/location parameters, they are considered to be referencing the same
instance of variable.

Swift IRGen emits a set of llvm.dbg.declare calls for every variable
instance (with unique SILDebugScope), so it is important that these calls have
distinct variable/location parameters. Otherwise their DIExpression may be
incorrect when treated as referencing the same variable. For example, if they
have a DIExpression with fragments, we will see this as multiple declarations of
the same fragment. LLVM detects this and crashes with assertion failure:

DwarfExpression.cpp:679: void llvm::DwarfExpression::addFragmentOffset(const
llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits &&
"overlapping or duplicate fragments"' failed.

The patch resolves apple#55703. The LIT test (debug_scope_distinct.swift) is the
reproducer from that issue.
asavonic added a commit to asavonic/swift that referenced this issue Jun 28, 2023
LLVM seems to determine a variable instance as a combination of DILocalVariable
and DILocation. Therefore if multiple llvm.dbg.declare have the same
variable/location parameters, they are considered to be referencing the same
instance of variable.

Swift IRGen emits a set of llvm.dbg.declare calls for every variable
instance (with unique SILDebugScope), so it is important that these calls have
distinct variable/location parameters. Otherwise their DIExpression may be
incorrect when treated as referencing the same variable. For example, if they
have a DIExpression with fragments, we will see this as multiple declarations of
the same fragment. LLVM detects this and crashes with assertion failure:

DwarfExpression.cpp:679: void llvm::DwarfExpression::addFragmentOffset(const
llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits &&
"overlapping or duplicate fragments"' failed.

The patch resolves apple#55703. The LIT test (debug_scope_distinct.swift) is the
reproducer from that issue.
asavonic added a commit to asavonic/swift that referenced this issue Jun 29, 2023
LLVM seems to determine a variable instance as a combination of DILocalVariable
and DILocation. Therefore if multiple llvm.dbg.declare have the same
variable/location parameters, they are considered to be referencing the same
instance of variable.

Swift IRGen emits a set of llvm.dbg.declare calls for every variable
instance (with unique SILDebugScope), so it is important that these calls have
distinct variable/location parameters. Otherwise their DIExpression may be
incorrect when treated as referencing the same variable. For example, if they
have a DIExpression with fragments, we will see this as multiple declarations of
the same fragment. LLVM detects this and crashes with assertion failure:

DwarfExpression.cpp:679: void llvm::DwarfExpression::addFragmentOffset(const
llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits &&
"overlapping or duplicate fragments"' failed.

The patch resolves apple#55703. The LIT test (debug_scope_distinct.swift) is the
reproducer from that issue.
asavonic added a commit to asavonic/swift that referenced this issue Jul 24, 2023
The patch resolves apple#55703.

When the original function has a tuple result type, we should append
thunkedLinearMap as the last element of the tuple to match the function
declaration. Before this patch, the compiler used to wrap the original result
tuple and thunkedLinearMap into another tuple, and caused the verifier error.

Before the patch:

  return %{{.*}} : $((Float, Double), @callee_guaranteed (X.TangentVector) -> Float)

After the patch:

  return %{{.*}} : $(Float, Double, @callee_guaranteed (Float) -> X.TangentVector)
@AnthonyLatsis AnthonyLatsis added compiler The Swift compiler in itself IRGen LLVM IR generation debug info Area → compiler → IRGen: Debug information emission crash Bug: A crash, i.e., an abnormal termination of software swift 5.9 assertion failure Bug → crash: An assertion failure labels Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
assertion failure Bug → crash: An assertion failure bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software debug info Area → compiler → IRGen: Debug information emission IRGen LLVM IR generation swift 5.9
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants