diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-06-01 16:45:28 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-06-01 16:45:28 -0700 |
| commit | 288e89b606b46328a5ab358b2eef2c5dc277bc8f (patch) | |
| tree | ce898990af2eec71a7d515cc317b7e7b096d76b5 | |
| parent | a4cdb49a58f62776b73ad873b25243e65ac29266 (diff) | |
| download | zig-288e89b606b46328a5ab358b2eef2c5dc277bc8f.tar.gz zig-288e89b606b46328a5ab358b2eef2c5dc277bc8f.zip | |
Sema: fix compiler crash with comptime arithmetic involving `@ptrToInt`
| -rw-r--r-- | src/Sema.zig | 52 | ||||
| -rw-r--r-- | test/behavior/align.zig | 11 | ||||
| -rw-r--r-- | test/behavior/bugs/1741.zig | 5 |
3 files changed, 47 insertions, 21 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 88847ced0a..fd3dab4866 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1540,6 +1540,24 @@ fn resolveMaybeUndefVal( } } +/// Value Tag `variable` results in `null`. +/// Value Tag `undef` results in the Value. +/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned. +/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`. +fn resolveMaybeUndefValIntable( + sema: *Sema, + block: *Block, + src: LazySrcLoc, + inst: Air.Inst.Ref, +) CompileError!?Value { + const val = (try sema.resolveMaybeUndefValAllowVariables(block, src, inst)) orelse return null; + switch (val.tag()) { + .variable, .decl_ref, .decl_ref_mut => return null, + .generic_poison => return error.GenericPoison, + else => return val, + } +} + /// Returns all Value tags including `variable` and `undef`. fn resolveMaybeUndefValAllowVariables( sema: *Sema, @@ -9302,19 +9320,27 @@ fn zirBitwise( return sema.fail(block, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag()), @tagName(rhs_ty.zigTypeTag()) }); } - if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| { - if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| { - const result_val = switch (air_tag) { - .bit_and => try lhs_val.bitwiseAnd(rhs_val, resolved_type, sema.arena, target), - .bit_or => try lhs_val.bitwiseOr(rhs_val, resolved_type, sema.arena, target), - .xor => try lhs_val.bitwiseXor(rhs_val, resolved_type, sema.arena, target), - else => unreachable, - }; - return sema.addConstant(resolved_type, result_val); + const runtime_src = runtime: { + // TODO: ask the linker what kind of relocations are available, and + // in some cases emit a Value that means "this decl's address AND'd with this operand". + if (try sema.resolveMaybeUndefValIntable(block, lhs_src, casted_lhs)) |lhs_val| { + if (try sema.resolveMaybeUndefValIntable(block, rhs_src, casted_rhs)) |rhs_val| { + const result_val = switch (air_tag) { + .bit_and => try lhs_val.bitwiseAnd(rhs_val, resolved_type, sema.arena, target), + .bit_or => try lhs_val.bitwiseOr(rhs_val, resolved_type, sema.arena, target), + .xor => try lhs_val.bitwiseXor(rhs_val, resolved_type, sema.arena, target), + else => unreachable, + }; + return sema.addConstant(resolved_type, result_val); + } else { + break :runtime rhs_src; + } + } else { + break :runtime lhs_src; } - } + }; - try sema.requireRuntimeBlock(block, src); + try sema.requireRuntimeBlock(block, runtime_src); return block.addBinOp(air_tag, casted_lhs, casted_rhs); } @@ -10163,8 +10189,8 @@ fn analyzeArithmetic( const mod = sema.mod; const target = mod.getTarget(); - const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs); - const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs); + const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(block, lhs_src, casted_lhs); + const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(block, rhs_src, casted_rhs); const rs: struct { src: LazySrcLoc, air_tag: Air.Inst.Tag } = rs: { switch (zir_tag) { .add => { diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 4d21aac483..ad35db2171 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -502,12 +502,9 @@ test "align(@alignOf(T)) T does not force resolution of T" { test "align(N) on functions" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO // function alignment is a compile error on wasm32/wasm64 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest; @@ -531,5 +528,5 @@ test "comptime alloc alignment" { comptime var bytes2 align(256) = [_]u8{0}; var bytes2_addr = @ptrToInt(&bytes2); - try std.testing.expect(bytes2_addr & 0xff == 0); + try expect(bytes2_addr & 0xff == 0); } diff --git a/test/behavior/bugs/1741.zig b/test/behavior/bugs/1741.zig index b91ac8e2fb..63de6e83dc 100644 --- a/test/behavior/bugs/1741.zig +++ b/test/behavior/bugs/1741.zig @@ -2,7 +2,10 @@ const std = @import("std"); const builtin = @import("builtin"); test "fixed" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + const x: f32 align(128) = 12.34; try std.testing.expect(@ptrToInt(&x) % 128 == 0); } |
