From 1bf8da19e1b58159b27033d415b7289cf455b870 Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Sun, 27 Feb 2022 21:38:09 +0100 Subject: [PATCH] stage2 ARM: implement slice and array_to_slice --- src/arch/arm/CodeGen.zig | 33 ++++++++++++++++++++++++++++----- test/behavior/array.zig | 2 -- test/behavior/cast.zig | 3 --- test/behavior/if.zig | 1 - test/behavior/slice.zig | 2 -- test/behavior/while.zig | 1 - 6 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 51b2e7f1a8..6cd4a1fd9f 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -433,7 +433,9 @@ fn gen(self: *Self) !void { }); // exitlude jumps - if (self.exitlude_jump_relocs.items.len == 1) { + const only_one_exitlude_jump = self.exitlude_jump_relocs.items.len == 1 and + self.exitlude_jump_relocs.items[0] == self.mir_instructions.len - 1; + if (only_one_exitlude_jump) { // There is only one relocation. Hence, // this relocation must be at the end of // the code. Therefore, we can just delete @@ -1066,7 +1068,17 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void { fn airSlice(self: *Self, inst: Air.Inst.Index) !void { const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice for {}", .{self.target.cpu.arch}); + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { + const ptr = try self.resolveInst(bin_op.lhs); + const ptr_ty = self.air.typeOf(bin_op.lhs); + const len = try self.resolveInst(bin_op.rhs); + const len_ty = self.air.typeOf(bin_op.rhs); + + const stack_offset = try self.allocMem(inst, 8, 8); + try self.genSetStack(ptr_ty, stack_offset + 4, ptr); + try self.genSetStack(len_ty, stack_offset, len); + break :result MCValue{ .stack_offset = stack_offset }; + }; return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); } @@ -3855,9 +3867,17 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airArrayToSlice for {}", .{ - self.target.cpu.arch, - }); + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { + const ptr_ty = self.air.typeOf(ty_op.operand); + const ptr = try self.resolveInst(ty_op.operand); + const array_ty = ptr_ty.childType(); + const array_len = @intCast(u32, array_ty.arrayLenIncludingSentinel()); + + const stack_offset = try self.allocMem(inst, 8, 8); + try self.genSetStack(ptr_ty, stack_offset + 4, ptr); + try self.genSetStack(Type.initTag(.usize), stack_offset, .{ .immediate = array_len }); + break :result MCValue{ .stack_offset = stack_offset }; + }; return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } @@ -4078,6 +4098,9 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { } switch (typed_value.ty.zigTypeTag()) { + .Array => { + return self.lowerUnnamedConst(typed_value); + }, .Pointer => switch (typed_value.ty.ptrSize()) { .Slice => { return self.lowerUnnamedConst(typed_value); diff --git a/test/behavior/array.zig b/test/behavior/array.zig index 1d6a149560..58c676b7b8 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -49,7 +49,6 @@ fn getArrayLen(a: []const u32) usize { test "array init with mult" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const a = 'a'; var i: [8]u8 = [2]u8{ a, 'b' } ** 4; @@ -98,7 +97,6 @@ test "array literal with specified size" { test "array len field" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; var arr = [4]u8{ 0, 0, 0, 0 }; var ptr = &arr; diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index e237fa8439..819739083b 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -273,7 +273,6 @@ test "*const ?[*]const T to [*c]const [*c]const T" { test "array coersion to undefined at runtime" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; @setRuntimeSafety(true); @@ -337,7 +336,6 @@ test "peer type unsigned int to signed" { test "expected [*c]const u8, found [*:0]const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; var a: [*:0]const u8 = "hello"; var b: [*c]const u8 = a; @@ -648,7 +646,6 @@ test "peer cast *[0]T to []const T" { test "peer cast *[N]T to [*]T" { 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 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO var array = [4:99]i32{ 1, 2, 3, 4 }; diff --git a/test/behavior/if.zig b/test/behavior/if.zig index 54ee5338af..cf7a932ccb 100644 --- a/test/behavior/if.zig +++ b/test/behavior/if.zig @@ -4,7 +4,6 @@ const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; test "if statements" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; shouldBeEqual(1, 1); diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index c6405fd168..992a187a3e 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -257,7 +257,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { test "C pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf"; var len: u32 = 10; @@ -356,7 +355,6 @@ test "empty array to slice" { test "@ptrCast slice to pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const S = struct { fn doTheTest() !void { diff --git a/test/behavior/while.zig b/test/behavior/while.zig index 86724d166a..03670d28a7 100644 --- a/test/behavior/while.zig +++ b/test/behavior/while.zig @@ -249,7 +249,6 @@ fn returnTrue() bool { test "return with implicit cast from while loop" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; returnWithImplicitCastFromWhileLoopTest() catch unreachable;