llvm-link is creating 32 and 64-bit versions of a struct

I have two bitcode files that I want to link together, using the command
llvm-link -o llvm-helpers.bc1 target/arm/op_helper.bc2 target/arm/helper.bc2

Both files define the struct %struct.ARMCPRegInfo. However, when I link them together, the resulting bitcode has two structs of different bitsizes, one ending with .32. As a result, some functions use the .32 type as an argument, which is not intended.

%struct.ARMCPRegInfo.32 = type { i8*, i8, i8, i8, i8, i8, i8, i32, i32, i32, i32, i8*, i64, i64, [2 x i64], i32 (%struct.CPUARMState*, %struct.ARMCPRegInfo.32*, i1), {}, void (%struct.CPUARMState*, %struct.ARMCPRegInfo.32*, i64), {}, void (%struct.CPUARMState*, %struct.ARMCPRegInfo.32*, i64), void (%struct.CPUARMState, %struct.ARMCPRegInfo. 32*)* }

%struct.ARMCPRegInfo = type { i8*, i8, i8, i8, i8, i8, i8, i32, i32, i32, i32, i8*, i64, i64, [2 x i64], i32 (%struct.CPUARMState*, %struct.ARMCPRegInfo*, i1), i64 (%struct.CPUARMState, %struct.ARMCPRegInfo*), void (%struct.CPUARMState, %struct.ARMCPRegInfo*, i64), i64 (%struct.CPUARMState, %struct.ARMCPRegInfo*), void (%struct. CPUARMState, %struct.ARMCPRegInfo*, i64), void (%struct.CPUARMState, %struct.ARMCPRegInfo*)* }

Why are two structs being created, and how do I prevent this from happening?

Hi Ray,

Both files define the struct `%struct.ARMCPRegInfo`. However, when I link them together, the resulting bitcode has two structs of different bitsizes, one ending with `.32`. As a result, some functions use the `.32` type as an argument, which is not intended.

What makes you think they have different sizes? LLVM claims they're
both 88 bytes for me.

%struct.ARMCPRegInfo.32 = type { i8*, i8, i8, i8, i8, i8, i8, i32, i32, i32, i32, i8*, i64, i64, [2 x i64], i32 (%struct.CPUARMState*, %struct.ARMCPRegInfo.32*, i1)*, {}*, void (%struct.CPUARMState*, %struct.ARMCPRegInfo.32*, i64)*, {}*, void (%struct.CPUARMState*, %struct.ARMCPRegInfo.32*, i64)*, void (%struct.CPUARMState*, %struct.ARMCPRegInfo. 32*)* }

%struct.ARMCPRegInfo = type { i8*, i8, i8, i8, i8, i8, i8, i32, i32, i32, i32, i8*, i64, i64, [2 x i64], i32 (%struct.CPUARMState*, %struct.ARMCPRegInfo*, i1)*, i64 (%struct.CPUARMState*, %struct.ARMCPRegInfo*)*, void (%struct.CPUARMState*, %struct.ARMCPRegInfo*, i64)*, i64 (%struct.CPUARMState*, %struct.ARMCPRegInfo*)*, void (%struct. CPUARMState*, %struct.ARMCPRegInfo*, i64)*, void (%struct.CPUARMState*, %struct.ARMCPRegInfo*)* }

Why are two structs being created, and how do I prevent this from happening?

The critical difference is the "{}*" parameter in the middle, which is
a more fleshed out function pointer type in the second struct. LLVM
will only merge types that are identical (otherwise it would have to
add or remove cast instructions from functions which goes well beyond
linking), so if you really want to stop the rename you have to change
how you generate these types.

But really you should probably try to stop relying on types being
unique, or the names of types at all, in LLVM IR. They're not designed
to be used like that; they're really only named at all as an aid to
human comprehension. Especially, Clang will not guarantee identical
types in the IR it generates (for various reasons).

Cheers.

Tim.