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.