Commit ca1ffb0951

joachimschmidt557 <joachim.schmidt557@outlook.com>
2022-03-12 22:30:28
stage2 ARM: genSetStack for stack_argument_offset
1 parent 1f313b3
src/arch/arm/CodeGen.zig
@@ -2876,35 +2876,19 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
                 const condition = Condition.fromCompareOperatorUnsigned(cmp_op);
                 break :blk condition.negate();
             },
-            .register => |reg| blk: {
-                try self.spillCompareFlagsIfOccupied();
-
-                // cmp reg, 1
-                // bne ...
-                _ = try self.addInst(.{
-                    .tag = .cmp,
-                    .cond = .al,
-                    .data = .{ .rr_op = .{
-                        .rd = .r0,
-                        .rn = reg,
-                        .op = Instruction.Operand.imm(1, 0),
-                    } },
-                });
+            else => blk: {
+                const reg = switch (cond) {
+                    .register => |r| r,
+                    else => try self.copyToTmpRegister(Type.bool, cond),
+                };
 
-                break :blk .ne;
-            },
-            .stack_offset,
-            .memory,
-            .stack_argument_offset,
-            => blk: {
                 try self.spillCompareFlagsIfOccupied();
 
-                const reg = try self.copyToTmpRegister(Type.initTag(.bool), cond);
-
                 // cmp reg, 1
                 // bne ...
                 _ = try self.addInst(.{
                     .tag = .cmp,
+                    .cond = .al,
                     .data = .{ .rr_op = .{
                         .rd = .r0,
                         .rn = reg,
@@ -2914,7 +2898,6 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
 
                 break :blk .ne;
             },
-            else => return self.fail("TODO implement condbr {} when condition is {s}", .{ self.target.cpu.arch, @tagName(cond) }),
         };
 
         break :reloc try self.addInst(.{
@@ -3603,9 +3586,18 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
                         try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
                     },
                     .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }),
-                    .embedded_in_code,
-                    .stack_argument_offset,
-                    => return self.fail("TODO genSetStack with src={}", .{mcv}),
+                    .stack_argument_offset => |unadjusted_off| {
+                        const adj_off = unadjusted_off + abi_size;
+
+                        _ = try self.addInst(.{
+                            .tag = .ldr_ptr_stack_argument,
+                            .data = .{ .r_stack_offset = .{
+                                .rt = src_reg,
+                                .stack_offset = adj_off,
+                            } },
+                        });
+                    },
+                    .embedded_in_code => return self.fail("TODO genSetStack with src={}", .{mcv}),
                     else => unreachable,
                 }
 
src/arch/arm/Emit.zig
@@ -112,6 +112,7 @@ pub fn emitMir(
             .str => try emit.mirLoadStore(inst),
             .strb => try emit.mirLoadStore(inst),
 
+            .ldr_ptr_stack_argument => try emit.mirLoadStackArgument(inst),
             .ldr_stack_argument => try emit.mirLoadStackArgument(inst),
             .ldrb_stack_argument => try emit.mirLoadStackArgument(inst),
             .ldrh_stack_argument => try emit.mirLoadStackArgument(inst),
@@ -597,6 +598,12 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
 
     const raw_offset = emit.prologue_stack_space - r_stack_offset.stack_offset;
     switch (tag) {
+        .ldr_ptr_stack_argument => {
+            const operand = Instruction.Operand.fromU32(raw_offset) orelse
+                return emit.fail("TODO mirLoadStack larger offsets", .{});
+
+            try emit.writeInstruction(Instruction.add(cond, r_stack_offset.rt, .fp, operand));
+        },
         .ldr_stack_argument,
         .ldrb_stack_argument,
         => {
src/arch/arm/Mir.zig
@@ -54,6 +54,8 @@ pub const Inst = struct {
         eor,
         /// Load Register
         ldr,
+        /// Pseudo-instruction: Load pointer to stack argument offset
+        ldr_ptr_stack_argument,
         /// Load Register
         ldr_stack_argument,
         /// Load Register Byte
test/behavior/bugs/1421.zig
@@ -9,7 +9,6 @@ const S = struct {
 };
 
 test "functions with return type required to be comptime are generic" {
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
test/behavior/bugs/2692.zig
@@ -6,7 +6,6 @@ fn foo(a: []u8) void {
 
 test "address of 0 length array" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 
     var pt: [0]u8 = undefined;
test/behavior/bugs/5474.zig
@@ -49,15 +49,11 @@ fn constant() !void {
 }
 
 test "pointer-to-array constness for zero-size elements, var" {
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
-
     try mutable();
     comptime try mutable();
 }
 
 test "pointer-to-array constness for zero-size elements, const" {
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
-
     try constant();
     comptime try constant();
 }
test/behavior/bugs/828.zig
@@ -30,7 +30,6 @@ fn constCount(comptime cb: *const CountBy, comptime unused: u32) void {
 }
 
 test "comptime struct return should not return the same instance" {
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 
     //the first parameter must be passed by reference to trigger the bug
test/behavior/array.zig
@@ -202,7 +202,6 @@ fn doSomeMangling(array: *[4]u8) void {
 
 test "implicit cast zero sized array ptr to slice" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 
     {
         var b = "".*;
test/behavior/bitcast.zig
@@ -269,7 +269,6 @@ test "bitcast passed as tuple element" {
 
 test "triple level result location with bitcast sandwich passed as tuple element" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 
     const S = struct {
         fn foo(args: anytype) !void {
test/behavior/cast.zig
@@ -1129,7 +1129,6 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
 test "peer type resolution: [0]u8 and []const u8" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
     try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
@@ -1278,8 +1277,6 @@ test "assignment to optional pointer result loc" {
 }
 
 test "cast between *[N]void and []void" {
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
-
     var a: [4]void = undefined;
     var b: []void = &a;
     try expect(b.len == 4);
test/behavior/optional.zig
@@ -26,7 +26,6 @@ pub const EmptyStruct = struct {};
 
 test "optional pointer to size zero struct" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     var e = EmptyStruct{};
     var o: ?*EmptyStruct = &e;
test/behavior/sizeof_and_typeof.zig
@@ -186,7 +186,6 @@ test "@sizeOf(T) == 0 doesn't force resolving struct size" {
 }
 
 test "@TypeOf() has no runtime side effects" {
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
     const S = struct {
test/behavior/slice.zig
@@ -70,7 +70,6 @@ test "comptime slice of undefined pointer of length 0" {
 test "implicitly cast array of size 0 to slice" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 
     var msg = [_]u8{};
     try assertLenIsZero(&msg);
@@ -206,7 +205,6 @@ const y = x[0x100..];
 test "compile time slice of pointer to hard coded address" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage1) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
 
test/behavior/struct.zig
@@ -926,7 +926,6 @@ test "anonymous struct literal syntax" {
 
 test "fully anonymous struct" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     const S = struct {
         fn doTheTest() !void {
@@ -951,7 +950,6 @@ test "fully anonymous struct" {
 
 test "fully anonymous list literal" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     const S = struct {
         fn doTheTest() !void {
test/behavior/struct_contains_null_ptr_itself.zig
@@ -3,7 +3,6 @@ const expect = std.testing.expect;
 const builtin = @import("builtin");
 
 test "struct contains null pointer which contains original struct" {
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
test/behavior/var_args.zig
@@ -14,7 +14,6 @@ fn add(args: anytype) i32 {
 
 test "add arbitrary args" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
     try expect(add(.{@as(i32, 1234)}) == 1234);
@@ -27,14 +26,12 @@ fn readFirstVarArg(args: anytype) void {
 
 test "send void arg to var args" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     readFirstVarArg(.{{}});
 }
 
 test "pass args directly" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
 
     try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
@@ -89,7 +86,6 @@ fn foo2(args: anytype) bool {
 
 test "array of var args functions" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     try expect(foos[0](.{}));
     try expect(!foos[1](.{}));
@@ -97,7 +93,6 @@ test "array of var args functions" {
 
 test "pass zero length array to var args param" {
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     doNothingWithFirstArg(.{""});
 }