| author | |
| committer | |
| log | c64279b15b527749420e0e79fcc6dbfbfeb02812 |
| tree | 8f7fe813a6b2b7048468731f5f93619b3704e882 |
| parent | 1adb15098c711973d1c75061f122b907aaf09a7c |
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(); |
| 6399 | 6399 | ||
| 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); |
| 6408 | 6407 | ||
| 6408 | return sema.intCast(block, dest_ty, dest_ty_src, operand, operand_src, true); | ||
| 6409 | } | ||
| 6410 | |||
| 6411 | fn 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)); |
| 6411 | 6422 | ||
| 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 | } |
| 6417 | 6428 | ||
| 6418 | // TODO insert safety check to make sure the value fits in the dest type | 6429 | // TODO insert safety check to make sure the value fits in the dest type |
| 6430 | _ = runtime_safety; | ||
| 6419 | 6431 | ||
| 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); |
| 7987 | 7999 | ||
| 7988 | // TODO coerce rhs if air_tag is not shl_sat | 8000 | // 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)); | ||
| 7989 | 8002 | ||
| 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 | } |
| 8001 | 8014 | ||
| 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(); | ||
| 8004 | 8018 | ||
| 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; |
| 8007 | 8022 | ||
| 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( |
| 8038 | 8052 | ||
| 8039 | // TODO: insert runtime safety check for shl_exact | 8053 | // TODO: insert runtime safety check for shl_exact |
| 8040 | 8054 | ||
| 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 | } |
| 8044 | 8074 | ||
| 8045 | fn zirShr( | 8075 | fn 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 | |||
| 14573 | fn 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); |
| 14541 | 14584 | ||
| 14542 | // TODO @maximum(max_int, undefined) should return max_int | 14585 | // 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 | } |
| 610 | 610 | ||
| 611 | test "negation f80" { | 611 | test "negation f80" { |
| 612 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 612 | 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 | } | ||
| 613 | 617 | ||
| 614 | if (builtin.os.tag == .freebsd) { | 618 | if (builtin.os.tag == .freebsd) { |
| 615 | // TODO file issue to track this failure | 619 | // TODO file issue to track this failure |
| ... | @@ -673,7 +677,10 @@ fn fnWithFloatMode() f32 { | ... | @@ -673,7 +677,10 @@ fn fnWithFloatMode() f32 { |
| 673 | } | 677 | } |
| 674 | 678 | ||
| 675 | test "float literal at compile time not lossy" { | 679 | test "float literal at compile time not lossy" { |
| 676 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 680 | if (builtin.zig_backend != .stage1) { |
| 681 | // https://github.com/ziglang/zig/issues/11169 | ||
| 682 | return error.SkipZigTest; | ||
| 683 | } | ||
| 677 | 684 | ||
| 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 | } |
| 308 | 308 | ||
| 309 | test "function pointers" { | 309 | test "function pointers" { |
| 310 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 310 | 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 | ||
| 311 | 318 | ||
| 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 | } |
| 381 | 388 | ||
| 382 | test "function with inferred error set but returning no error" { | 389 | test "function with inferred error set but returning no error" { |
| 383 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 390 | 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 | ||
| 384 | 393 | ||
| 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 | } |
| 164 | 164 | ||
| 165 | test "saturating shl uses the LHS type" { | 165 | test "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; |
| 170 | 168 |
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 | } |
| 46 | 46 | ||
| 47 | test "casting to union with a macro" { | 47 | test "casting to union with a macro" { |
| 48 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO Sema.zirUnionInitPtr | 48 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 49 | 49 | ||
| 50 | const l: c_long = 42; | 50 | const l: c_long = 42; |
| 51 | const d: f64 = 2.0; | 51 | const d: f64 = 2.0; |
| 52 | 52 | ||
| 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); |
| 55 | 55 | ||
| 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 | } |
| 59 | 59 | ||
| 60 | test "nested comma operator" { | 60 | test "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 | } |
| 231 | 231 | ||
| 232 | test "Type.AnyFrame" { | 232 | test "Type.AnyFrame" { |
| 233 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 233 | if (builtin.zig_backend != .stage1) { |
| 234 | // https://github.com/ziglang/zig/issues/6025 | ||
| 235 | return error.SkipZigTest; | ||
| 236 | } | ||
| 234 | 237 | ||
| 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 | |||
| 518 | test "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 | |||
| 536 | test "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 | } |
| 389 | 383 | ||
| 390 | extern fn foo(a: usize, b: bool, ...) callconv(.C) usize; | 384 | extern 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 | } |
| 414 | 408 | ||
| 415 | test "type info: anyframe and anyframe->T" { | 409 | test "type info: anyframe and anyframe->T" { |
| 416 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 410 | if (builtin.zig_backend != .stage1) { |
| 411 | // https://github.com/ziglang/zig/issues/6025 | ||
| 412 | return error.SkipZigTest; | ||
| 413 | } | ||
| 417 | 414 | ||
| 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 | } |
| 470 | 467 | ||
| 471 | test "type info for async frames" { | 468 | test "type info for async frames" { |
| 472 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 469 | if (builtin.zig_backend != .stage1) { |
| 470 | // https://github.com/ziglang/zig/issues/6025 | ||
| 471 | return error.SkipZigTest; | ||
| 472 | } | ||
| 473 | 473 | ||
| 474 | switch (@typeInfo(@Frame(add))) { | 474 | switch (@typeInfo(@Frame(add))) { |
| 475 | .Frame => |frame| { | 475 | .Frame => |frame| { |