ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.37k stars 2.51k forks source link

ptrToInt causes compiler segfault with microzig #15712

Open kuon opened 1 year ago

kuon commented 1 year ago

When compiling the following repo with zig version 0.11.0-dev.3138+87de8212ad I get a compiler segfault.

I was not able to isolate the issue to a simple example so I made a repo.

Repo: https://github.com/kuon/zig-bug-2

Error below. I got a coredump, but my zig is not built in debug mode so it doesn't help much. If you cannot reproduce with my repo above, I'll rebuild in debug.

zig build -Drelease=true
zig build-exe bug2 ReleaseFast thumb-freestanding-none: error: the following command terminated unexpectedly:
/usr/bin/zig build-exe /home/kuon/Playground/zig-bug-2/libs/microzig/src/start.zig -fno-strip -OReleaseFast --cache-dir /home/kuon/Playground/zig-bug-2/zig-cache --global-cache-dir /home/kuon/.cache/zig --name bug2 -fcompiler-rt -fsingle-threaded -target thumb-freestanding-none -mcpu cortex_m0plus --script /home/kuon/Playground/zig-bug-2/zig-cache/microzig/a7289ec13926489f324ef84143336b92/STM32L0x1_ARM Cortex-M0+.ld --mod cpu:microzig:/home/kuon/Playground/zig-bug-2/libs/microzig/src/modules/cpus/cortex-m.zig --mod config::/home/kuon/Playground/zig-bug-2/zig-cache/microzig/config-dd06784b0c0c6ff6ae747202d5132cc8.zig --mod app:microzig:/home/kuon/Playground/zig-bug-2/src/main.zig --mod microzig:config,chip,cpu:/home/kuon/Playground/zig-bug-2/libs/microzig/src/microzig.zig --mod chip:microzig:/home/kuon/Playground/zig-bug-2/src/registers.zig --deps app,microzig -fno-lto --listen=- 
Build Summary: 1/4 steps succeeded; 1 failed (disable with -fno-summary)
install transitive failure
└─ install bug2 transitive failure
   └─ zig build-exe bug2 ReleaseFast thumb-freestanding-none failure
      └─ linkerscript success
error: the following build command failed with exit code 1:
/home/kuon/Playground/zig-bug-2/zig-cache/o/8b257d72eafa2970f751537206867168/build /usr/bin/zig /home/kuon/Playground/zig-bug-2 /home/kuon/Playground/zig-bug-2/zig-cache /home/kuon/.cache/zig -Drelease=true
matu3ba commented 1 year ago

The file src/registers.zig looks huge (>5k LOC). Can you reduce it further?

kuon commented 1 year ago

I trimmed the file.

llogick commented 1 year ago

I happen to have a debug build, so if it'd help:

zig build-exe bug2 Debug thumb-freestanding-none: error: thread 14955 panic: reached unreachable code
Analyzing libs/microzig/src/start.zig: start.zig:microzig_main
      %348 = dbg_stmt(27, 13)
      %349 = call(.auto, %203, []) 
    > %350 = is_non_err(%349) 
      %351 = condbr(%350, {
        %353 = err_union_payload_unsafe(%349) 
        %399 = break(%352, %353)
      }, {
        %354 = save_err_ret_index(@Zir.Inst.Ref.none)
        %355 = err_union_code(%349) 
        %356 = block({
          %357 = dbg_block_begin()
          %358 = dbg_stmt(31, 13)
          %359 = block_comptime({
            %360 = int(64)
            %361 = array_type(%360, @Zir.Inst.Ref.u8_type) 
            %362 = break(%359, %361)
          }) 
          %363 = alloc_mut(%359) 
          %364 = store_node(%363, @Zir.Inst.Ref.undef) 
          %365 = dbg_var_ptr(%363, "msg")
          %366 = dbg_stmt(32, 13)
          %384 = block({
            %367 = decl_ref("std") 
            %368 = dbg_stmt(32, 23)
            %369 = field_ptr(%367, "fmt") 
            %370 = dbg_stmt(32, 27)
            %371 = field_call_bind(%369, "bufPrint") 
            %372 = dbg_stmt(32, 36)
            %373 = call(.auto, %371, [
              {
                %374 = break_inline(%373, %363)
              },
              {
                %375 = str("main() returned error {s}")
                %376 = break_inline(%373, %375)
              },
              {
                %377 = as_node(@Zir.Inst.Ref.anyerror_type, %355) 
                %378 = dbg_stmt(32, 74)
                %379 = error_name(%377) 
                %380 = array_init_anon({%379}) 
                %381 = break_inline(%373, %380)
              },
            ]) 
            %382 = is_non_err(%373) 
            %383 = condbr(%382, {
              %385 = err_union_payload_unsafe(%373) 
              %386 = as_node(@Zir.Inst.Ref.const_slice_u8_type, %385) 
              %392 = break(%384, %386)
            }, {
              %387 = save_err_ret_index(@Zir.Inst.Ref.none)
              %388 = dbg_stmt(32, 98)
              %389 = str("main() returned error.")
              %390 = as_node(@Zir.Inst.Ref.const_slice_u8_type, %389) 
              %391 = panic(%390) 
            }) 
          }) 
          %393 = as_node(@Zir.Inst.Ref.const_slice_u8_type, %384) 
          %394 = panic(%393) 
          %395 = dbg_block_end()
          %396 = restore_err_ret_index(%356, @Zir.Inst.Ref.none)
          %397 = break(%356, @Zir.Inst.Ref.void_value)
        }) 
        %398 = restore_err_ret_index(%352, @Zir.Inst.Ref.none)
        %400 = break(%352, @Zir.Inst.Ref.void_value)
      }) 
    For full context, use the command
      zig ast-check -t libs/microzig/src/start.zig

  in libs/microzig/src/start.zig: start.zig:microzig_main
    > %352 = block({%348..%351}) 
  in libs/microzig/src/start.zig: start.zig:microzig_main
    > %345 = block({%346..%404}) 
  in libs/microzig/src/start.zig: start.zig:microzig_main
    > %342 = condbr(%341, {%344..%416}, {%406..%417}) 
  in libs/microzig/src/start.zig: start.zig:microzig_main
    > %343 = block({%336..%342}) 
  in libs/microzig/src/start.zig: start.zig:microzig_main
    > %176 = block({%177..%427}) 

/home/rad/lab/zig/src/value.zig:1161:21: 0x6584d6c in toBigIntAdvanced (zig)
            else => unreachable,
                    ^
/home/rad/lab/zig/src/value.zig:1100:36: 0x61e0b5c in toBigInt (zig)
        return val.toBigIntAdvanced(space, target, null) catch unreachable;
                                   ^
/home/rad/lab/zig/src/codegen/llvm.zig:3279:51: 0x5fcfcbb in lowerValue (zig)
                    const bigint = tv.val.toBigInt(&bigint_space, target);
                                                  ^
/home/rad/lab/zig/src/codegen/llvm.zig:4502:48: 0x6997f6f in resolveValue (zig)
        const llvm_val = try self.dg.lowerValue(tv);
                                               ^
/home/rad/lab/zig/src/codegen/llvm.zig:4493:47: 0x699847f in resolveInst (zig)
        const llvm_val = try self.resolveValue(.{
                                              ^
/home/rad/lab/zig/src/codegen/llvm.zig:8209:49: 0x69c899f in airStore (zig)
        const src_operand = try self.resolveInst(bin_op.rhs);
                                                ^
/home/rad/lab/zig/src/codegen/llvm.zig:4652:53: 0x64059ed in genBody (zig)
                .store          => try self.airStore(inst, false),
                                                    ^
/home/rad/lab/zig/src/codegen/llvm.zig:1232:19: 0x64008b4 in updateFunc (zig)
        fg.genBody(air.getMainBody()) catch |err| switch (err) {
                  ^
/home/rad/lab/zig/src/link/Elf.zig:2562:74: 0x640920e in updateFunc (zig)
        if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(module, func, air, liveness);
                                                                         ^
/home/rad/lab/zig/src/link.zig:578:77: 0x6164f87 in updateFunc (zig)
            .elf   => return @fieldParentPtr(Elf,   "base", base).updateFunc(module, func, air, liveness),
                                                                            ^
/home/rad/lab/zig/src/Module.zig:4392:37: 0x5f6eefc in ensureFuncBodyAnalyzed (zig)
            comp.bin_file.updateFunc(mod, func, air, liveness) catch |err| switch (err) {
                                    ^
/home/rad/lab/zig/src/Sema.zig:28906:36: 0x6b04557 in ensureFuncBodyAnalyzed (zig)
    sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
                                   ^
/home/rad/lab/zig/src/Sema.zig:31577:40: 0x6549d46 in resolveInferredErrorSet (zig)
        try sema.ensureFuncBodyAnalyzed(ies.func);
                                       ^
/home/rad/lab/zig/src/Sema.zig:29195:49: 0x650b633 in analyzeIsNonErrComptimeOnly (zig)
                try sema.resolveInferredErrorSet(block, src, ies);
                                                ^
/home/rad/lab/zig/src/Sema.zig:29222:56: 0x6a4e0dc in analyzeIsNonErr (zig)
    const result = try sema.analyzeIsNonErrComptimeOnly(block, src, operand);
                                                       ^
/home/rad/lab/zig/src/Sema.zig:16940:32: 0x64531f7 in zirIsNonErr (zig)
    return sema.analyzeIsNonErr(block, src, operand);
                               ^
/home/rad/lab/zig/src/Sema.zig:966:66: 0x617ef20 in analyzeBodyInner (zig)
            .is_non_err                   => try sema.zirIsNonErr(block, inst),
                                                                 ^
/home/rad/lab/zig/src/Sema.zig:5506:34: 0x6a72a89 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/rad/lab/zig/src/Sema.zig:5489:33: 0x650eb38 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/rad/lab/zig/src/Sema.zig:1462:49: 0x6190674 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/rad/lab/zig/src/Sema.zig:5506:34: 0x6a72a89 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/rad/lab/zig/src/Sema.zig:5489:33: 0x650eb38 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/rad/lab/zig/src/Sema.zig:1462:49: 0x6190674 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/rad/lab/zig/src/Sema.zig:16989:37: 0x6509452 in zirCondbr (zig)
        return sema.analyzeBodyInner(parent_block, body);
                                    ^
/home/rad/lab/zig/src/Sema.zig:1571:61: 0x618d3bb in analyzeBodyInner (zig)
                if (!block.is_comptime) break sema.zirCondbr(block, inst);
                                                            ^
/home/rad/lab/zig/src/Sema.zig:5506:34: 0x6a72a89 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/rad/lab/zig/src/Sema.zig:5489:33: 0x650eb38 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/rad/lab/zig/src/Sema.zig:1462:49: 0x6190674 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/rad/lab/zig/src/Sema.zig:5506:34: 0x6a72a89 in resolveBlockBody (zig)
        if (sema.analyzeBodyInner(child_block, body)) |_| {
                                 ^
/home/rad/lab/zig/src/Sema.zig:5489:33: 0x650eb38 in zirBlock (zig)
    return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
                                ^
/home/rad/lab/zig/src/Sema.zig:1462:49: 0x6190674 in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[inst] == .block_comptime);
                                                ^
/home/rad/lab/zig/src/Sema.zig:804:30: 0x63eaa78 in analyzeBody (zig)
    _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                             ^
/home/rad/lab/zig/src/Module.zig:5695:21: 0x61629ca in analyzeFnBody (zig)
    sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
                    ^
/home/rad/lab/zig/src/Module.zig:4324:40: 0x5f6e541 in ensureFuncBodyAnalyzed (zig)
            var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
                                       ^
/home/rad/lab/zig/src/Compilation.zig:3127:42: 0x5f6c633 in processOneJob (zig)
            module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
                                         ^
/home/rad/lab/zig/src/Compilation.zig:3064:30: 0x5e1ca9e in performAllTheWork (zig)
            try processOneJob(comp, work_item, main_progress_node);
                             ^
/home/rad/lab/zig/src/Compilation.zig:2020:31: 0x5e191ad in update (zig)
    try comp.performAllTheWork(main_progress_node);
                              ^
/home/rad/lab/zig/src/main.zig:3403:36: 0x5e448d8 in serve (zig)
                    try comp.update(main_progress_node);
                                   ^
/home/rad/lab/zig/src/main.zig:3217:22: 0x5cc995c in buildOutputType (zig)
            try serve(
                     ^
/home/rad/lab/zig/src/main.zig:268:31: 0x5c9e471 in mainArgs (zig)
        return buildOutputType(gpa, arena, args, .{ .build = .Exe });
                              ^
/home/rad/lab/zig/src/main.zig:212:20: 0x5c9dae5 in main (zig)
    return mainArgs(gpa, arena, args);
                   ^
/home/rad/lab/zig/lib/std/start.zig:609:37: 0x5ca0258 in main (zig)
            const result = root.main() catch |err| {
                                    ^

zig build-exe bug2 Debug thumb-freestanding-none: error: the following command terminated unexpectedly:
/home/rad/lab/zig/build/stage3/bin/zig build-exe -freference-trace=256 /home/rad/lab/zta/zig-bug-2/libs/microzig/src/start.zig -fno-strip --cache-dir /home/rad/lab/zta/zig-bug-2/zig-cache --global-cache-dir /home/rad/.cache/zig --name bug2 -fcompiler-rt -fsingle-threaded -target thumb-freestanding-none -mcpu cortex_m0plus --script /home/rad/lab/zta/zig-bug-2/zig-cache/microzig/590102268d89866a601b4aa09edb9090/STM32L0x1_ARM Cortex-M0+.ld --mod microzig:config,chip,cpu:/home/rad/lab/zta/zig-bug-2/libs/microzig/src/microzig.zig --mod cpu:microzig:/home/rad/lab/zta/zig-bug-2/libs/microzig/src/modules/cpus/cortex-m.zig --mod chip:microzig:/home/rad/lab/zta/zig-bug-2/src/registers.zig --mod app:microzig:/home/rad/lab/zta/zig-bug-2/src/main.zig --mod config::/home/rad/lab/zta/zig-bug-2/zig-cache/microzig/config-4dafd40c6a22e11d752590ea0491f999.zig --deps app,microzig -fno-lto --listen=- 
Build Summary: 1/4 steps succeeded; 1 failed
install transitive failure
└─ install bug2 transitive failure
   └─ zig build-exe bug2 Debug thumb-freestanding-none failure
      └─ linkerscript success
error: the following build command failed with exit code 1:
/home/rad/lab/zta/zig-bug-2/zig-cache/o/67aa5454eeec0ac96d6eecba5e586177/build /home/rad/lab/zig/build/stage3/bin/zig /home/rad/lab/zta/zig-bug-2 /home/rad/lab/zta/zig-bug-2/zig-cache /home/rad/.cache/zig -freference-trace -freference-trace -fsummary
kuon commented 1 year ago

I was able to reproduce a segfault without microzig, I am not sure if this is the same bug, I added main2.zig to the repository.

llogick commented 1 year ago

I was able to reproduce a segfault without microzig, I am not sure if this is the same bug, I added main2.zig to the repository.

I think this one triggers https://github.com/ziglang/zig/issues/15513

matu3ba commented 1 year ago
pub fn main() !void {
    var int_values: [5]u32 = .{0} ** 5;
    var rx: [21]u8 = .{0} ** 21;

    @memcpy(@ptrCast([*]u8, &int_values), rx[1..]);
}

might be fixed with https://github.com/ziglang/zig/pull/15704.

kuon commented 1 year ago

Yes this seems different, good call.

matu3ba commented 1 year ago

Running the repo now produces:

/home/user/dev/git/zi/zig/buildrel/stage3/bin/zig build-exe /home/user/try/tryzig/zig-bug-2/libs/microzig/src/start.zig -fno-strip -OReleaseFast --cache-dir /home/user/try/tryzig/zig-bug-2/zig-cache --global-cache-dir /home/user/.cache/zig --name bug2 -fcompiler-rt -fsingle-threaded -target thumb-freestanding-none -mcpu cortex_m0plus --script /home/user/try/tryzig/zig-bug-2/zig-cache/microzig/c695ee9a1010a79ae3523a2e12d9cea0/STM32L0x1_ARM Cortex-M0+.ld --mod cpu:microzig:/home/user/try/tryzig/zig-bug-2/libs/microzig/src/modules/cpus/cortex-m.zig --mod chip:microzig:/home/user/try/tryzig/zig-bug-2/src/registers.zig --mod config::/home/user/try/tryzig/zig-bug-2/zig-cache/microzig/config-d8618022b2e27976a8aa8539a992690a.zig --mod app:microzig:/home/user/try/tryzig/zig-bug-2/src/main.zig --mod microzig:config,chip,cpu:/home/user/try/tryzig/zig-bug-2/libs/microzig/src/microzig.zig --deps app,microzig -fno-lto --listen=-
error: unrecognized file extension of parameter 'Cortex-M0+.ld'

The simplified example runs fine.

matu3ba commented 1 year ago

Suggestion to close and, if needed, clarify with a new issue for feature detection.

kuon commented 1 year ago

Running the repo now produces:

/home/user/dev/git/zi/zig/buildrel/stage3/bin/zig build-exe /home/user/try/tryzig/zig-bug-2/libs/microzig/src/start.zig -fno-strip -OReleaseFast --cache-dir /home/user/try/tryzig/zig-bug-2/zig-cache --global-cache-dir /home/user/.cache/zig --name bug2 -fcompiler-rt -fsingle-threaded -target thumb-freestanding-none -mcpu cortex_m0plus --script /home/user/try/tryzig/zig-bug-2/zig-cache/microzig/c695ee9a1010a79ae3523a2e12d9cea0/STM32L0x1_ARM Cortex-M0+.ld --mod cpu:microzig:/home/user/try/tryzig/zig-bug-2/libs/microzig/src/modules/cpus/cortex-m.zig --mod chip:microzig:/home/user/try/tryzig/zig-bug-2/src/registers.zig --mod config::/home/user/try/tryzig/zig-bug-2/zig-cache/microzig/config-d8618022b2e27976a8aa8539a992690a.zig --mod app:microzig:/home/user/try/tryzig/zig-bug-2/src/main.zig --mod microzig:config,chip,cpu:/home/user/try/tryzig/zig-bug-2/libs/microzig/src/microzig.zig --deps app,microzig -fno-lto --listen=-
error: unrecognized file extension of parameter 'Cortex-M0+.ld'

If you execute the command manually in a shell, you need to quote the file name as there is a space in it.

/usr/bin/zig build-exe /home/kuon/Playground/zig-bug-2/libs/microzig/src/start.zig -fno-strip -OReleaseFast --cache-dir /home/kuon/Playground/zig-bug-2/zig-cache --global-cache-dir /home/kuon/.cache/zig --name bug2 -fcompiler-rt -fsingle-threaded -target thumb-freestanding-none -mcpu cortex_m0plus --script "/home/kuon/Playground/zig-bug-2/zig-cache/microzig/bc8bf26f5ea5af870d018d26f6a49393/STM32L0x1_ARM Cortex-M0+.ld" --mod config::/home/kuon/Playground/zig-bug-2/zig-cache/microzig/config-dd06784b0c0c6ff6ae747202d5132cc8.zig --mod microzig:config,chip,cpu:/home/kuon/Playground/zig-bug-2/libs/microzig/src/microzig.zig --mod cpu:microzig:/home/kuon/Playground/zig-bug-2/libs/microzig/src/modules/cpus/cortex-m.zig --mod chip:microzig:/home/kuon/Playground/zig-bug-2/src/registers.zig --mod app:microzig:/home/kuon/Playground/zig-bug-2/src/main.zig --deps app,microzig -fno-lto
fish: Job 1, '/usr/bin/zig build-exe /home/ku…' terminated by signal SIGSEGV (Address boundary error)

The simplified example runs fine.

Yes, this was issue #15704 and is fixed.

Suggestion to close and, if needed, clarify with a new issue for feature detection.

The original issue stands, I sidetracked with the second example, but it had nothing to do with the original issue.

I will try to bundle everything in a single file.

kuon commented 1 year ago
const std = @import("std");
const assert = std.debug.assert;

pub fn Mmio(comptime PackedT: type) type {
    const size = @bitSizeOf(PackedT);
    const IntT = std.meta.Int(.unsigned, size);
    return extern struct {
        const Self = @This();

        raw: IntT,

        pub const underlying_type = PackedT;
    };
}

pub const devices = struct {
    pub const AES = @intToPtr(*volatile types.AES, 0x40026000);
};

pub const types = struct {
    ///  Advanced encryption standard hardware accelerator
    pub const AES = extern struct {
        ///  control register
        CR: Mmio(packed struct(u32) {
            EN: u1,
            padding: u31,
        }),
    };
};

pub fn main() !void {
    var addr = @ptrToInt(&devices.AES.CR.raw);
    _ = addr;
}

Triggers the bug (repo updated too).

/usr/bin/zig build-exe /home/kuon/Playground/zig-bug-2/src/main.zig -OReleaseFast --cache-dir /home/kuon/Playground/zig-bug-2/zig-cache --global-cache-dir /home/kuon/.cache/zig --name bug2 -fno-lto                          3105ms  ven 19 mai 2023 18:55:20
fish: Job 1, '/usr/bin/zig build-exe /home/ku…' terminated by signal SIGSEGV (Address boundary error)
andrewrk commented 1 year ago

Thanks for the reduction. No longer reproduces with 0.11.0-dev.4186+c72a9feab. Just needs test coverage and then this issue can be closed.