authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-14 23:15:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-14 23:15:01-07:00
logc64279b15b527749420e0e79fcc6dbfbfeb02812
tree8f7fe813a6b2b7048468731f5f93619b3704e882
parent1adb15098c711973d1c75061f122b907aaf09a7c

Sema: fix shl_sat with comptime rhs


7 files changed, 89 insertions(+), 65 deletions(-)

src/Sema.zig+49-6
...@@ -6398,7 +6398,6 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -6398,7 +6398,6 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
6398 defer tracy.end();6398 defer tracy.end();
63996399
6400 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6400 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6401 const src = inst_data.src();
6402 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };6401 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
6403 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };6402 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
6404 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;6403 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
...@@ -6406,16 +6405,29 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -6406,16 +6405,29 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
6406 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);6405 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
6407 const operand = sema.resolveInst(extra.rhs);6406 const operand = sema.resolveInst(extra.rhs);
64086407
6408 return sema.intCast(block, dest_ty, dest_ty_src, operand, operand_src, true);
6409}
6410
6411fn intCast(
6412 sema: *Sema,
6413 block: *Block,
6414 dest_ty: Type,
6415 dest_ty_src: LazySrcLoc,
6416 operand: Air.Inst.Ref,
6417 operand_src: LazySrcLoc,
6418 runtime_safety: bool,
6419) CompileError!Air.Inst.Ref {
6409 const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_ty);6420 const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_ty);
6410 _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand));6421 _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand));
64116422
6412 if (try sema.isComptimeKnown(block, operand_src, operand)) {6423 if (try sema.isComptimeKnown(block, operand_src, operand)) {
6413 return sema.coerce(block, dest_ty, operand, operand_src);6424 return sema.coerce(block, dest_ty, operand, operand_src);
6414 } else if (dest_is_comptime_int) {6425 } else if (dest_is_comptime_int) {
6415 return sema.fail(block, src, "unable to cast runtime value to 'comptime_int'", .{});6426 return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{});
6416 }6427 }
64176428
6418 // TODO insert safety check to make sure the value fits in the dest type6429 // TODO insert safety check to make sure the value fits in the dest type
6430 _ = runtime_safety;
64196431
6420 if ((try sema.typeHasOnePossibleValue(block, dest_ty_src, dest_ty))) |opv| {6432 if ((try sema.typeHasOnePossibleValue(block, dest_ty_src, dest_ty))) |opv| {
6421 return sema.addConstant(dest_ty, opv);6433 return sema.addConstant(dest_ty, opv);
...@@ -7986,6 +7998,7 @@ fn zirShl(...@@ -7986,6 +7998,7 @@ fn zirShl(
7986 const rhs = sema.resolveInst(extra.rhs);7998 const rhs = sema.resolveInst(extra.rhs);
79877999
7988 // TODO coerce rhs if air_tag is not shl_sat8000 // TODO coerce rhs if air_tag is not shl_sat
8001 const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, sema.typeOf(rhs));
79898002
7990 const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs);8003 const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs);
7991 const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs);8004 const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs);
...@@ -7999,13 +8012,14 @@ fn zirShl(...@@ -7999,13 +8012,14 @@ fn zirShl(
7999 }8012 }
8000 }8013 }
80018014
8002 const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {8015 const lhs_ty = sema.typeOf(lhs);
8003 const lhs_ty = sema.typeOf(lhs);8016 const rhs_ty = sema.typeOf(rhs);
8017 const target = sema.mod.getTarget();
80048018
8019 const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {
8005 if (lhs_val.isUndef()) return sema.addConstUndef(lhs_ty);8020 if (lhs_val.isUndef()) return sema.addConstUndef(lhs_ty);
8006 const rhs_val = maybe_rhs_val orelse break :rs rhs_src;8021 const rhs_val = maybe_rhs_val orelse break :rs rhs_src;
80078022
8008 const target = sema.mod.getTarget();
8009 const val = switch (air_tag) {8023 const val = switch (air_tag) {
8010 .shl_exact => val: {8024 .shl_exact => val: {
8011 const shifted = try lhs_val.shl(rhs_val, sema.arena);8025 const shifted = try lhs_val.shl(rhs_val, sema.arena);
...@@ -8038,8 +8052,24 @@ fn zirShl(...@@ -8038,8 +8052,24 @@ fn zirShl(
80388052
8039 // TODO: insert runtime safety check for shl_exact8053 // TODO: insert runtime safety check for shl_exact
80408054
8055 const new_rhs = if (air_tag == .shl_sat) rhs: {
8056 // Limit the RHS type for saturating shl to be an integer as small as the LHS.
8057 if (rhs_is_comptime_int or
8058 rhs_ty.intInfo(target).bits > lhs_ty.intInfo(target).bits)
8059 {
8060 const max_int = try sema.addConstant(
8061 lhs_ty,
8062 try lhs_ty.maxInt(sema.arena, target),
8063 );
8064 const rhs_limited = try sema.analyzeMinMax(block, rhs_src, rhs, max_int, .min, rhs_src, rhs_src);
8065 break :rhs try sema.intCast(block, lhs_ty, rhs_src, rhs_limited, rhs_src, false);
8066 } else {
8067 break :rhs rhs;
8068 }
8069 } else rhs;
8070
8041 try sema.requireRuntimeBlock(block, runtime_src);8071 try sema.requireRuntimeBlock(block, runtime_src);
8042 return block.addBinOp(air_tag, lhs, rhs);8072 return block.addBinOp(air_tag, lhs, new_rhs);
8043}8073}
80448074
8045fn zirShr(8075fn zirShr(
...@@ -14537,6 +14567,19 @@ fn zirMinMax(...@@ -14537,6 +14567,19 @@ fn zirMinMax(
14537 const rhs = sema.resolveInst(extra.rhs);14567 const rhs = sema.resolveInst(extra.rhs);
14538 try sema.checkNumericType(block, lhs_src, sema.typeOf(lhs));14568 try sema.checkNumericType(block, lhs_src, sema.typeOf(lhs));
14539 try sema.checkNumericType(block, rhs_src, sema.typeOf(rhs));14569 try sema.checkNumericType(block, rhs_src, sema.typeOf(rhs));
14570 return sema.analyzeMinMax(block, src, lhs, rhs, air_tag, lhs_src, rhs_src);
14571}
14572
14573fn analyzeMinMax(
14574 sema: *Sema,
14575 block: *Block,
14576 src: LazySrcLoc,
14577 lhs: Air.Inst.Ref,
14578 rhs: Air.Inst.Ref,
14579 air_tag: Air.Inst.Tag,
14580 lhs_src: LazySrcLoc,
14581 rhs_src: LazySrcLoc,
14582) CompileError!Air.Inst.Ref {
14540 const simd_op = try sema.checkSimdBinOp(block, src, lhs, rhs, lhs_src, rhs_src);14583 const simd_op = try sema.checkSimdBinOp(block, src, lhs, rhs, lhs_src, rhs_src);
1454114584
14542 // TODO @maximum(max_int, undefined) should return max_int14585 // TODO @maximum(max_int, undefined) should return max_int
test/behavior/floatop.zig+9-2
...@@ -609,7 +609,11 @@ test "negation f64" {...@@ -609,7 +609,11 @@ test "negation f64" {
609}609}
610610
611test "negation f80" {611test "negation f80" {
612 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO612 if (builtin.zig_backend != .stage1) {
613 // This test case exercises @intToFloat f80 in the compiler implementation.
614 // https://github.com/ziglang/zig/issues/11030
615 return error.SkipZigTest;
616 }
613617
614 if (builtin.os.tag == .freebsd) {618 if (builtin.os.tag == .freebsd) {
615 // TODO file issue to track this failure619 // TODO file issue to track this failure
...@@ -673,7 +677,10 @@ fn fnWithFloatMode() f32 {...@@ -673,7 +677,10 @@ fn fnWithFloatMode() f32 {
673}677}
674678
675test "float literal at compile time not lossy" {679test "float literal at compile time not lossy" {
676 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO680 if (builtin.zig_backend != .stage1) {
681 // https://github.com/ziglang/zig/issues/11169
682 return error.SkipZigTest;
683 }
677684
678 try expect(16777216.0 + 1.0 == 16777217.0);685 try expect(16777216.0 + 1.0 == 16777217.0);
679 try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);686 try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
test/behavior/fn.zig+16-7
...@@ -307,13 +307,20 @@ fn acceptsString(foo: []u8) void {...@@ -307,13 +307,20 @@ fn acceptsString(foo: []u8) void {
307}307}
308308
309test "function pointers" {309test "function pointers" {
310 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO310 if (builtin.zig_backend == .stage1) {
311 // stage1 has wrong semantics for function pointers
312 return error.SkipZigTest;
313 }
314
315 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
317 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
311318
312 const fns = [_]@TypeOf(fn1){319 const fns = [_]*const @TypeOf(fn1){
313 fn1,320 &fn1,
314 fn2,321 &fn2,
315 fn3,322 &fn3,
316 fn4,323 &fn4,
317 };324 };
318 for (fns) |f, i| {325 for (fns) |f, i| {
319 try expect(f() == @intCast(u32, i) + 5);326 try expect(f() == @intCast(u32, i) + 5);
...@@ -380,7 +387,9 @@ test "ability to give comptime types and non comptime types to same parameter" {...@@ -380,7 +387,9 @@ test "ability to give comptime types and non comptime types to same parameter" {
380}387}
381388
382test "function with inferred error set but returning no error" {389test "function with inferred error set but returning no error" {
383 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO390 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
391 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
384393
385 const S = struct {394 const S = struct {
386 fn foo() !void {}395 fn foo() !void {}
test/behavior/saturating_arithmetic.zig-2
...@@ -163,8 +163,6 @@ test "saturating shift-left" {...@@ -163,8 +163,6 @@ test "saturating shift-left" {
163}163}
164164
165test "saturating shl uses the LHS type" {165test "saturating shl uses the LHS type" {
166 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
167
168 const lhs_const: u8 = 1;166 const lhs_const: u8 = 1;
169 var lhs_var: u8 = 1;167 var lhs_var: u8 = 1;
170168
test/behavior/translate_c_macros.zig+3-3
...@@ -45,16 +45,16 @@ test "cast negative integer to pointer" {...@@ -45,16 +45,16 @@ test "cast negative integer to pointer" {
45}45}
4646
47test "casting to union with a macro" {47test "casting to union with a macro" {
48 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO Sema.zirUnionInitPtr48 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
4949
50 const l: c_long = 42;50 const l: c_long = 42;
51 const d: f64 = 2.0;51 const d: f64 = 2.0;
5252
53 var casted = h.UNION_CAST(l);53 var casted = h.UNION_CAST(l);
54 try expectEqual(l, casted.l);54 try expect(l == casted.l);
5555
56 casted = h.UNION_CAST(d);56 casted = h.UNION_CAST(d);
57 try expectEqual(d, casted.d);57 try expect(d == casted.d);
58}58}
5959
60test "nested comma operator" {60test "nested comma operator" {
test/behavior/type.zig+4-37
...@@ -230,7 +230,10 @@ test "Type.Vector" {...@@ -230,7 +230,10 @@ test "Type.Vector" {
230}230}
231231
232test "Type.AnyFrame" {232test "Type.AnyFrame" {
233 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO233 if (builtin.zig_backend != .stage1) {
234 // https://github.com/ziglang/zig/issues/6025
235 return error.SkipZigTest;
236 }
234237
235 try testTypes(&[_]type{238 try testTypes(&[_]type{
236 anyframe,239 anyframe,
...@@ -514,39 +517,3 @@ test "Type.Union from regular enum" {...@@ -514,39 +517,3 @@ test "Type.Union from regular enum" {
514 _ = T;517 _ = T;
515 _ = @typeInfo(T).Union;518 _ = @typeInfo(T).Union;
516}519}
517
518test "Type.Fn" {
519 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
520
521 // wasm doesn't support align attributes on functions
522 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
523
524 const foo = struct {
525 fn func(a: usize, b: bool) align(4) callconv(.C) usize {
526 _ = a;
527 _ = b;
528 return 0;
529 }
530 }.func;
531 const Foo = @Type(@typeInfo(@TypeOf(foo)));
532 const foo_2: Foo = foo;
533 _ = foo_2;
534}
535
536test "Type.BoundFn" {
537 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
538
539 // wasm doesn't support align attributes on functions
540 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
541
542 const TestStruct = packed struct {
543 pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void {
544 _ = self;
545 }
546 };
547 const test_instance: TestStruct = undefined;
548 try testing.expect(std.meta.eql(
549 @typeName(@TypeOf(test_instance.foo)),
550 @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))),
551 ));
552}
test/behavior/type_info.zig+8-8
...@@ -379,12 +379,6 @@ fn testFunction() !void {...@@ -379,12 +379,6 @@ fn testFunction() !void {
379 try expect(fn_info.Fn.return_type.? == usize);379 try expect(fn_info.Fn.return_type.? == usize);
380 const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));380 const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
381 try expect(fn_aligned_info.Fn.alignment == 4);381 try expect(fn_aligned_info.Fn.alignment == 4);
382
383 if (builtin.zig_backend != .stage1) return; // no bound fn in stage2
384 const test_instance: TestPackedStruct = undefined;
385 const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
386 try expect(bound_fn_info == .BoundFn);
387 try expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestPackedStruct);
388}382}
389383
390extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;384extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
...@@ -413,7 +407,10 @@ fn testVector() !void {...@@ -413,7 +407,10 @@ fn testVector() !void {
413}407}
414408
415test "type info: anyframe and anyframe->T" {409test "type info: anyframe and anyframe->T" {
416 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO410 if (builtin.zig_backend != .stage1) {
411 // https://github.com/ziglang/zig/issues/6025
412 return error.SkipZigTest;
413 }
417414
418 try testAnyFrame();415 try testAnyFrame();
419 comptime try testAnyFrame();416 comptime try testAnyFrame();
...@@ -469,7 +466,10 @@ fn add(a: i32, b: i32) i32 {...@@ -469,7 +466,10 @@ fn add(a: i32, b: i32) i32 {
469}466}
470467
471test "type info for async frames" {468test "type info for async frames" {
472 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO469 if (builtin.zig_backend != .stage1) {
470 // https://github.com/ziglang/zig/issues/6025
471 return error.SkipZigTest;
472 }
473473
474 switch (@typeInfo(@Frame(add))) {474 switch (@typeInfo(@Frame(add))) {
475 .Frame => |frame| {475 .Frame => |frame| {