Skip to content

Commit a06e9ec

Browse files
stage2 AArch64: add more slice support
* airSlice * airArrayToSlice * and initial support for airSlicePtr and co
1 parent ed7e293 commit a06e9ec

27 files changed

+71
-180
lines changed

src/arch/aarch64/CodeGen.zig

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -818,9 +818,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
818818

819819
if (reg_ok) {
820820
// Make sure the type can fit in a register before we try to allocate one.
821-
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
822-
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
823-
if (abi_size <= ptr_bytes) {
821+
if (abi_size <= 8) {
824822
if (self.register_manager.tryAllocReg(inst)) |reg| {
825823
return MCValue{ .register = registerAlias(reg, abi_size) };
826824
}
@@ -1038,7 +1036,20 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void {
10381036
fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
10391037
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
10401038
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1041-
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice for {}", .{self.target.cpu.arch});
1039+
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1040+
const ptr = try self.resolveInst(bin_op.lhs);
1041+
const ptr_ty = self.air.typeOf(bin_op.lhs);
1042+
const len = try self.resolveInst(bin_op.rhs);
1043+
const len_ty = self.air.typeOf(bin_op.rhs);
1044+
1045+
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1046+
const ptr_bytes = @divExact(ptr_bits, 8);
1047+
1048+
const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
1049+
try self.genSetStack(ptr_ty, stack_offset + ptr_bytes, ptr);
1050+
try self.genSetStack(len_ty, stack_offset, len);
1051+
break :result MCValue{ .stack_offset = stack_offset };
1052+
};
10421053
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
10431054
}
10441055

@@ -1602,22 +1613,39 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
16021613

16031614
fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
16041615
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1605-
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch});
1616+
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1617+
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1618+
const ptr_bytes = @divExact(ptr_bits, 8);
1619+
const mcv = try self.resolveInst(ty_op.operand);
1620+
switch (mcv) {
1621+
.dead, .unreach, .none => unreachable,
1622+
.register => unreachable, // a slice doesn't fit in one register
1623+
.stack_offset => |off| {
1624+
break :result MCValue{ .stack_offset = off + ptr_bytes };
1625+
},
1626+
.memory => |addr| {
1627+
break :result MCValue{ .memory = addr };
1628+
},
1629+
else => return self.fail("TODO implement slice_len for {}", .{mcv}),
1630+
}
1631+
};
16061632
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
16071633
}
16081634

16091635
fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
16101636
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
16111637
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1638+
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1639+
const ptr_bytes = @divExact(ptr_bits, 8);
16121640
const mcv = try self.resolveInst(ty_op.operand);
16131641
switch (mcv) {
1614-
.dead, .unreach => unreachable,
1642+
.dead, .unreach, .none => unreachable,
16151643
.register => unreachable, // a slice doesn't fit in one register
16161644
.stack_offset => |off| {
16171645
break :result MCValue{ .stack_offset = off };
16181646
},
16191647
.memory => |addr| {
1620-
break :result MCValue{ .memory = addr + 8 };
1648+
break :result MCValue{ .memory = addr + ptr_bytes };
16211649
},
16221650
else => return self.fail("TODO implement slice_len for {}", .{mcv}),
16231651
}
@@ -1627,13 +1655,33 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
16271655

16281656
fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
16291657
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1630-
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_slice_len_ptr for {}", .{self.target.cpu.arch});
1658+
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1659+
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1660+
const ptr_bytes = @divExact(ptr_bits, 8);
1661+
const mcv = try self.resolveInst(ty_op.operand);
1662+
switch (mcv) {
1663+
.dead, .unreach, .none => unreachable,
1664+
.ptr_stack_offset => |off| {
1665+
break :result MCValue{ .ptr_stack_offset = off + ptr_bytes };
1666+
},
1667+
else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}),
1668+
}
1669+
};
16311670
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
16321671
}
16331672

16341673
fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
16351674
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1636-
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{self.target.cpu.arch});
1675+
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1676+
const mcv = try self.resolveInst(ty_op.operand);
1677+
switch (mcv) {
1678+
.dead, .unreach, .none => unreachable,
1679+
.ptr_stack_offset => |off| {
1680+
break :result MCValue{ .ptr_stack_offset = off };
1681+
},
1682+
else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}),
1683+
}
1684+
};
16371685
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
16381686
}
16391687

@@ -3475,9 +3523,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
34753523

34763524
fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
34773525
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3478-
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airArrayToSlice for {}", .{
3479-
self.target.cpu.arch,
3480-
});
3526+
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3527+
const ptr_ty = self.air.typeOf(ty_op.operand);
3528+
const ptr = try self.resolveInst(ty_op.operand);
3529+
const array_ty = ptr_ty.childType();
3530+
const array_len = @intCast(u32, array_ty.arrayLen());
3531+
3532+
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
3533+
const ptr_bytes = @divExact(ptr_bits, 8);
3534+
3535+
const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
3536+
try self.genSetStack(ptr_ty, stack_offset + ptr_bytes, ptr);
3537+
try self.genSetStack(Type.initTag(.usize), stack_offset, .{ .immediate = array_len });
3538+
break :result MCValue{ .stack_offset = stack_offset };
3539+
};
34813540
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
34823541
}
34833542

test/behavior/align.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,6 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
269269

270270
test "runtime known array index has best alignment possible" {
271271
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
272-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
273272
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
274273

275274
// take full advantage of over-alignment

test/behavior/array.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,6 @@ test "array with sentinels" {
142142
}
143143

144144
test "void arrays" {
145-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
146-
147145
var array: [4]void = undefined;
148146
array[0] = void{};
149147
array[1] = array[2];

test/behavior/bitcast.zig

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe
7575
}
7676

7777
test "nested bitcast" {
78-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
79-
8078
const S = struct {
8179
fn moo(x: isize) !void {
8280
try expect(@intCast(isize, 42) == x);
@@ -94,8 +92,6 @@ test "nested bitcast" {
9492
}
9593

9694
test "@bitCast enum to its integer type" {
97-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
98-
9995
const SOCK = enum(c_int) {
10096
A,
10197
B,
@@ -113,15 +109,11 @@ test "@bitCast enum to its integer type" {
113109

114110
// issue #3010: compiler segfault
115111
test "bitcast literal [4]u8 param to u32" {
116-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
117-
118112
const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
119113
try expect(ip == maxInt(u32));
120114
}
121115

122116
test "bitcast generates a temporary value" {
123-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
124-
125117
var y = @as(u16, 0x55AA);
126118
const x = @bitCast(u16, @bitCast([2]u8, y));
127119
try expect(y == x);
@@ -240,7 +232,6 @@ test "implicit cast to error union by returning" {
240232
test "bitcast packed struct literal to byte" {
241233
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
242234
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
243-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
244235

245236
const Foo = packed struct {
246237
value: u8,
@@ -252,7 +243,6 @@ test "bitcast packed struct literal to byte" {
252243
test "comptime bitcast used in expression has the correct type" {
253244
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
254245
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
255-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
256246

257247
const Foo = packed struct {
258248
value: u8,

test/behavior/bugs/3367.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const Mixin = struct {
1010
};
1111

1212
test "container member access usingnamespace decls" {
13-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1413
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1514
var foo = Foo{};
1615
foo.two();

test/behavior/bugs/3586.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ const Container = struct {
77
};
88

99
test "fixed" {
10-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11-
1210
var ctr = Container{
1311
.params = NoteParams{},
1412
};

test/behavior/bugs/704.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ const xxx = struct {
66
}
77
};
88
test "bug 704" {
9-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10-
119
var x: xxx = undefined;
1210
x.bar();
1311
}

test/behavior/cast.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,6 @@ test "peer type resolve array pointers, one of them const" {
984984
test "peer type resolve array pointer and unknown pointer" {
985985
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
986986
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
987-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
988987
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
989988
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
990989

@@ -1255,7 +1254,6 @@ test "assignment to optional pointer result loc" {
12551254
}
12561255

12571256
test "cast between *[N]void and []void" {
1258-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12591257
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12601258

12611259
var a: [4]void = undefined;

test/behavior/defer.zig

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ const expectEqual = std.testing.expectEqual;
55
const expectError = std.testing.expectError;
66

77
test "break and continue inside loop inside defer expression" {
8-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9-
108
testBreakContInDefer(10);
119
comptime testBreakContInDefer(10);
1210
}
@@ -23,8 +21,6 @@ fn testBreakContInDefer(x: usize) void {
2321
}
2422

2523
test "defer and labeled break" {
26-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
27-
2824
var i = @as(usize, 0);
2925

3026
blk: {

0 commit comments

Comments
 (0)