Skip to content

clang-20.1 starts to zero padding in global initializers #3253

Open
@karolherbst

Description

@karolherbst

I think this is something that needs to be worked around in the translator properly.

Starting with llvm/llvm-project@7a086e1 clang zero initializes in C dialects besides C++ all padding in static initializers, which do include Program scope variables in the global address space.

Assume code like this (OpenCL CTS test_basic progvar_prog_scope_misc):

input1.cl:

typedef struct { uchar c; uint i; } my_struct_t;

my_struct_t var = { 'a', 42 };

kernel void writer( uchar c, uint i ) {
  var.c = c;
  var.i = i;
}

and input2.cl:

typedef struct { uchar c; uint i; } my_struct_t;

extern my_struct_t var;

kernel void reader( global uchar* C, global uint* I ) {
  *C = var.c;
  *I = var.i;
}

The types of the global variable var ends up being different in the translation units:

@var = addrspace(1) global { i8, [3 x i8], i32 } { i8 97, [3 x i8] zeroinitializer, i32 42 }, align 4

vs

%struct.my_struct_t = type { i8, i32 }
@var = external addrspace(1) global %struct.my_struct_t, align 4

This also leads to different types for those variables on the SPIR-V level and therefore makes spirv-link fail with this: Type mismatch on symbol "var" between imported variable/function %47 and exported variable/function %13.

One could convince spirv-link to link variables together despite their different type, however this will cause access chains to point to the wrong members in some translation units.

I don't really know on which level this could be handled the best. I see a couple of options:

  • make clang not do it for OpenCL C
  • make LLVM add the padding fields also in kernels without initializers
  • make the translator treat imported global variables as opaque (give it some random type, like being a single byte) and cast pointers to that variable on use
  • add some lowering to spirv-link to pick one type and fix up all derefs (can be difficult, because how would the linker know what's padding and what's real).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions