Zero-sized globals in LLVM IR

Hello the list,

What is the correct type for a global of size zero? I need the compiler to be able to generate one, so that the linker will insert it at a specific position without perturbing the location of anything else in the section. I have tried a zero-length array (generates something at least one byte). At Nuno’s suggestion, I tried a structure with no fields. In release builds, this works correctly, but in debug builds it triggers an assertion that the type must be sized.

What is the recommended way of doing this?


I believe C says you can’t have one. Every variable must have a distinct address. I don’t know what LLVM IR says, but you could maybe insert an asm label.

I’m aware that C doesn’t permit this, but LLVM is intended to be a portable abstraction between source languages and target binary formats, and all supported object file formats do support it. In PE/COFF, this is the standard way of implementing the equivalent of the GNU linker’s __start_ magic symbols, for example.


Slightly off-topic, but out of curiosity, what’s the PE/COFF mechanism you’re intending to use? The standard one I’ve seen is grouped sections, i.e. you have section$A containing your start symbol, section$C containing your end symbol, and then everything in between is placed in section$B, so the linker ensures it’s sorted between the start and end symbols. The start and end symbols I’ve seen have always been sized the same as the other list entries, though I suppose you could make them zero-sized.

How did you come to the conclusion that a zero-length array generates something of at least of size 1? I don't see a significant difference between the assembly output of "@a1 = global [0 x i8] []" and "@a2 = global {} {}".

  .type a1,@object # @a1
  .globl a1
  .size a1, 0

  .type a2,@object # @a2
  .globl a2
  .p2align 3
  .size a2, 0

Subjectively, I'd consider "@a2 = global {} {}" to be the "idiomatic" way to define a zero-sized global. IMHO it shouldn't trigger an assertion.

Hi David,

You wrote

but in debug builds it triggers an assertion that the type must be sized

I am curious as to which specific assert you’re encountering.

Context: zero-sized structures and arrays are legal in the Go language; so far in our (in-progress) gollvm work we haven’t seen issues or asserts with these sorts of constructs.

Thanks, Than