This change should fix some who could not find referenced DIE issues.
For example, see https://github.com/apple/swift/issues/53940.
I created a demo.
main.swift is:
let foos: Set<Foo> = []
foo.swift is:
struct Foo: Equatable, Hashable {}
I use SPM to build these IRs:
// swift-tools-version: 5.6 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "demo", targets: [ .executableTarget( name: "demo", swiftSettings: [ .unsafeFlags(["-Xfrontend", "-lto=llvm-full", "-Xfrontend", "-emit-bc"]) ]), ] )
Then:
swift build -c release llvm-link .build/x86_64-unknown-linux-gnu/release/demo.build/foo.swift.o .build/x86_64-unknown-linux-gnu/release/demo.build/main.swift.o -o .build/lto.bc llc -filetype=obj .build/lto.bc -o .build/lto.o llvm-dwarfdump .build/lto.o --verify
Outputs:
... error: invalid DIE reference 0x00000097. Offset is in between DIEs: 0x0000008f: DW_TAG_inlined_subroutine [8] * (0x0000007c) DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x0097 => {0x00000097}) DW_AT_low_pc [DW_FORM_addr] (0x000000000000012b ".text") DW_AT_high_pc [DW_FORM_data4] (0x0000000f) DW_AT_call_file [DW_FORM_data1] ("/home/dianqk/Documents/demo/Sources/demo/main.swift") DW_AT_call_line [DW_FORM_data1] (0) Verifying unit: 2 / 2, "/home/dianqk/Documents/demo/Sources/demo/foo.swift" Verifying dwo Units... Errors detected.
I dumped the dwarf and found DW_TAG_structure_type("Foo") is owned by DW_TAG_compile_unit(main.swift), then some invalidating cross-unit references are found. It should be owned by DW_TAG_compile_unit(foo.swift).
To better (and completely) solve this problem, I think there are some general rules to consider.
We cannot freely share DIType with every CU in all cases.
It follows these rules:
- When a DIType has no successor node, the DIType can belong to any CU, and other CUs reference this.
- If there are (recursive) successor nodes and only if these successor nodes belong to the same CU, the DIType can share in a limited way, and this DIType must belong to the corresponding CU.
- When there are successor nodes, which scatter in different CUs, DIType cannot share.
However, it will be a major change to implement the above rules accurately.
So to solve the current problem, we need to make trade-offs.
Merge 2 and 3 rules, When there are successor nodes, DIType cannot share.
I modified a test case that correctly places a subprogram that does not need to share in the appropriate CU.
In addition, I added the above swift test case (I edited it to simpler) as a supplement.