KhronosGroup / KhronosGroup/SPIRV-LLVM-Translator
clang-20.1 starts to zero padding in global initializers
- Dominant language
- LLVM
- Stars
- 625
- Forks
- 279
- Avg merge
- 3d 5h
- Merged PRs (30d)
- 34
Description
I think this is something that needs to be worked around in the translator properly.
Starting with https://github.com/llvm/llvm-project/commit/7a086e1b2dc05f54afae3591614feede727601fa 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:
```opencl
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:
```opencl
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:
```llvm
@var = addrspace(1) global { i8, [3 x i8], i32 } { i8 97, [3 x i8] zeroinitializer, i32 42 }, align 4
```
vs
```llvm
%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).
Contributor guide
Research direction
Start with the OpenCL CTS test_basic progvar_prog_scope_misc and the input1.cl/input2.cl examples; inspect the generated LLVM IR declarations and definitions for var, then follow the SPIR-V output into spirv-link. Done means the two translation units link successfully without changing the struct member access layout or producing a type mismatch.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100