<div dir="ltr">Hmm I'm not sure that workaround will work. Here's the example code I'm trying to compile (zig language):<div><br></div><div>// create 2-bit and 3-bit unsigned integer types</div><div><div>const u2 = @intType(false, 2);</div><div>const u3 = @intType(false, 3);</div><div><br></div><div>// define a packed struct with bitfields. the third field `c` is a pointer which starts at 6 bits.</div><div>const Data = packed struct {</div><div>    a: u3,</div><div>    b: u3,</div><div>    c: &i32,</div><div>    d: u2,</div><div>};</div><div><br></div><div>var an_integer: i32 = 1234;</div><div><br></div><div>const data = Data {</div><div>    .a = 1,</div><div>    .b = 2,</div><div>    .c = &an_integer,</div><div>    .d = 3,</div><div>};</div></div><div><br></div><div>This generates the LLVM IR:</div><div><br></div><div><div>%Data = type <{ i72 }></div><div><br></div><div>@an_integer = internal unnamed_addr global i32 1234, align 4</div><div>@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</div></div><div><br></div><div><br></div><div>It's an i72 because 3 + 3 + 64 + 2 = 72. The static initializer is trying to initialize the packed struct with bit fields correctly.</div><div><br></div><div>I did notice that this is not possible with clang. Equivalent C:</div><div><br></div><div><div>struct Foo {</div><div>    unsigned a : 3;</div><div>    unsigned b : 3;</div><div>    unsigned long c : 64;</div><div>    unsigned d : 2;</div><div>} __attribute__ ((__packed__));</div><div><br></div><div>static int an_integer = 1234;</div><div><br></div><div>struct Foo foo = {1, 2, (unsigned long)&an_integer, 3};</div><div><br></div><div>unsigned long f(void) {</div><div>    return foo.c;</div><div>}</div></div><div><br></div><div><br></div><div>Gives this compile error:</div><div><br></div><div><div>test.c:12:25: error: initializer element is not a compile-time constant</div><div>struct Foo foo = {1, 2, (unsigned long)&an_integer, 3};</div><div>                        ^~~~~~~~~~~~~~~~~~~~~~~~~~</div></div><div><br></div><div><br></div><div>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?</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 15, 2017 at 4:40 PM, Tim Northover <span dir="ltr"><<a href="mailto:t.p.northover@gmail.com" target="_blank">t.p.northover@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 15 February 2017 at 13:22, Andrew Kelley via llvm-dev<br>
<span class=""><<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br>
> LLVM ERROR: Unsupported expression in static initializer: zext (i64 ptrtoint<br>
> (i32* @an_integer to i64) to i72)<br>
<br>
</span>It's the zext to a really weird type. Generally static initializers<br>
are only supported if they map neatly to a target's relocation (or an<br>
expression not needing any relocation).<br>
<br>
You could probably emulate it with something (depending on endianness) like<br>
<br>
    @var = global [i32*, i8] [i32* @an_integer, i8 0]<br>
<br>
cast that to an i72* before each use and you probably can't tell the difference.<br>
<span class="HOEnZb"><font color="#888888"><br>
Tim/<br>
</font></span></blockquote></div><br></div>