Unsupported expression in static initializer?

Why is this not allowed?

LLVM ERROR: Unsupported expression in static initializer: zext (i64 ptrtoint (i32* @an_integer to i64) to i72)

It's the zext to a really weird type. Generally static initializers
are only supported if they map neatly to a target's relocation (or an
expression not needing any relocation).

You could probably emulate it with something (depending on endianness) like

    @var = global [i32*, i8] [i32* @an_integer, i8 0]

cast that to an i72* before each use and you probably can't tell the difference.


Hmm I’m not sure that workaround will work. Here’s the example code I’m trying to compile (zig language):

// create 2-bit and 3-bit unsigned integer types

const u2 = @intType(false, 2);
const u3 = @intType(false, 3);

// define a packed struct with bitfields. the third field c is a pointer which starts at 6 bits.
const Data = packed struct {
b: u3,
c: &i32,
d: u2,

var an_integer: i32 = 1234;

const data = Data {
.a = 1,
.b = 2,
.c = &an_integer,
.d = 3,

This generates the LLVM IR:

%Data = type <{ i72 }>

@an_integer = internal unnamed_addr global i32 1234, align 4
@data = internal unnamed_addr constant %Data <{ i72 or (i72 shl (i72 or (i72 zext (i64 ptrtoint (i32* @an_integer to i64) to i72), i72 184467440737095516160), i72 2), i72 3) }>, align 8

It’s an i72 because 3 + 3 + 64 + 2 = 72. The static initializer is trying to initialize the packed struct with bit fields correctly.

I did notice that this is not possible with clang. Equivalent C:

struct Foo {
unsigned a : 3;
unsigned b : 3;
unsigned long c : 64;
unsigned d : 2;
} attribute ((packed));

static int an_integer = 1234;

struct Foo foo = {1, 2, (unsigned long)&an_integer, 3};

unsigned long f(void) {
return foo.c;

Gives this compile error:

test.c:12:25: error: initializer element is not a compile-time constant
struct Foo foo = {1, 2, (unsigned long)&an_integer, 3};

Is this simply not possible to determine? Is this because the target does not support non-byte-aligned relocations at link time? Doesn’t the linker have a way to specify expressions such that this static initializer could work?

Ouch, yeah that's just not representable in any object format I know
of. You'll probably have to initialize it dynamically if you really
need support.