[llvm-dev] Unsupported expression in static initializer?

Andrew Kelley via llvm-dev llvm-dev at lists.llvm.org
Wed Feb 15 13:51:46 PST 2017


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 {
    a: u3,
    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?


On Wed, Feb 15, 2017 at 4:40 PM, Tim Northover <t.p.northover at gmail.com>
wrote:

> On 15 February 2017 at 13:22, Andrew Kelley via llvm-dev
> <llvm-dev at lists.llvm.org> wrote:
> > 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.
>
> Tim/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170215/ba96f6d5/attachment.html>


More information about the llvm-dev mailing list