authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-05-18 18:55:15+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-05-20 17:30:21+02:00
log6c055570720197af242b4c5538dd784d2e3a58f7
treef85e0efa0d9c488172c301542b528a89cf1a3797
parent0ba0d8fecb255cf19a225e4cb160921d73f83652
signaturelock-open Commit is signed but in an unrecognized format.

spirv: fix some (Ptr)AccessChain uses

The first dereference of PtrAccessChain returns a pointer of the same type as the base pointer, in contrast to AccessChain, where the first dereference returns a pointer of the dereferenced type of the base pointer.

1 files changed, 56 insertions(+), 50 deletions(-)

src/codegen/spirv.zig+56-50
...@@ -457,14 +457,8 @@ pub const DeclGen = struct {...@@ -457,14 +457,8 @@ pub const DeclGen = struct {
457 const members = spv_composite_ty.payload(.@"struct").members;457 const members = spv_composite_ty.payload(.@"struct").members;
458 for (constituents, members, 0..) |constitent_id, member, index| {458 for (constituents, members, 0..) |constitent_id, member, index| {
459 const index_id = try self.constInt(index_ty_ref, index);459 const index_id = try self.constInt(index_ty_ref, index);
460 const ptr_id = self.spv.allocId();
461 const ptr_member_ty_ref = try self.spv.ptrType(member.ty, .Generic, 0);460 const ptr_member_ty_ref = try self.spv.ptrType(member.ty, .Generic, 0);
462 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{461 const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{index_id});
463 .id_result_type = self.typeId(ptr_member_ty_ref),
464 .id_result = ptr_id,
465 .base = ptr_composite_id,
466 .indexes = &.{index_id},
467 });
468 try self.func.body.emit(self.spv.gpa, .OpStore, .{462 try self.func.body.emit(self.spv.gpa, .OpStore, .{
469 .pointer = ptr_id,463 .pointer = ptr_id,
470 .object = constitent_id,464 .object = constitent_id,
...@@ -2089,6 +2083,44 @@ pub const DeclGen = struct {...@@ -2089,6 +2083,44 @@ pub const DeclGen = struct {
2089 return result_id;2083 return result_id;
2090 }2084 }
20912085
2086 /// AccessChain is essentially PtrAccessChain with 0 as initial argument. The effective
2087 /// difference lies in whether the resulting type of the first dereference will be the
2088 /// same as that of the base pointer, or that of a dereferenced base pointer. AccessChain
2089 /// is the latter and PtrAccessChain is the former.
2090 fn accessChain(
2091 self: *DeclGen,
2092 result_ty_ref: SpvType.Ref,
2093 base: IdRef,
2094 indexes: []const IdRef,
2095 ) !IdRef {
2096 const result_id = self.spv.allocId();
2097 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
2098 .id_result_type = self.typeId(result_ty_ref),
2099 .id_result = result_id,
2100 .base = base,
2101 .indexes = indexes,
2102 });
2103 return result_id;
2104 }
2105
2106 fn ptrAccessChain(
2107 self: *DeclGen,
2108 result_ty_ref: SpvType.Ref,
2109 base: IdRef,
2110 element: IdRef,
2111 indexes: []const IdRef,
2112 ) !IdRef {
2113 const result_id = self.spv.allocId();
2114 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
2115 .id_result_type = self.typeId(result_ty_ref),
2116 .id_result = result_id,
2117 .base = base,
2118 .element = element,
2119 .indexes = indexes,
2120 });
2121 return result_id;
2122 }
2123
2092 fn cmp(2124 fn cmp(
2093 self: *DeclGen,2125 self: *DeclGen,
2094 comptime op: std.math.CompareOperator,2126 comptime op: std.math.CompareOperator,
...@@ -2353,12 +2385,12 @@ pub const DeclGen = struct {...@@ -2353,12 +2385,12 @@ pub const DeclGen = struct {
2353 const slice = try self.resolve(bin_op.lhs);2385 const slice = try self.resolve(bin_op.lhs);
2354 const index = try self.resolve(bin_op.rhs);2386 const index = try self.resolve(bin_op.rhs);
23552387
2356 const spv_ptr_ty = try self.resolveTypeId(self.air.typeOfIndex(inst));2388 const ptr_ty_ref = try self.resolveType(self.air.typeOfIndex(inst), .direct);
23572389
2358 const slice_ptr = blk: {2390 const slice_ptr = blk: {
2359 const result_id = self.spv.allocId();2391 const result_id = self.spv.allocId();
2360 try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{2392 try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{
2361 .id_result_type = spv_ptr_ty,2393 .id_result_type = self.typeId(ptr_ty_ref),
2362 .id_result = result_id,2394 .id_result = result_id,
2363 .composite = slice,2395 .composite = slice,
2364 .indexes = &.{0},2396 .indexes = &.{0},
...@@ -2366,14 +2398,7 @@ pub const DeclGen = struct {...@@ -2366,14 +2398,7 @@ pub const DeclGen = struct {
2366 break :blk result_id;2398 break :blk result_id;
2367 };2399 };
23682400
2369 const result_id = self.spv.allocId();2401 return try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index, &.{});
2370 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
2371 .id_result_type = spv_ptr_ty,
2372 .id_result = result_id,
2373 .base = slice_ptr,
2374 .element = index,
2375 });
2376 return result_id;
2377 }2402 }
23782403
2379 fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2404 fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -2385,12 +2410,12 @@ pub const DeclGen = struct {...@@ -2385,12 +2410,12 @@ pub const DeclGen = struct {
2385 const index = try self.resolve(bin_op.rhs);2410 const index = try self.resolve(bin_op.rhs);
23862411
2387 var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;2412 var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;
2388 const ptr_ty_id = try self.resolveTypeId(slice_ty.slicePtrFieldType(&slice_buf));2413 const ptr_ty_ref = try self.resolveType(slice_ty.slicePtrFieldType(&slice_buf), .direct);
23892414
2390 const slice_ptr = blk: {2415 const slice_ptr = blk: {
2391 const result_id = self.spv.allocId();2416 const result_id = self.spv.allocId();
2392 try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{2417 try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{
2393 .id_result_type = ptr_ty_id,2418 .id_result_type = self.typeId(ptr_ty_ref),
2394 .id_result = result_id,2419 .id_result = result_id,
2395 .composite = slice,2420 .composite = slice,
2396 .indexes = &.{0},2421 .indexes = &.{0},
...@@ -2398,17 +2423,7 @@ pub const DeclGen = struct {...@@ -2398,17 +2423,7 @@ pub const DeclGen = struct {
2398 break :blk result_id;2423 break :blk result_id;
2399 };2424 };
24002425
2401 const elem_ptr = blk: {2426 const elem_ptr = try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index, &.{});
2402 const result_id = self.spv.allocId();
2403 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
2404 .id_result_type = ptr_ty_id,
2405 .id_result = result_id,
2406 .base = slice_ptr,
2407 .element = index,
2408 });
2409 break :blk result_id;
2410 };
2411
2412 return try self.load(slice_ty, elem_ptr);2427 return try self.load(slice_ty, elem_ptr);
2413 }2428 }
24142429
...@@ -2423,19 +2438,18 @@ pub const DeclGen = struct {...@@ -2423,19 +2438,18 @@ pub const DeclGen = struct {
2423 // TODO: Make this return a null ptr or something2438 // TODO: Make this return a null ptr or something
2424 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null;2439 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null;
24252440
2426 const result_type_id = try self.resolveTypeId(result_ty);2441 const result_ty_ref = try self.resolveType(result_ty, .direct);
2427 const base_ptr = try self.resolve(bin_op.lhs);2442 const base_ptr = try self.resolve(bin_op.lhs);
2428 const rhs = try self.resolve(bin_op.rhs);2443 const rhs = try self.resolve(bin_op.rhs);
24292444
2430 const result_id = self.spv.allocId();2445 if (ptr_ty.isSinglePointer()) {
2431 const indexes = [_]IdRef{rhs};2446 // Pointer-to-array. In this case, the resulting pointer is not of the same type
2432 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{2447 // as the ptr_ty, and hence we need to use accessChain.
2433 .id_result_type = result_type_id,2448 return try self.accessChain(result_ty_ref, base_ptr, &.{rhs});
2434 .id_result = result_id,2449 } else {
2435 .base = base_ptr,2450 // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain
2436 .indexes = &indexes,2451 return try self.ptrAccessChain(result_ty_ref, base_ptr, rhs, &.{});
2437 });2452 }
2438 return result_id;
2439 }2453 }
24402454
2441 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2455 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -2480,16 +2494,8 @@ pub const DeclGen = struct {...@@ -2480,16 +2494,8 @@ pub const DeclGen = struct {
2480 const u32_ty_id = self.typeId(try self.intType(.unsigned, 32));2494 const u32_ty_id = self.typeId(try self.intType(.unsigned, 32));
2481 const field_index_id = self.spv.allocId();2495 const field_index_id = self.spv.allocId();
2482 try self.spv.emitConstant(u32_ty_id, field_index_id, .{ .uint32 = field_index });2496 try self.spv.emitConstant(u32_ty_id, field_index_id, .{ .uint32 = field_index });
2483 const result_id = self.spv.allocId();2497 const result_ty_ref = try self.resolveType(result_ptr_ty, .direct);
2484 const result_type_id = try self.resolveTypeId(result_ptr_ty);2498 return try self.accessChain(result_ty_ref, object_ptr, &.{field_index_id});
2485 const indexes = [_]IdRef{field_index_id};
2486 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
2487 .id_result_type = result_type_id,
2488 .id_result = result_id,
2489 .base = object_ptr,
2490 .indexes = &indexes,
2491 });
2492 return result_id;
2493 },2499 },
2494 },2500 },
2495 else => unreachable, // TODO2501 else => unreachable, // TODO