Skip to content

"<unknown>:0: error: expected relocatable expression" when building std lib tests for 32-bit linux with stage2 LLVM #12014

Open
@andrewrk

Description

@andrewrk

Zig Version: 0.10.0-dev.2887+9a5c7b4b4

Repro:

$ stage2/bin/zig test ../lib/std/std.zig -target i386-linux-none
LLVM Emit Object... error: <unknown>:0: expected relocatable expression

Reduced LLVM IR:

source_filename = "test"
target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128"
target triple = "i386-unknown-linux-unknown"

%os.linux.io_uring_sqe = type { i8, i8, i16, i32, i64, i64, i32, i32, i64, i16, i16, i32, [2 x i64] }


@os.linux.io_uring.test.openat__anon_60060 = internal unnamed_addr constant [21 x i8] c"test_io_uring_openat\00", align 1
@0 = private unnamed_addr constant %os.linux.io_uring_sqe { i8 18, i8 0, i16 0, i32 -100, i64 0, i64 ptrtoint ([21 x i8]* @os.linux.io_uring.test.openat__anon_60060 to i64), i32 438, i32 524354, i64 858993459, i16 0, i16 0, i32 0, [2 x i64] zeroinitializer }, align 4

Confirmed happens with both LLVM 13.0.1 and LLVM 14.0.6.

The source code comes from here:

const path = "test_io_uring_openat";
defer std.fs.cwd().deleteFile(path) catch {};
const flags: u32 = os.O.CLOEXEC | os.O.RDWR | os.O.CREAT;
const mode: os.mode_t = 0o666;
const sqe_openat = try ring.openat(0x33333333, linux.AT.FDCWD, path, flags, mode);
try testing.expectEqual(linux.io_uring_sqe{
.opcode = .OPENAT,
.flags = 0,
.ioprio = 0,
.fd = linux.AT.FDCWD,
.off = 0,
.addr = @ptrToInt(path),

It's just a @ptrToInt on a string literal, inside a const struct literal. Stage2 emits it, correctly, like this:

@os.linux.io_uring.test.openat__anon_60060 = internal unnamed_addr constant [21 x i8] c"test_io_uring_openat\00", align 1

@1140 = private unnamed_addr constant %os.linux.io_uring_sqe { i8 18, i8 0, i16 0, i32 -100, i64 0, i64 ptrtoint ([21 x i8]* @os.linux.io_uring.test.openat__anon_60060 to i64), i32 438, i32 524354, i64 858993459, i16 0, i16 0, i32 0, [2 x i64] zeroinitializer }, align 4

Looks good. Why doesn't the issue happen with stage1? The answer is that stage1 failed to notice that the struct initializer should be constant, and initialized the struct at runtime, accidentally avoiding LLVM's bug:

  %60 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 0, !dbg !22452
  %61 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 1, !dbg !22453
  %62 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 2, !dbg !22454
  %63 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 3, !dbg !22455
  %64 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 4, !dbg !22456
  %65 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 5, !dbg !22457
  store i64 zext (i32 ptrtoint ([21 x i8]* @10355 to i32) to i64), i64* %65, align 4, !dbg !22458
  %66 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 6, !dbg !22459
  %67 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 7, !dbg !22460
  %68 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 8, !dbg !22461
  %69 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 9, !dbg !22462
  %70 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 10, !dbg !22463
  %71 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 11, !dbg !22464
  %72 = getelementptr inbounds %os.linux.io_uring_sqe, %os.linux.io_uring_sqe* %5, i32 0, i32 12, !dbg !22465
  store i8 18, i8* %60, align 1, !dbg !22452
  store i8 0, i8* %61, align 1, !dbg !22453
  store i16 0, i16* %62, align 2, !dbg !22454
  store i32 -100, i32* %63, align 4, !dbg !22455
  store i64 0, i64* %64, align 4, !dbg !22456
  store i32 438, i32* %66, align 4, !dbg !22459
  store i32 524354, i32* %67, align 4, !dbg !22460
  store i64 858993459, i64* %68, align 4, !dbg !22461
  store i16 0, i16* %69, align 2, !dbg !22462
  store i16 0, i16* %70, align 2, !dbg !22463
  store i32 0, i32* %71, align 4, !dbg !22464
  %73 = bitcast [2 x i64]* %72 to i8*, !dbg !22465
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %73, i8* align 4 bitcast ([2 x i64]* @10360 to i8*), i32 16, i1 false), !dbg !22465
  %74 = load %os.linux.io_uring_sqe*, %os.linux.io_uring_sqe** %sqe_openat, align 4, !dbg !22466
  %75 = bitcast %os.linux.io_uring_sqe* %74 to i8*, !dbg !22467
  %76 = bitcast %os.linux.io_uring_sqe* %6 to i8*, !dbg !22467
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %76, i8* align 4 %75, i32 64, i1 false), !dbg !22467
  %77 = call fastcc i16 @testing.expectEqual.2452(%builtin.StackTrace* %0, %os.linux.io_uring_sqe* %5, %os.linux.io_uring_sqe* %74), !dbg !22468

Upstream bug report: llvm/llvm-project#56400

Metadata

Metadata

Assignees

No one assigned

    Labels

    arch-arm32-bit ARMarch-x8632-bit x86backend-llvmThe LLVM backend outputs an LLVM IR Module.contributor friendlyThis issue is limited in scope and/or knowledge of Zig internals.frontendTokenization, parsing, AstGen, Sema, and Liveness.os-linuxupstreamAn issue with a third party project that Zig uses.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions