ziglang / zig

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

x86_64: Bug multiplying `@as(u17, @intCast(u8)) * comptime_int` #19607

Open clickingbuttons opened 7 months ago

clickingbuttons commented 7 months ago

Zig Version

0.12.0-dev.3528+423cb317f

Steps to Reproduce and Observed Behavior

pub fn main() !void {
    const a = std.crypto.random.int(u8);
    const b = @as(u17, a) * 60;

    std.debug.print("{}\n", .{ b });
}

pub const std = @import("std");
./zig/build/stage4/bin/zig build-exe ./test.zig -fno-llvm -fno-lld -target x86_64-linux
thread 2176532 panic: access of union field 'load_frame' while field 'immediate' is active

src/zig/src/arch/x86_64/CodeGen.zig:9216:48: 0x10eede63b in genMulDivBinOp (zig)
                    .base = .{ .frame = rhs_mcv.load_frame.index },
                                               ^
src/zig/src/arch/x86_64/CodeGen.zig:4631:56: 0x10ef07003 in airMulWithOverflow (zig)
            const partial_mcv = try self.genMulDivBinOp(.mul, null, dst_ty, src_ty, lhs, rhs);
                                                       ^
src/zig/src/arch/x86_64/CodeGen.zig:2019:62: 0x10ea34b5b in genBody (zig)
            .mul_with_overflow => try self.airMulWithOverflow(inst),
                                                             ^
src/zig/src/arch/x86_64/CodeGen.zig:1820:25: 0x10e4d77eb in gen (zig)
        try self.genBody(self.air.getMainBody());
                        ^

Expected Behavior

No crash. I spent a while reading the Intel developer's manual but now I understand less.

Edit: Remove unnecessary @intCast

mochalins commented 7 months ago

I don't believe this should be happening anyway, but just wanted to note that the @intCast is unnecessary here; would that get around this problem for your use case temporarily?

clickingbuttons commented 7 months ago

@mochalins Problem still happens with @intCast removed. It was leftover from my reduction from some other code. I have removed it from the OP.

Miguel0312 commented 7 months ago

I think that the problem is related to the code in CodeGen.zig in line 9183:

if (switch (tag) {
        else => unreachable,
        .mul, .mul_wrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2,
        .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_abi_size != src_abi_size,
    } or src_abi_size > 8)

When src_ty is u8 and dst_ty is u17, dst_abi_size is 4 and src_abit_size is 1 so the code inside this block is executed which causes the union field rhs_mvc.load_frame to be accessed and this causes a error. But I don't know if the solution is to modify the condition so the code inside the block is never executed or if the code inside the block must be modified to deal with this case.

kkHAIKE commented 5 months ago

aarch64 have same issus

/Users/dexter/Downloads/zig/src/arch/aarch64/CodeGen.zig:6176:40: 0x10ab8cd03 in genTypedValue (zig)
            .load_symbol, .load_tlv => unreachable, // TODO
                                       ^
/Users/dexter/Downloads/zig/src/arch/aarch64/CodeGen.zig:6145:71: 0x10a664133 in resolveInst (zig)
    const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?);
                                                                      ^
/Users/dexter/Downloads/zig/src/arch/aarch64/CodeGen.zig:4289:45: 0x10a68689b in airCall (zig)
        const arg_mcv = try self.resolveInst(args[arg_i]);
                                            ^
/Users/dexter/Downloads/zig/src/arch/aarch64/CodeGen.zig:812:51: 0x10a0c247b in genBody (zig)
            .call              => try self.airCall(inst, .auto),
                                                  ^
/Users/dexter/Downloads/zig/src/arch/aarch64/CodeGen.zig:543:25: 0x10a0bbd1f in gen (zig)
        try self.genBody(self.air.getMainBody());
                        ^
/Users/dexter/Downloads/zig/src/arch/aarch64/CodeGen.zig:395:17: 0x109c2e01f in generate (zig)
    function.gen() catch |err| switch (err) {
                ^
/Users/dexter/Downloads/zig/src/codegen.zig:68:63: 0x1096e9283 in generateFunction (zig)
        => return @import("arch/aarch64/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output),n.main
                                                              ^
/Users/dexter/Downloads/zig/src/link/MachO/ZigObject.zig:683:45: 0x1096f2083 in updateFunc (zig)
    const res = try codegen.generateFunction(
                                            ^
/Users/dexter/Downloads/zig/src/link/MachO.zig:3166:44: 0x1096f298f in updateFunc (zig)
    return self.getZigObject().?.updateFunc(self, mod, func_index, air, liveness);
                                           ^
/Users/dexter/Downloads/zig/src/link.zig:422:82: 0x10940ac73 in updateFunc (zig)
                return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(module, func_index, air, liveness);
                                                                                 ^
/Users/dexter/Downloads/zig/src/Module.zig:3223:22: 0x1091a1893 in ensureFuncBodyAnalyzed (zig)
        lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {
                     ^
/Users/dexter/Downloads/zig/src/Compilation.zig:3405:42: 0x10919ec07 in processOneJob (zig)
            module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
                                         ^
/Users/dexter/Downloads/zig/src/Compilation.zig:3345:30: 0x108ffef03 in performAllTheWork (zig)
            try processOneJob(comp, work_item, main_progress_node);
                             ^
/Users/dexter/Downloads/zig/src/Compilation.zig:2132:31: 0x108ffb41b in update (zig)
    try comp.performAllTheWork(main_progress_node);
                              ^
/Users/dexter/Downloads/zig/src/main.zig:4404:20: 0x109026983 in updateModule (zig)
    try comp.update(prog_node);
                   ^
/Users/dexter/Downloads/zig/src/main.zig:3422:21: 0x109085d17 in buildOutputType (zig)
        updateModule(comp, color, root_prog_node) catch |err| switch (err) {
                    ^
/Users/dexter/Downloads/zig/src/main.zig:271:31: 0x108f03593 in mainArgs (zig)
        return buildOutputType(gpa, arena, args, .run);
                              ^
/Users/dexter/Downloads/zig/src/main.zig:209:20: 0x108f0085f in main (zig)
    return mainArgs(gpa, arena, args);
                   ^
/Users/dexter/Downloads/zig/lib/std/start.zig:524:37: 0x108f004a3 in main (zig)
            const result = root.main() catch |err| {