| ... | @@ -1065,6 +1065,7 @@ const NavGen = struct { | ... | @@ -1065,6 +1065,7 @@ const NavGen = struct { |
| 1065 | | 1065 | |
| 1066 | fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef { | 1066 | fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef { |
| 1067 | const pt = self.pt; | 1067 | const pt = self.pt; |
| | 1068 | const zcu = pt.zcu; |
| 1068 | switch (derivation) { | 1069 | switch (derivation) { |
| 1069 | .comptime_alloc_ptr, .comptime_field_ptr => unreachable, | 1070 | .comptime_alloc_ptr, .comptime_field_ptr => unreachable, |
| 1070 | .int => |int| { | 1071 | .int => |int| { |
| ... | @@ -1104,23 +1105,36 @@ const NavGen = struct { | ... | @@ -1104,23 +1105,36 @@ const NavGen = struct { |
| 1104 | .offset_and_cast => |oac| { | 1105 | .offset_and_cast => |oac| { |
| 1105 | const parent_ptr_id = try self.derivePtr(oac.parent.*); | 1106 | const parent_ptr_id = try self.derivePtr(oac.parent.*); |
| 1106 | const parent_ptr_ty = try oac.parent.ptrType(pt); | 1107 | const parent_ptr_ty = try oac.parent.ptrType(pt); |
| 1107 | disallow: { | 1108 | const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct); |
| 1108 | if (oac.byte_offset != 0) break :disallow; | 1109 | |
| 1109 | // Allow changing the pointer type child only to restructure arrays. | 1110 | if (oac.byte_offset != 0) { |
| 1110 | // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T. | 1111 | const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu); |
| 1111 | const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct); | 1112 | if (oac.byte_offset % child_size != 0) { |
| 1112 | const result_ptr_id = self.spv.allocId(); | 1113 | return self.fail("cannot perform pointer cast: '{}' to '{}'", .{ |
| 1113 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | 1114 | parent_ptr_ty.fmt(pt), |
| 1114 | .id_result_type = result_ty_id, | 1115 | oac.new_ptr_ty.fmt(pt), |
| 1115 | .id_result = result_ptr_id, | 1116 | }); |
| 1116 | .operand = parent_ptr_id, | 1117 | } |
| 1117 | }); | 1118 | |
| 1118 | return result_ptr_id; | 1119 | // Vector element ptr accesses are derived as offset_and_cast. |
| | 1120 | // We can just use OpAccessChain. |
| | 1121 | assert(parent_ptr_ty.childType(zcu).zigTypeTag(zcu) == .vector); |
| | 1122 | return self.accessChain( |
| | 1123 | result_ty_id, |
| | 1124 | parent_ptr_id, |
| | 1125 | &.{@intCast(@divExact(oac.byte_offset, child_size))}, |
| | 1126 | ); |
| 1119 | } | 1127 | } |
| 1120 | return self.fail("cannot perform pointer cast: '{}' to '{}'", .{ | 1128 | |
| 1121 | parent_ptr_ty.fmt(pt), | 1129 | // Allow changing the pointer type child only to restructure arrays. |
| 1122 | oac.new_ptr_ty.fmt(pt), | 1130 | // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T. |
| | 1131 | const result_ptr_id = self.spv.allocId(); |
| | 1132 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| | 1133 | .id_result_type = result_ty_id, |
| | 1134 | .id_result = result_ptr_id, |
| | 1135 | .operand = parent_ptr_id, |
| 1123 | }); | 1136 | }); |
| | 1137 | return result_ptr_id; |
| 1124 | }, | 1138 | }, |
| 1125 | } | 1139 | } |
| 1126 | } | 1140 | } |