authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-09-06 12:34:27+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-09-09 19:17:18+02:00
logb976997e16835e822ef9400973ac12a20e3d0705
treea78725862b74dac733eca2a90961cf7875cbcede
parenta0a7d15142cfffbab934860064a44b7615f9dd55
signature Commit is signed but in an unrecognized format.

stage2 ARM: implement ptr_elem_val


8 files changed, 75 insertions(+), 91 deletions(-)

src/arch/arm/CodeGen.zig+75-75
...@@ -2258,89 +2258,84 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2258,89 +2258,84 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
2258 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2258 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2259}2259}
22602260
2261fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {2261fn ptrElemVal(
2262 const is_volatile = false; // TODO2262 self: *Self,
2263 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2263 ptr_bind: ReadArg.Bind,
22642264 index_bind: ReadArg.Bind,
2265 if (!is_volatile and self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });2265 ptr_ty: Type,
2266 const result: MCValue = result: {2266 maybe_inst: ?Air.Inst.Index,
2267 const slice_mcv = try self.resolveInst(bin_op.lhs);2267) !MCValue {
22682268 const elem_ty = ptr_ty.childType();
2269 // TODO optimize for the case where the index is a constant,2269 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
2270 // i.e. index_mcv == .immediate
2271 const index_mcv = try self.resolveInst(bin_op.rhs);
2272 const index_is_register = index_mcv == .register;
2273
2274 const slice_ty = self.air.typeOf(bin_op.lhs);
2275 const elem_ty = slice_ty.childType();
2276 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
2277
2278 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2279 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
2280
2281 const index_lock: ?RegisterLock = if (index_is_register)
2282 self.register_manager.lockRegAssumeUnused(index_mcv.register)
2283 else
2284 null;
2285 defer if (index_lock) |reg| self.register_manager.unlockReg(reg);
22862270
2287 const base_mcv = slicePtr(slice_mcv);2271 switch (elem_size) {
2272 1, 4 => {
2273 var base_reg: Register = undefined;
2274 var index_reg: Register = undefined;
2275 var dest_reg: Register = undefined;
22882276
2289 switch (elem_size) {2277 const read_args = [_]ReadArg{
2290 1, 4 => {2278 .{ .ty = ptr_ty, .bind = ptr_bind, .class = gp, .reg = &base_reg },
2291 const base_reg = switch (base_mcv) {2279 .{ .ty = Type.usize, .bind = index_bind, .class = gp, .reg = &index_reg },
2292 .register => |r| r,2280 };
2293 else => try self.copyToTmpRegister(slice_ptr_field_type, base_mcv),2281 const write_args = [_]WriteArg{
2294 };2282 .{ .ty = elem_ty, .bind = .none, .class = gp, .reg = &dest_reg },
2295 const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg);2283 };
2296 defer self.register_manager.unlockReg(base_reg_lock);2284 try self.allocRegs(
2285 &read_args,
2286 &write_args,
2287 if (maybe_inst) |inst| .{
2288 .corresponding_inst = inst,
2289 .operand_mapping = &.{ 0, 1 },
2290 } else null,
2291 );
22972292
2298 const dst_reg = try self.register_manager.allocReg(inst, gp);2293 const tag: Mir.Inst.Tag = switch (elem_size) {
2299 const dst_mcv = MCValue{ .register = dst_reg };2294 1 => .ldrb,
2300 const dst_reg_lock = self.register_manager.lockRegAssumeUnused(dst_reg);2295 4 => .ldr,
2301 defer self.register_manager.unlockReg(dst_reg_lock);2296 else => unreachable,
2297 };
2298 const shift: u5 = switch (elem_size) {
2299 1 => 0,
2300 4 => 2,
2301 else => unreachable,
2302 };
23022303
2303 const index_reg: Register = switch (index_mcv) {2304 _ = try self.addInst(.{
2304 .register => |reg| reg,2305 .tag = tag,
2305 else => try self.copyToTmpRegister(Type.usize, index_mcv),2306 .data = .{ .rr_offset = .{
2306 };2307 .rt = dest_reg,
2307 const index_reg_lock = self.register_manager.lockReg(index_reg);2308 .rn = base_reg,
2308 defer if (index_reg_lock) |lock| self.register_manager.unlockReg(lock);2309 .offset = .{ .offset = Instruction.Offset.reg(index_reg, .{ .lsl = shift }) },
2310 } },
2311 });
23092312
2310 const tag: Mir.Inst.Tag = switch (elem_size) {2313 return MCValue{ .register = dest_reg };
2311 1 => .ldrb,2314 },
2312 4 => .ldr,2315 else => {
2313 else => unreachable,2316 const addr = try self.ptrArithmetic(.ptr_add, ptr_bind, index_bind, ptr_ty, Type.usize, null);
2314 };
2315 const shift: u5 = switch (elem_size) {
2316 1 => 0,
2317 4 => 2,
2318 else => unreachable,
2319 };
23202317
2321 _ = try self.addInst(.{2318 const dest = try self.allocRegOrMem(elem_ty, true, maybe_inst);
2322 .tag = tag,2319 try self.load(dest, addr, ptr_ty);
2323 .data = .{ .rr_offset = .{2320 return dest;
2324 .rt = dst_reg,2321 },
2325 .rn = base_reg,2322 }
2326 .offset = .{ .offset = Instruction.Offset.reg(index_reg, .{ .lsl = shift }) },2323}
2327 } },
2328 });
23292324
2330 break :result dst_mcv;2325fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2331 },2326 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2332 else => {2327 const slice_ty = self.air.typeOf(bin_op.lhs);
2333 const dest = try self.allocRegOrMem(self.air.typeOfIndex(inst), true, inst);2328 const result: MCValue = if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
2329 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2330 const ptr_ty = slice_ty.slicePtrFieldType(&buf);
23342331
2335 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };2332 const slice_mcv = try self.resolveInst(bin_op.lhs);
2336 const index_bind: ReadArg.Bind = .{ .mcv = index_mcv };2333 const base_mcv = slicePtr(slice_mcv);
23372334
2338 const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ptr_field_type, Type.usize, null);2335 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };
2339 try self.load(dest, addr, slice_ptr_field_type);2336 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
23402337
2341 break :result dest;2338 break :result try self.ptrElemVal(base_bind, index_bind, ptr_ty, inst);
2342 },
2343 }
2344 };2339 };
2345 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2340 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2346}2341}
...@@ -2371,9 +2366,14 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2371,9 +2366,14 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2371}2366}
23722367
2373fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {2368fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2374 const is_volatile = false; // TODO
2375 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2369 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2376 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_elem_val for {}", .{self.target.cpu.arch});2370 const ptr_ty = self.air.typeOf(bin_op.lhs);
2371 const result: MCValue = if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
2372 const base_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
2373 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
2374
2375 break :result try self.ptrElemVal(base_bind, index_bind, ptr_ty, inst);
2376 };
2377 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2377 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2378}2378}
23792379
test/behavior/basic.zig-1
...@@ -641,7 +641,6 @@ test "global constant is loaded with a runtime-known index" {...@@ -641,7 +641,6 @@ test "global constant is loaded with a runtime-known index" {
641641
642test "multiline string literal is null terminated" {642test "multiline string literal is null terminated" {
643 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;643 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
644 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
645644
646 const s1 =645 const s1 =
647 \\one646 \\one
test/behavior/cast.zig-3
...@@ -576,7 +576,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void {...@@ -576,7 +576,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void {
576test "cast *[1][*]const u8 to [*]const ?[*]const u8" {576test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
578 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO578 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
579 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
580 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO579 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
581580
582 const window_name = [1][*]const u8{"window name"};581 const window_name = [1][*]const u8{"window name"};
...@@ -919,7 +918,6 @@ test "peer cast *[N:x]T to *[N]T" {...@@ -919,7 +918,6 @@ test "peer cast *[N:x]T to *[N]T" {
919918
920test "peer cast [*:x]T to [*]T" {919test "peer cast [*:x]T to [*]T" {
921 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO920 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
922 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
923 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO921 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
924922
925 const S = struct {923 const S = struct {
...@@ -1004,7 +1002,6 @@ test "variable initialization uses result locations properly with regards to the...@@ -1004,7 +1002,6 @@ test "variable initialization uses result locations properly with regards to the
10041002
1005test "cast between C pointer with different but compatible types" {1003test "cast between C pointer with different but compatible types" {
1006 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1004 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1007 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10081005
1009 const S = struct {1006 const S = struct {
1010 fn foo(arg: [*]c_ushort) u16 {1007 fn foo(arg: [*]c_ushort) u16 {
test/behavior/const_slice_child.zig-1
...@@ -9,7 +9,6 @@ var argv: [*]const [*]const u8 = undefined;...@@ -9,7 +9,6 @@ var argv: [*]const [*]const u8 = undefined;
9test "const slice child" {9test "const slice child" {
10 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1312
14 const strs = [_][*]const u8{ "one", "two", "three" };13 const strs = [_][*]const u8{ "one", "two", "three" };
15 argv = &strs;14 argv = &strs;
test/behavior/eval.zig-5
...@@ -137,7 +137,6 @@ test "pointer to type" {...@@ -137,7 +137,6 @@ test "pointer to type" {
137test "a type constructed in a global expression" {137test "a type constructed in a global expression" {
138 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
141140
142 var l: List = undefined;141 var l: List = undefined;
143 l.array[0] = 10;142 l.array[0] = 10;
...@@ -804,7 +803,6 @@ test "array concatenation sets the sentinel - value" {...@@ -804,7 +803,6 @@ test "array concatenation sets the sentinel - value" {
804test "array concatenation sets the sentinel - pointer" {803test "array concatenation sets the sentinel - pointer" {
805 if (builtin.zig_backend == .stage1) return error.SkipZigTest;804 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
806 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;805 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
807 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
808 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;806 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
809807
810 var a = [2]u3{ 1, 7 };808 var a = [2]u3{ 1, 7 };
...@@ -1071,7 +1069,6 @@ test "comptime break operand passing through runtime switch converted to runtime...@@ -1071,7 +1069,6 @@ test "comptime break operand passing through runtime switch converted to runtime
10711069
1072test "no dependency loop for alignment of self struct" {1070test "no dependency loop for alignment of self struct" {
1073 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1071 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1074 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10751072
1076 const S = struct {1073 const S = struct {
1077 fn doTheTest() !void {1074 fn doTheTest() !void {
...@@ -1108,7 +1105,6 @@ test "no dependency loop for alignment of self struct" {...@@ -1108,7 +1105,6 @@ test "no dependency loop for alignment of self struct" {
11081105
1109test "no dependency loop for alignment of self bare union" {1106test "no dependency loop for alignment of self bare union" {
1110 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1111 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11121108
1113 const S = struct {1109 const S = struct {
1114 fn doTheTest() !void {1110 fn doTheTest() !void {
...@@ -1145,7 +1141,6 @@ test "no dependency loop for alignment of self bare union" {...@@ -1145,7 +1141,6 @@ test "no dependency loop for alignment of self bare union" {
11451141
1146test "no dependency loop for alignment of self tagged union" {1142test "no dependency loop for alignment of self tagged union" {
1147 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1143 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1148 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11491144
1150 const S = struct {1145 const S = struct {
1151 fn doTheTest() !void {1146 fn doTheTest() !void {
test/behavior/generics.zig-1
...@@ -91,7 +91,6 @@ fn max_f64(a: f64, b: f64) f64 {...@@ -91,7 +91,6 @@ fn max_f64(a: f64, b: f64) f64 {
9191
92test "type constructed by comptime function call" {92test "type constructed by comptime function call" {
93 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;93 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
94 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
95 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;94 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9695
97 var l: SimpleList(10) = undefined;96 var l: SimpleList(10) = undefined;
test/behavior/pointers.zig-4
...@@ -18,7 +18,6 @@ fn testDerefPtr() !void {...@@ -18,7 +18,6 @@ fn testDerefPtr() !void {
1818
19test "pointer arithmetic" {19test "pointer arithmetic" {
20 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2322
24 var ptr: [*]const u8 = "abcd";23 var ptr: [*]const u8 = "abcd";
...@@ -280,7 +279,6 @@ test "array initialization types" {...@@ -280,7 +279,6 @@ test "array initialization types" {
280279
281test "null terminated pointer" {280test "null terminated pointer" {
282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;281 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
284 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO282 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
285283
286 const S = struct {284 const S = struct {
...@@ -298,7 +296,6 @@ test "null terminated pointer" {...@@ -298,7 +296,6 @@ test "null terminated pointer" {
298296
299test "allow any sentinel" {297test "allow any sentinel" {
300 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;298 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
301 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
302 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO299 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
303300
304 const S = struct {301 const S = struct {
...@@ -314,7 +311,6 @@ test "allow any sentinel" {...@@ -314,7 +311,6 @@ test "allow any sentinel" {
314311
315test "pointer sentinel with enums" {312test "pointer sentinel with enums" {
316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
317 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO314 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
319315
320 const S = struct {316 const S = struct {
test/behavior/union.zig-1
...@@ -92,7 +92,6 @@ const FooExtern = extern union {...@@ -92,7 +92,6 @@ const FooExtern = extern union {
92};92};
9393
94test "basic extern unions" {94test "basic extern unions" {
95 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
96 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;95 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9796
98 var foo = FooExtern{ .int = 1 };97 var foo = FooExtern{ .int = 1 };