| author | |
| committer | |
| log | cc26cb9b2366723a8149e9f79e8252936cb69b73 |
| tree | 30e2bcaa34d25f747f5ecb5ae193919b26818bee |
| parent | fb28349349483c5e1c9523b19c2158cb465cf4e9 |
4 files changed, 95 insertions(+), 10 deletions(-)
src-self-hosted/astgen.zig+7-5| ... | ... | @@ -802,7 +802,7 @@ fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Catch) |
| 802 | 802 | const err_name = tree.tokenSlice(payload.castTag(.Payload).?.error_symbol.firstToken()); |
| 803 | 803 | if (mem.eql(u8, err_name, "_")) |
| 804 | 804 | break :blk &err_scope.base; |
| 805 | ||
| 805 | ||
| 806 | 806 | const unwrapped_err_ptr = try addZIRUnOp(mod, &err_scope.base, src, .unwrap_err_code, err_union_ptr); |
| 807 | 807 | err_val_scope = .{ |
| 808 | 808 | .parent = &err_scope.base, |
| ... | ... | @@ -1374,7 +1374,8 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For) |
| 1374 | 1374 | .ty = Type.initTag(.usize), |
| 1375 | 1375 | .val = Value.initTag(.one), |
| 1376 | 1376 | }); |
| 1377 | const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index, one); | |
| 1377 | const index_2 = try addZIRUnOp(mod, &loop_scope.base, cond_src, .deref, index_ptr); | |
| 1378 | const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one); | |
| 1378 | 1379 | _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one); |
| 1379 | 1380 | |
| 1380 | 1381 | // looping stuff |
| ... | ... | @@ -1382,7 +1383,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For) |
| 1382 | 1383 | .instructions = try for_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items), |
| 1383 | 1384 | }); |
| 1384 | 1385 | const for_block = try addZIRInstBlock(mod, scope, for_src, .{ |
| 1385 | .instructions = try scope.arena().dupe(*zir.Inst, for_scope.instructions.items), | |
| 1386 | .instructions = try for_scope.arena.dupe(*zir.Inst, for_scope.instructions.items), | |
| 1386 | 1387 | }); |
| 1387 | 1388 | |
| 1388 | 1389 | // while body |
| ... | ... | @@ -1404,7 +1405,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For) |
| 1404 | 1405 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = for_block }, |
| 1405 | 1406 | }; |
| 1406 | 1407 | |
| 1407 | var index_scope: Scope.LocalVal = undefined; | |
| 1408 | var index_scope: Scope.LocalPtr = undefined; | |
| 1408 | 1409 | const then_sub_scope = blk: { |
| 1409 | 1410 | const payload = for_node.payload.castTag(.PointerIndexPayload).?; |
| 1410 | 1411 | const is_ptr = payload.ptr_token != null; |
| ... | ... | @@ -1422,11 +1423,12 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For) |
| 1422 | 1423 | if (mem.eql(u8, index_name, "_")) { |
| 1423 | 1424 | break :blk &then_scope.base; |
| 1424 | 1425 | } |
| 1426 | // TODO make this const without an extra copy? | |
| 1425 | 1427 | index_scope = .{ |
| 1426 | 1428 | .parent = &then_scope.base, |
| 1427 | 1429 | .gen_zir = &then_scope, |
| 1428 | 1430 | .name = index_name, |
| 1429 | .inst = index, | |
| 1431 | .ptr = index_ptr, | |
| 1430 | 1432 | }; |
| 1431 | 1433 | break :blk &index_scope.base; |
| 1432 | 1434 | }; |
src-self-hosted/codegen.zig+28-4| ... | ... | @@ -829,6 +829,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 829 | 829 | // No side effects, so if it's unreferenced, do nothing. |
| 830 | 830 | if (inst.base.isUnused()) |
| 831 | 831 | return MCValue.dead; |
| 832 | ||
| 833 | const operand = try self.resolveInst(inst.operand); | |
| 834 | const info_a = inst.operand.ty.intInfo(self.target.*); | |
| 835 | const info_b = inst.base.ty.intInfo(self.target.*); | |
| 836 | if (info_a.signed != info_b.signed) | |
| 837 | return self.fail(inst.base.src, "TODO gen intcast sign safety in semantic analysis", .{}); | |
| 838 | ||
| 839 | if (info_a.bits == info_b.bits) | |
| 840 | return operand; | |
| 841 | ||
| 832 | 842 | switch (arch) { |
| 833 | 843 | else => return self.fail(inst.base.src, "TODO implement intCast for {}", .{self.target.cpu.arch}), |
| 834 | 844 | } |
| ... | ... | @@ -2039,15 +2049,29 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2039 | 2049 | mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), x); |
| 2040 | 2050 | }, |
| 2041 | 2051 | 8 => { |
| 2042 | return self.fail(src, "TODO implement set abi_size=8 stack variable with immediate", .{}); | |
| 2052 | // We have a positive stack offset value but we want a twos complement negative | |
| 2053 | // offset from rbp, which is at the top of the stack frame. | |
| 2054 | const negative_offset = @intCast(i8, -@intCast(i32, adj_off)); | |
| 2055 | const twos_comp = @bitCast(u8, negative_offset); | |
| 2056 | ||
| 2057 | // 64 bit write to memory would take two mov's anyways so we | |
| 2058 | // insted just use two 32 bit writes to avoid register allocation | |
| 2059 | try self.code.ensureCapacity(self.code.items.len + 14); | |
| 2060 | var buf: [8]u8 = undefined; | |
| 2061 | mem.writeIntLittle(u64, &buf, x_big); | |
| 2062 | ||
| 2063 | // mov DWORD PTR [rbp+offset+4], immediate | |
| 2064 | self.code.appendSliceAssumeCapacity(&[_]u8{ 0xc7, 0x45, twos_comp + 4}); | |
| 2065 | self.code.appendSliceAssumeCapacity(buf[4..8]); | |
| 2066 | ||
| 2067 | // mov DWORD PTR [rbp+offset], immediate | |
| 2068 | self.code.appendSliceAssumeCapacity(&[_]u8{ 0xc7, 0x45, twos_comp }); | |
| 2069 | self.code.appendSliceAssumeCapacity(buf[0..4]); | |
| 2043 | 2070 | }, |
| 2044 | 2071 | else => { |
| 2045 | 2072 | return self.fail(src, "TODO implement set abi_size=large stack variable with immediate", .{}); |
| 2046 | 2073 | }, |
| 2047 | 2074 | } |
| 2048 | if (x_big <= math.maxInt(u32)) {} else { | |
| 2049 | return self.fail(src, "TODO implement set stack variable with large immediate", .{}); | |
| 2050 | } | |
| 2051 | 2075 | }, |
| 2052 | 2076 | .embedded_in_code => |code_offset| { |
| 2053 | 2077 | return self.fail(src, "TODO implement set stack variable from embedded_in_code", .{}); |
src-self-hosted/zir_sema.zig+1-1| ... | ... | @@ -112,7 +112,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 112 | 112 | .condbr => return analyzeInstCondBr(mod, scope, old_inst.castTag(.condbr).?), |
| 113 | 113 | .isnull => return analyzeInstIsNonNull(mod, scope, old_inst.castTag(.isnull).?, true), |
| 114 | 114 | .isnonnull => return analyzeInstIsNonNull(mod, scope, old_inst.castTag(.isnonnull).?, false), |
| 115 | .iserr => return analyzeInstIsErr(mod, scope, old_inst.castTag(.iserr).?, true), | |
| 115 | .iserr => return analyzeInstIsErr(mod, scope, old_inst.castTag(.iserr).?), | |
| 116 | 116 | .boolnot => return analyzeInstBoolNot(mod, scope, old_inst.castTag(.boolnot).?), |
| 117 | 117 | .typeof => return analyzeInstTypeOf(mod, scope, old_inst.castTag(.typeof).?), |
| 118 | 118 | .optional_type => return analyzeInstOptionalType(mod, scope, old_inst.castTag(.optional_type).?), |
test/stage2/test.zig+59| ... | ... | @@ -845,6 +845,65 @@ pub fn addCases(ctx: *TestContext) !void { |
| 845 | 845 | , |
| 846 | 846 | "", |
| 847 | 847 | ); |
| 848 | ||
| 849 | // 64bit set stack | |
| 850 | case.addCompareOutput( | |
| 851 | \\export fn _start() noreturn { | |
| 852 | \\ var i: u64 = 0xFFEEDDCCBBAA9988; | |
| 853 | \\ assert(i == 0xFFEEDDCCBBAA9988); | |
| 854 | \\ | |
| 855 | \\ exit(); | |
| 856 | \\} | |
| 857 | \\ | |
| 858 | \\pub fn assert(ok: bool) void { | |
| 859 | \\ if (!ok) unreachable; // assertion failure | |
| 860 | \\} | |
| 861 | \\ | |
| 862 | \\fn exit() noreturn { | |
| 863 | \\ asm volatile ("syscall" | |
| 864 | \\ : | |
| 865 | \\ : [number] "{rax}" (231), | |
| 866 | \\ [arg1] "{rdi}" (0) | |
| 867 | \\ : "rcx", "r11", "memory" | |
| 868 | \\ ); | |
| 869 | \\ unreachable; | |
| 870 | \\} | |
| 871 | , | |
| 872 | "", | |
| 873 | ); | |
| 874 | ||
| 875 | // Basic for loop | |
| 876 | case.addCompareOutput( | |
| 877 | \\export fn _start() noreturn { | |
| 878 | \\ for ("hello") |_| print(); | |
| 879 | \\ | |
| 880 | \\ exit(); | |
| 881 | \\} | |
| 882 | \\ | |
| 883 | \\fn print() void { | |
| 884 | \\ asm volatile ("syscall" | |
| 885 | \\ : | |
| 886 | \\ : [number] "{rax}" (1), | |
| 887 | \\ [arg1] "{rdi}" (1), | |
| 888 | \\ [arg2] "{rsi}" (@ptrToInt("hello\n")), | |
| 889 | \\ [arg3] "{rdx}" (6) | |
| 890 | \\ : "rcx", "r11", "memory" | |
| 891 | \\ ); | |
| 892 | \\ return; | |
| 893 | \\} | |
| 894 | \\ | |
| 895 | \\fn exit() noreturn { | |
| 896 | \\ asm volatile ("syscall" | |
| 897 | \\ : | |
| 898 | \\ : [number] "{rax}" (231), | |
| 899 | \\ [arg1] "{rdi}" (0) | |
| 900 | \\ : "rcx", "r11", "memory" | |
| 901 | \\ ); | |
| 902 | \\ unreachable; | |
| 903 | \\} | |
| 904 | , | |
| 905 | "hello\nhello\nhello\nhello\nhello\n", | |
| 906 | ); | |
| 848 | 907 | } |
| 849 | 908 | |
| 850 | 909 | { |