Question about @llvm.used global variable

Not sure if I should ask this question here or in the optimizations category. I’m sure there is plenty of overlap.

I have several frontends on OpenVMS that have the requirement that simply declaring an external routine (but not using it) gets the external symbol placed in the ELF symbol table. The existence of the symbol gets our linker to find/include the module that contains the external routine. [Such modules can then provide .init_array routines.]

Looking at the definition of @llvm.used (we’re currently using 10.0.1), I read:

"The @llvm.used global is an array which has appending linkage. This array contains a list of pointers to named global variables, functions and aliases which may optionally have a pointer cast formed of bitcast or getelementptr.

If a symbol appears in the @llvm.used list, then the compiler, assembler, and linker are required to treat the symbol as if there is a reference to the symbol that it cannot see (which is why they have to be named). For example, if a variable has internal linkage and no references other than that from the @llvm.used list, it cannot be deleted."

Since the description mentions “routines”, I was hoping this would result in the external routine ending up in the ELF symbol table despite it having no references. That doesn’t seem to be the case. When I enable optimization, the declared (but unused) routine doesn’t get emitted to the symbol table in spite of it being listed in @llvm.used.

Our current hack-around is to declare some static variables that are initialized with the address of the external routine and place those static variables into @llvm.used. Works but it results in static variables and possibly lots of relocations at link/load times.

Is this a bug or am I too optimistic about what the documentation says?

I think I’d consider this more of a missing feature than a bug; @llvm.used was designed for use with definitions.

That said, any implementation of this feature would look a lot like @llvm.used, so it seems reasonable to me to just extend it to do what you want here.

Oh, also, if you want a workaround, I’d suggest using module-level inline assembly. Something like module asm ".globl xxx" should do what you want.

Unless the symbol is weak, in which case you need .weak. Unless you’re using GNU as to assemble, at which point the symbol still won’t end up in the symbol table, though .set dummy, symbol seems to be good enough for achieving that.