| author | |
| committer | |
| log | b976997e16835e822ef9400973ac12a20e3d0705 |
| tree | a78725862b74dac733eca2a90961cf7875cbcede |
| parent | a0a7d15142cfffbab934860064a44b7615f9dd55 |
| signature | Commit is signed but in an unrecognized format. |
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 | 2258 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2259 | 2259 | } |
| 2260 | 2260 | |
| 2261 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | |
| 2262 | const is_volatile = false; // TODO | |
| 2263 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | |
| 2264 | ||
| 2265 | if (!is_volatile and self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | |
| 2266 | const result: MCValue = result: { | |
| 2267 | const slice_mcv = try self.resolveInst(bin_op.lhs); | |
| 2268 | ||
| 2269 | // TODO optimize for the case where the index is a constant, | |
| 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); | |
| 2261 | fn ptrElemVal( | |
| 2262 | self: *Self, | |
| 2263 | ptr_bind: ReadArg.Bind, | |
| 2264 | index_bind: ReadArg.Bind, | |
| 2265 | ptr_ty: Type, | |
| 2266 | maybe_inst: ?Air.Inst.Index, | |
| 2267 | ) !MCValue { | |
| 2268 | const elem_ty = ptr_ty.childType(); | |
| 2269 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | |
| 2286 | 2270 | |
| 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; | |
| 2288 | 2276 | |
| 2289 | switch (elem_size) { | |
| 2290 | 1, 4 => { | |
| 2291 | const base_reg = switch (base_mcv) { | |
| 2292 | .register => |r| r, | |
| 2293 | else => try self.copyToTmpRegister(slice_ptr_field_type, base_mcv), | |
| 2294 | }; | |
| 2295 | const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg); | |
| 2296 | defer self.register_manager.unlockReg(base_reg_lock); | |
| 2277 | const read_args = [_]ReadArg{ | |
| 2278 | .{ .ty = ptr_ty, .bind = ptr_bind, .class = gp, .reg = &base_reg }, | |
| 2279 | .{ .ty = Type.usize, .bind = index_bind, .class = gp, .reg = &index_reg }, | |
| 2280 | }; | |
| 2281 | const write_args = [_]WriteArg{ | |
| 2282 | .{ .ty = elem_ty, .bind = .none, .class = gp, .reg = &dest_reg }, | |
| 2283 | }; | |
| 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 | ); | |
| 2297 | 2292 | |
| 2298 | const dst_reg = try self.register_manager.allocReg(inst, gp); | |
| 2299 | const dst_mcv = MCValue{ .register = dst_reg }; | |
| 2300 | const dst_reg_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | |
| 2301 | defer self.register_manager.unlockReg(dst_reg_lock); | |
| 2293 | const tag: Mir.Inst.Tag = switch (elem_size) { | |
| 2294 | 1 => .ldrb, | |
| 2295 | 4 => .ldr, | |
| 2296 | else => unreachable, | |
| 2297 | }; | |
| 2298 | const shift: u5 = switch (elem_size) { | |
| 2299 | 1 => 0, | |
| 2300 | 4 => 2, | |
| 2301 | else => unreachable, | |
| 2302 | }; | |
| 2302 | 2303 | |
| 2303 | const index_reg: Register = switch (index_mcv) { | |
| 2304 | .register => |reg| reg, | |
| 2305 | else => try self.copyToTmpRegister(Type.usize, index_mcv), | |
| 2306 | }; | |
| 2307 | const index_reg_lock = self.register_manager.lockReg(index_reg); | |
| 2308 | defer if (index_reg_lock) |lock| self.register_manager.unlockReg(lock); | |
| 2304 | _ = try self.addInst(.{ | |
| 2305 | .tag = tag, | |
| 2306 | .data = .{ .rr_offset = .{ | |
| 2307 | .rt = dest_reg, | |
| 2308 | .rn = base_reg, | |
| 2309 | .offset = .{ .offset = Instruction.Offset.reg(index_reg, .{ .lsl = shift }) }, | |
| 2310 | } }, | |
| 2311 | }); | |
| 2309 | 2312 | |
| 2310 | const tag: Mir.Inst.Tag = switch (elem_size) { | |
| 2311 | 1 => .ldrb, | |
| 2312 | 4 => .ldr, | |
| 2313 | else => unreachable, | |
| 2314 | }; | |
| 2315 | const shift: u5 = switch (elem_size) { | |
| 2316 | 1 => 0, | |
| 2317 | 4 => 2, | |
| 2318 | else => unreachable, | |
| 2319 | }; | |
| 2313 | return MCValue{ .register = dest_reg }; | |
| 2314 | }, | |
| 2315 | else => { | |
| 2316 | const addr = try self.ptrArithmetic(.ptr_add, ptr_bind, index_bind, ptr_ty, Type.usize, null); | |
| 2320 | 2317 | |
| 2321 | _ = try self.addInst(.{ | |
| 2322 | .tag = tag, | |
| 2323 | .data = .{ .rr_offset = .{ | |
| 2324 | .rt = dst_reg, | |
| 2325 | .rn = base_reg, | |
| 2326 | .offset = .{ .offset = Instruction.Offset.reg(index_reg, .{ .lsl = shift }) }, | |
| 2327 | } }, | |
| 2328 | }); | |
| 2318 | const dest = try self.allocRegOrMem(elem_ty, true, maybe_inst); | |
| 2319 | try self.load(dest, addr, ptr_ty); | |
| 2320 | return dest; | |
| 2321 | }, | |
| 2322 | } | |
| 2323 | } | |
| 2329 | 2324 | |
| 2330 | break :result dst_mcv; | |
| 2331 | }, | |
| 2332 | else => { | |
| 2333 | const dest = try self.allocRegOrMem(self.air.typeOfIndex(inst), true, inst); | |
| 2325 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | |
| 2326 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | |
| 2327 | const slice_ty = self.air.typeOf(bin_op.lhs); | |
| 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); | |
| 2334 | 2331 | |
| 2335 | const base_bind: ReadArg.Bind = .{ .mcv = base_mcv }; | |
| 2336 | const index_bind: ReadArg.Bind = .{ .mcv = index_mcv }; | |
| 2332 | const slice_mcv = try self.resolveInst(bin_op.lhs); | |
| 2333 | const base_mcv = slicePtr(slice_mcv); | |
| 2337 | 2334 | |
| 2338 | const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ptr_field_type, Type.usize, null); | |
| 2339 | try self.load(dest, addr, slice_ptr_field_type); | |
| 2335 | const base_bind: ReadArg.Bind = .{ .mcv = base_mcv }; | |
| 2336 | const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs }; | |
| 2340 | 2337 | |
| 2341 | break :result dest; | |
| 2342 | }, | |
| 2343 | } | |
| 2338 | break :result try self.ptrElemVal(base_bind, index_bind, ptr_ty, inst); | |
| 2344 | 2339 | }; |
| 2345 | 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 | 2366 | } |
| 2372 | 2367 | |
| 2373 | 2368 | fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2374 | const is_volatile = false; // TODO | |
| 2375 | 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 | 2377 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2378 | 2378 | } |
| 2379 | 2379 |
test/behavior/basic.zig-1| ... | ... | @@ -641,7 +641,6 @@ test "global constant is loaded with a runtime-known index" { |
| 641 | 641 | |
| 642 | 642 | test "multiline string literal is null terminated" { |
| 643 | 643 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 644 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 645 | 644 | |
| 646 | 645 | const s1 = |
| 647 | 646 | \\one |
test/behavior/cast.zig-3| ... | ... | @@ -576,7 +576,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void { |
| 576 | 576 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { |
| 577 | 577 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 578 | 578 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 579 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 580 | 579 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 581 | 580 | |
| 582 | 581 | const window_name = [1][*]const u8{"window name"}; |
| ... | ... | @@ -919,7 +918,6 @@ test "peer cast *[N:x]T to *[N]T" { |
| 919 | 918 | |
| 920 | 919 | test "peer cast [*:x]T to [*]T" { |
| 921 | 920 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 922 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 923 | 921 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 924 | 922 | |
| 925 | 923 | const S = struct { |
| ... | ... | @@ -1004,7 +1002,6 @@ test "variable initialization uses result locations properly with regards to the |
| 1004 | 1002 | |
| 1005 | 1003 | test "cast between C pointer with different but compatible types" { |
| 1006 | 1004 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1007 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1008 | 1005 | |
| 1009 | 1006 | const S = struct { |
| 1010 | 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 | 9 | test "const slice child" { |
| 10 | 10 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 11 | 11 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 12 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 13 | 12 | |
| 14 | 13 | const strs = [_][*]const u8{ "one", "two", "three" }; |
| 15 | 14 | argv = &strs; |
test/behavior/eval.zig-5| ... | ... | @@ -137,7 +137,6 @@ test "pointer to type" { |
| 137 | 137 | test "a type constructed in a global expression" { |
| 138 | 138 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 139 | 139 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 140 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 141 | 140 | |
| 142 | 141 | var l: List = undefined; |
| 143 | 142 | l.array[0] = 10; |
| ... | ... | @@ -804,7 +803,6 @@ test "array concatenation sets the sentinel - value" { |
| 804 | 803 | test "array concatenation sets the sentinel - pointer" { |
| 805 | 804 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 806 | 805 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 807 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 808 | 806 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 809 | 807 | |
| 810 | 808 | var a = [2]u3{ 1, 7 }; |
| ... | ... | @@ -1071,7 +1069,6 @@ test "comptime break operand passing through runtime switch converted to runtime |
| 1071 | 1069 | |
| 1072 | 1070 | test "no dependency loop for alignment of self struct" { |
| 1073 | 1071 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1074 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1075 | 1072 | |
| 1076 | 1073 | const S = struct { |
| 1077 | 1074 | fn doTheTest() !void { |
| ... | ... | @@ -1108,7 +1105,6 @@ test "no dependency loop for alignment of self struct" { |
| 1108 | 1105 | |
| 1109 | 1106 | test "no dependency loop for alignment of self bare union" { |
| 1110 | 1107 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1111 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1112 | 1108 | |
| 1113 | 1109 | const S = struct { |
| 1114 | 1110 | fn doTheTest() !void { |
| ... | ... | @@ -1145,7 +1141,6 @@ test "no dependency loop for alignment of self bare union" { |
| 1145 | 1141 | |
| 1146 | 1142 | test "no dependency loop for alignment of self tagged union" { |
| 1147 | 1143 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1148 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1149 | 1144 | |
| 1150 | 1145 | const S = struct { |
| 1151 | 1146 | fn doTheTest() !void { |
test/behavior/generics.zig-1| ... | ... | @@ -91,7 +91,6 @@ fn max_f64(a: f64, b: f64) f64 { |
| 91 | 91 | |
| 92 | 92 | test "type constructed by comptime function call" { |
| 93 | 93 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 94 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 95 | 94 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 96 | 95 | |
| 97 | 96 | var l: SimpleList(10) = undefined; |
test/behavior/pointers.zig-4| ... | ... | @@ -18,7 +18,6 @@ fn testDerefPtr() !void { |
| 18 | 18 | |
| 19 | 19 | test "pointer arithmetic" { |
| 20 | 20 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 21 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 22 | 21 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 23 | 22 | |
| 24 | 23 | var ptr: [*]const u8 = "abcd"; |
| ... | ... | @@ -280,7 +279,6 @@ test "array initialization types" { |
| 280 | 279 | |
| 281 | 280 | test "null terminated pointer" { |
| 282 | 281 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 283 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 284 | 282 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 285 | 283 | |
| 286 | 284 | const S = struct { |
| ... | ... | @@ -298,7 +296,6 @@ test "null terminated pointer" { |
| 298 | 296 | |
| 299 | 297 | test "allow any sentinel" { |
| 300 | 298 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 301 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 302 | 299 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 303 | 300 | |
| 304 | 301 | const S = struct { |
| ... | ... | @@ -314,7 +311,6 @@ test "allow any sentinel" { |
| 314 | 311 | |
| 315 | 312 | test "pointer sentinel with enums" { |
| 316 | 313 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 317 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 318 | 314 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 319 | 315 | |
| 320 | 316 | const S = struct { |
test/behavior/union.zig-1| ... | ... | @@ -92,7 +92,6 @@ const FooExtern = extern union { |
| 92 | 92 | }; |
| 93 | 93 | |
| 94 | 94 | test "basic extern unions" { |
| 95 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 96 | 95 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 97 | 96 | |
| 98 | 97 | var foo = FooExtern{ .int = 1 }; |