| author | |
| committer | |
| log | 65157d30ab90de01da583dd97ee2409d8ad8aeb0 |
| tree | 0c9767c8c174bfd55fd0d9c5525d4ddef1ec7ceb |
| parent | 77b8bf2b82ffa71fc8ecf85f6780130f27dbeaf3 |
| signature |
Implements the ptr_elem_val air tag. Implementation is unified
with ptr_elem_ptr.21 files changed, 36 insertions(+), 41 deletions(-)
src/codegen/spirv.zig+36-12| ... | ... | @@ -1765,6 +1765,7 @@ pub const DeclGen = struct { |
| 1765 | 1765 | .slice_elem_ptr => try self.airSliceElemPtr(inst), |
| 1766 | 1766 | .slice_elem_val => try self.airSliceElemVal(inst), |
| 1767 | 1767 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), |
| 1768 | .ptr_elem_val => try self.airPtrElemVal(inst), | |
| 1768 | 1769 | |
| 1769 | 1770 | .struct_field_val => try self.airStructFieldVal(inst), |
| 1770 | 1771 | |
| ... | ... | @@ -2482,29 +2483,52 @@ pub const DeclGen = struct { |
| 2482 | 2483 | return try self.load(slice_ty, elem_ptr); |
| 2483 | 2484 | } |
| 2484 | 2485 | |
| 2486 | fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef { | |
| 2487 | // Construct new pointer type for the resulting pointer | |
| 2488 | const elem_ty = ptr_ty.elemType2(); // use elemType() so that we get T for *[N]T. | |
| 2489 | const elem_ty_ref = try self.resolveType(elem_ty, .direct); | |
| 2490 | const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(ptr_ty.ptrAddressSpace()), 0); | |
| 2491 | if (ptr_ty.isSinglePointer()) { | |
| 2492 | // Pointer-to-array. In this case, the resulting pointer is not of the same type | |
| 2493 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. | |
| 2494 | return try self.accessChain(elem_ptr_ty_ref, ptr_id, &.{index_id}); | |
| 2495 | } else { | |
| 2496 | // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain | |
| 2497 | return try self.ptrAccessChain(elem_ptr_ty_ref, ptr_id, index_id, &.{}); | |
| 2498 | } | |
| 2499 | } | |
| 2500 | ||
| 2485 | 2501 | fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2486 | 2502 | if (self.liveness.isUnused(inst)) return null; |
| 2487 | 2503 | |
| 2488 | 2504 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2489 | 2505 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2490 | 2506 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 2491 | const result_ty = self.air.typeOfIndex(inst); | |
| 2492 | 2507 | const elem_ty = ptr_ty.childType(); |
| 2493 | 2508 | // TODO: Make this return a null ptr or something |
| 2494 | 2509 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null; |
| 2495 | 2510 | |
| 2496 | const result_ty_ref = try self.resolveType(result_ty, .direct); | |
| 2497 | const base_ptr = try self.resolve(bin_op.lhs); | |
| 2498 | const rhs = try self.resolve(bin_op.rhs); | |
| 2511 | const ptr_id = try self.resolve(bin_op.lhs); | |
| 2512 | const index_id = try self.resolve(bin_op.rhs); | |
| 2513 | return try self.ptrElemPtr(ptr_ty, ptr_id, index_id); | |
| 2514 | } | |
| 2499 | 2515 | |
| 2500 | if (ptr_ty.isSinglePointer()) { | |
| 2501 | // Pointer-to-array. In this case, the resulting pointer is not of the same type | |
| 2502 | // as the ptr_ty, and hence we need to use accessChain. | |
| 2503 | return try self.accessChain(result_ty_ref, base_ptr, &.{rhs}); | |
| 2504 | } else { | |
| 2505 | // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain | |
| 2506 | return try self.ptrAccessChain(result_ty_ref, base_ptr, rhs, &.{}); | |
| 2507 | } | |
| 2516 | fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 2517 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | |
| 2518 | const ptr_ty = self.air.typeOf(bin_op.lhs); | |
| 2519 | const ptr_id = try self.resolve(bin_op.lhs); | |
| 2520 | const index_id = try self.resolve(bin_op.rhs); | |
| 2521 | ||
| 2522 | const elem_ptr_id = try self.ptrElemPtr(ptr_ty, ptr_id, index_id); | |
| 2523 | ||
| 2524 | // If we have a pointer-to-array, construct an element pointer to use with load() | |
| 2525 | // If we pass ptr_ty directly, it will attempt to load the entire array rather than | |
| 2526 | // just an element. | |
| 2527 | var elem_ptr_info = ptr_ty.ptrInfo(); | |
| 2528 | elem_ptr_info.data.size = .One; | |
| 2529 | const elem_ptr_ty = Type.initPayload(&elem_ptr_info.base); | |
| 2530 | ||
| 2531 | return try self.load(elem_ptr_ty, elem_ptr_id); | |
| 2508 | 2532 | } |
| 2509 | 2533 | |
| 2510 | 2534 | fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
test/behavior/align.zig-2| ... | ... | @@ -215,8 +215,6 @@ test "alignment and size of structs with 128-bit fields" { |
| 215 | 215 | } |
| 216 | 216 | |
| 217 | 217 | test "@ptrCast preserves alignment of bigger source" { |
| 218 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 219 | ||
| 220 | 218 | var x: u32 align(16) = 1234; |
| 221 | 219 | const ptr = @ptrCast(*u8, &x); |
| 222 | 220 | try expect(@TypeOf(ptr) == *align(16) u8); |
test/behavior/call.zig-2| ... | ... | @@ -385,8 +385,6 @@ test "generic function with generic function parameter" { |
| 385 | 385 | } |
| 386 | 386 | |
| 387 | 387 | test "recursive inline call with comptime known argument" { |
| 388 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 389 | ||
| 390 | 388 | const S = struct { |
| 391 | 389 | inline fn foo(x: i32) i32 { |
| 392 | 390 | if (x <= 0) { |
test/behavior/cast.zig-1| ... | ... | @@ -322,7 +322,6 @@ test "peer result null and comptime_int" { |
| 322 | 322 | test "*const ?[*]const T to [*c]const [*c]const T" { |
| 323 | 323 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 324 | 324 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 325 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 326 | 325 | |
| 327 | 326 | var array = [_]u8{ 'o', 'k' }; |
| 328 | 327 | const opt_array_ptr: ?[*]const u8 = &array; |
test/behavior/error.zig-1| ... | ... | @@ -22,7 +22,6 @@ test "error values" { |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | test "redefinition of error values allowed" { |
| 25 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 26 | 25 | shouldBeNotEqual(error.AnError, error.SecondError); |
| 27 | 26 | } |
| 28 | 27 | fn shouldBeNotEqual(a: anyerror, b: anyerror) void { |
test/behavior/eval.zig-2| ... | ... | @@ -47,8 +47,6 @@ test "inline variable gets result of const if" { |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | test "static function evaluation" { |
| 50 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 51 | ||
| 52 | 50 | try expect(statically_added_number == 3); |
| 53 | 51 | } |
| 54 | 52 | const statically_added_number = staticAdd(1, 2); |
test/behavior/floatop.zig-1| ... | ... | @@ -620,7 +620,6 @@ test "@floor" { |
| 620 | 620 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 621 | 621 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 622 | 622 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 623 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 624 | 623 | |
| 625 | 624 | comptime try testFloor(); |
| 626 | 625 | try testFloor(); |
test/behavior/fn.zig-2| ... | ... | @@ -12,8 +12,6 @@ fn testParamsAdd(a: i32, b: i32) i32 { |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | 14 | test "local variables" { |
| 15 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 16 | ||
| 17 | 15 | testLocVars(2); |
| 18 | 16 | } |
| 19 | 17 | fn testLocVars(b: i32) void { |
test/behavior/for.zig-2| ... | ... | @@ -39,8 +39,6 @@ fn testBreakOuter() !void { |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 41 | test "continue outer for loop" { |
| 42 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 43 | ||
| 44 | 42 | try testContinueOuter(); |
| 45 | 43 | comptime try testContinueOuter(); |
| 46 | 44 | } |
test/behavior/generics.zig-1| ... | ... | @@ -19,7 +19,6 @@ fn checkSize(comptime T: type) usize { |
| 19 | 19 | test "simple generic fn" { |
| 20 | 20 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 21 | 21 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 22 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 23 | 22 | |
| 24 | 23 | try expect(max(i32, 3, -1) == 3); |
| 25 | 24 | try expect(max(u8, 1, 100) == 100); |
test/behavior/optional.zig-1| ... | ... | @@ -421,7 +421,6 @@ test "optional of noreturn used with orelse" { |
| 421 | 421 | } |
| 422 | 422 | |
| 423 | 423 | test "orelse on C pointer" { |
| 424 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 425 | 424 | |
| 426 | 425 | // TODO https://github.com/ziglang/zig/issues/6597 |
| 427 | 426 | const foo: [*c]const u8 = "hey"; |
test/behavior/packed-struct.zig-1| ... | ... | @@ -93,7 +93,6 @@ test "flags in packed structs" { |
| 93 | 93 | |
| 94 | 94 | test "consistent size of packed structs" { |
| 95 | 95 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 96 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 97 | 96 | |
| 98 | 97 | const TxData1 = packed struct { data: u8, _23: u23, full: bool = false }; |
| 99 | 98 | const TxData2 = packed struct { data: u9, _22: u22, full: bool = false }; |
test/behavior/pointers.zig-2| ... | ... | @@ -19,7 +19,6 @@ fn testDerefPtr() !void { |
| 19 | 19 | test "pointer arithmetic" { |
| 20 | 20 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 21 | 21 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 22 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 23 | 22 | |
| 24 | 23 | var ptr: [*]const u8 = "abcd"; |
| 25 | 24 | |
| ... | ... | @@ -300,7 +299,6 @@ test "null terminated pointer" { |
| 300 | 299 | test "allow any sentinel" { |
| 301 | 300 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 302 | 301 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 303 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 304 | 302 | |
| 305 | 303 | const S = struct { |
| 306 | 304 | fn doTheTest() !void { |
test/behavior/sizeof_and_typeof.zig-1| ... | ... | @@ -154,7 +154,6 @@ test "@TypeOf() has no runtime side effects" { |
| 154 | 154 | |
| 155 | 155 | test "branching logic inside @TypeOf" { |
| 156 | 156 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 157 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 158 | 157 | |
| 159 | 158 | const S = struct { |
| 160 | 159 | var data: i32 = 0; |
test/behavior/slice.zig-1| ... | ... | @@ -672,7 +672,6 @@ test "array mult of slice gives ptr to array" { |
| 672 | 672 | |
| 673 | 673 | test "slice bounds in comptime concatenation" { |
| 674 | 674 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 675 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 676 | 675 | |
| 677 | 676 | const bs = comptime blk: { |
| 678 | 677 | const b = "........1........"; |
test/behavior/struct.zig-2| ... | ... | @@ -121,8 +121,6 @@ test "struct byval assign" { |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | 123 | test "call struct static method" { |
| 124 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 125 | ||
| 126 | 124 | const result = StructWithNoFields.add(3, 4); |
| 127 | 125 | try expect(result == 7); |
| 128 | 126 | } |
test/behavior/switch.zig-2| ... | ... | @@ -348,8 +348,6 @@ fn returnsFalse() bool { |
| 348 | 348 | } |
| 349 | 349 | } |
| 350 | 350 | test "switch on const enum with var" { |
| 351 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 352 | ||
| 353 | 351 | try expect(!returnsFalse()); |
| 354 | 352 | } |
| 355 | 353 |
test/behavior/threadlocal.zig-1| ... | ... | @@ -46,7 +46,6 @@ test "reference a global threadlocal variable" { |
| 46 | 46 | else => return error.SkipZigTest, |
| 47 | 47 | }; // TODO |
| 48 | 48 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 49 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 50 | 49 | |
| 51 | 50 | _ = nrfx_uart_rx(&g_uart0); |
| 52 | 51 | } |
test/behavior/type_info.zig-1| ... | ... | @@ -512,7 +512,6 @@ test "type info for async frames" { |
| 512 | 512 | |
| 513 | 513 | test "Declarations are returned in declaration order" { |
| 514 | 514 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 515 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 516 | 515 | |
| 517 | 516 | const S = struct { |
| 518 | 517 | const a = 1; |
test/behavior/var_args.zig-1| ... | ... | @@ -30,7 +30,6 @@ test "send void arg to var args" { |
| 30 | 30 | test "pass args directly" { |
| 31 | 31 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 32 | 32 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 33 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 34 | 33 | |
| 35 | 34 | try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10); |
| 36 | 35 | try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234); |
test/behavior/while.zig-2| ... | ... | @@ -38,8 +38,6 @@ fn staticWhileLoop2() i32 { |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | test "while with continue expression" { |
| 41 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 42 | ||
| 43 | 41 | var sum: i32 = 0; |
| 44 | 42 | { |
| 45 | 43 | var i: i32 = 0; |