| ... | ... | @@ -1065,6 +1065,7 @@ const NavGen = struct { |
| 1065 | 1065 | |
| 1066 | 1066 | fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef { |
| 1067 | 1067 | const pt = self.pt; |
| 1068 | const zcu = pt.zcu; |
| 1068 | 1069 | switch (derivation) { |
| 1069 | 1070 | .comptime_alloc_ptr, .comptime_field_ptr => unreachable, |
| 1070 | 1071 | .int => |int| { |
| ... | ... | @@ -1104,23 +1105,36 @@ const NavGen = struct { |
| 1104 | 1105 | .offset_and_cast => |oac| { |
| 1105 | 1106 | const parent_ptr_id = try self.derivePtr(oac.parent.*); |
| 1106 | 1107 | const parent_ptr_ty = try oac.parent.ptrType(pt); |
| 1107 | | disallow: { |
| 1108 | | if (oac.byte_offset != 0) break :disallow; |
| 1109 | | // Allow changing the pointer type child only to restructure arrays. |
| 1110 | | // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T. |
| 1111 | | const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct); |
| 1112 | | const result_ptr_id = self.spv.allocId(); |
| 1113 | | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 1114 | | .id_result_type = result_ty_id, |
| 1115 | | .id_result = result_ptr_id, |
| 1116 | | .operand = parent_ptr_id, |
| 1117 | | }); |
| 1118 | | return result_ptr_id; |
| 1108 | const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct); |
| 1109 | |
| 1110 | if (oac.byte_offset != 0) { |
| 1111 | const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu); |
| 1112 | if (oac.byte_offset % child_size != 0) { |
| 1113 | return self.fail("cannot perform pointer cast: '{}' to '{}'", .{ |
| 1114 | parent_ptr_ty.fmt(pt), |
| 1115 | oac.new_ptr_ty.fmt(pt), |
| 1116 | }); |
| 1117 | } |
| 1118 | |
| 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 '{}'", .{ |
| 1121 | | parent_ptr_ty.fmt(pt), |
| 1122 | | oac.new_ptr_ty.fmt(pt), |
| 1128 | |
| 1129 | // Allow changing the pointer type child only to restructure arrays. |
| 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 | } |