Linking two modules with @llvm.global_ctors arrays causes a linker error to occur

Hi, I’m trying to link 2 llvm::Module instances, but I’m having some trouble. In order to link my modules I’m using the llvm::Linker class and everything seems to work in simple usecases, but it sometimes fails in more complex ones, as is to be expected since that may require some more work on my end. Specifically, I can’t get the linker to link two modules that both contain a global ctors array. Take the following two modules as an example:

Module A

; ModuleID = 'lang'
source_filename = "lang"

@0 = constant [14 x i8] c"value is: %i\0A\00"
@msg = global ptr null
@llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @__global_init_msg, ptr null }]

define void @__global_init_msg() {
  store ptr @0, ptr @msg, align 8
  ret void
}

Module B

; ModuleID = 'lang'
source_filename = "lang"

@x = global i32 0
@llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @__global_init_x, ptr null }]

define void @__global_init_x() {
  store i32 22, ptr @x, align 4
  ret void
}

When I attempt to link these modules I get the following error:
Appending variables with different element types!

I’m not entirely sure how I should go about fixing this issue, my first guess would be to just extract the global ctors arrays from both modules before I link them, manually concatenate them, and insert them into the new module that is created from linking the two modules, but that feels a bit overcomplicated and there is probably a built in way/something I’m not noticing.

Any help/advice is greatly appreciated.

Your modules are broken:

error: constant expression type mismatch: got type '[1 x { i32, ptr, ptr }]' but expected '[0 x { i32, ptr, ptr }]'
@llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @__global_init_msg, ptr null }]

Use [1 x ... and try again.

I get the same error even if I include 1x and so on.

Are they in the same LLVMContext? If not, the types will be equivalent but pointer equality won’t work; LLVM assumes types are uniqued so pointer equality works.

1 Like

This was it, I wasn’t using the same context, thanks a bunch.