authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-26 21:07:56+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-26 19:50:56-07:00
logcc26cb9b2366723a8149e9f79e8252936cb69b73
tree30e2bcaa34d25f747f5ecb5ae193919b26818bee
parentfb28349349483c5e1c9523b19c2158cb465cf4e9

stage2: codegen needed for basic for loop


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)
802802 const err_name = tree.tokenSlice(payload.castTag(.Payload).?.error_symbol.firstToken());
803803 if (mem.eql(u8, err_name, "_"))
804804 break :blk &err_scope.base;
805
805
806806 const unwrapped_err_ptr = try addZIRUnOp(mod, &err_scope.base, src, .unwrap_err_code, err_union_ptr);
807807 err_val_scope = .{
808808 .parent = &err_scope.base,
......@@ -1374,7 +1374,8 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
13741374 .ty = Type.initTag(.usize),
13751375 .val = Value.initTag(.one),
13761376 });
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);
13781379 _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one);
13791380
13801381 // looping stuff
......@@ -1382,7 +1383,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
13821383 .instructions = try for_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),
13831384 });
13841385 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),
13861387 });
13871388
13881389 // while body
......@@ -1404,7 +1405,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
14041405 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = for_block },
14051406 };
14061407
1407 var index_scope: Scope.LocalVal = undefined;
1408 var index_scope: Scope.LocalPtr = undefined;
14081409 const then_sub_scope = blk: {
14091410 const payload = for_node.payload.castTag(.PointerIndexPayload).?;
14101411 const is_ptr = payload.ptr_token != null;
......@@ -1422,11 +1423,12 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
14221423 if (mem.eql(u8, index_name, "_")) {
14231424 break :blk &then_scope.base;
14241425 }
1426 // TODO make this const without an extra copy?
14251427 index_scope = .{
14261428 .parent = &then_scope.base,
14271429 .gen_zir = &then_scope,
14281430 .name = index_name,
1429 .inst = index,
1431 .ptr = index_ptr,
14301432 };
14311433 break :blk &index_scope.base;
14321434 };
src-self-hosted/codegen.zig+28-4
......@@ -829,6 +829,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
829829 // No side effects, so if it's unreferenced, do nothing.
830830 if (inst.base.isUnused())
831831 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
832842 switch (arch) {
833843 else => return self.fail(inst.base.src, "TODO implement intCast for {}", .{self.target.cpu.arch}),
834844 }
......@@ -2039,15 +2049,29 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
20392049 mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), x);
20402050 },
20412051 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]);
20432070 },
20442071 else => {
20452072 return self.fail(src, "TODO implement set abi_size=large stack variable with immediate", .{});
20462073 },
20472074 }
2048 if (x_big <= math.maxInt(u32)) {} else {
2049 return self.fail(src, "TODO implement set stack variable with large immediate", .{});
2050 }
20512075 },
20522076 .embedded_in_code => |code_offset| {
20532077 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!
112112 .condbr => return analyzeInstCondBr(mod, scope, old_inst.castTag(.condbr).?),
113113 .isnull => return analyzeInstIsNonNull(mod, scope, old_inst.castTag(.isnull).?, true),
114114 .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).?),
116116 .boolnot => return analyzeInstBoolNot(mod, scope, old_inst.castTag(.boolnot).?),
117117 .typeof => return analyzeInstTypeOf(mod, scope, old_inst.castTag(.typeof).?),
118118 .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 {
845845 ,
846846 "",
847847 );
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 );
848907 }
849908
850909 {