| ... | ... | @@ -1157,22 +1157,24 @@ fn isByRef(ty: Type, target: std.Target) bool { |
| 1157 | 1157 | /// local value to store the pointer. This allows for local re-use and improves binary size. |
| 1158 | 1158 | fn buildPointerOffset(self: *Self, ptr_value: WValue, offset: u64, action: enum { modify, new }) InnerError!WValue { |
| 1159 | 1159 | // do not perform arithmetic when offset is 0. |
| 1160 | | if (offset == 0 and ptr_value.offset() == 0) return ptr_value; |
| 1160 | if (offset == 0 and ptr_value.offset() == 0 and action == .modify) return ptr_value; |
| 1161 | 1161 | const result_ptr: WValue = switch (action) { |
| 1162 | 1162 | .new => try self.allocLocal(Type.usize), |
| 1163 | 1163 | .modify => ptr_value, |
| 1164 | 1164 | }; |
| 1165 | 1165 | try self.emitWValue(ptr_value); |
| 1166 | | switch (self.arch()) { |
| 1167 | | .wasm32 => { |
| 1168 | | try self.addImm32(@bitCast(i32, @intCast(u32, offset + ptr_value.offset()))); |
| 1169 | | try self.addTag(.i32_add); |
| 1170 | | }, |
| 1171 | | .wasm64 => { |
| 1172 | | try self.addImm64(offset + ptr_value.offset()); |
| 1173 | | try self.addTag(.i64_add); |
| 1174 | | }, |
| 1175 | | else => unreachable, |
| 1166 | if (offset + ptr_value.offset() > 0) { |
| 1167 | switch (self.arch()) { |
| 1168 | .wasm32 => { |
| 1169 | try self.addImm32(@bitCast(i32, @intCast(u32, offset + ptr_value.offset()))); |
| 1170 | try self.addTag(.i32_add); |
| 1171 | }, |
| 1172 | .wasm64 => { |
| 1173 | try self.addImm64(offset + ptr_value.offset()); |
| 1174 | try self.addTag(.i64_add); |
| 1175 | }, |
| 1176 | else => unreachable, |
| 1177 | } |
| 1176 | 1178 | } |
| 1177 | 1179 | try self.addLabel(.local_set, result_ptr.local); |
| 1178 | 1180 | return result_ptr; |
| ... | ... | @@ -1267,6 +1269,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1267 | 1269 | .struct_field_ptr_index_2 => self.airStructFieldPtrIndex(inst, 2), |
| 1268 | 1270 | .struct_field_ptr_index_3 => self.airStructFieldPtrIndex(inst, 3), |
| 1269 | 1271 | .struct_field_val => self.airStructFieldVal(inst), |
| 1272 | .field_parent_ptr => self.airFieldParentPtr(inst), |
| 1270 | 1273 | |
| 1271 | 1274 | .switch_br => self.airSwitchBr(inst), |
| 1272 | 1275 | .trunc => self.airTrunc(inst), |
| ... | ... | @@ -1334,7 +1337,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1334 | 1337 | .atomic_rmw, |
| 1335 | 1338 | .tag_name, |
| 1336 | 1339 | .error_name, |
| 1337 | | .field_parent_ptr, |
| 1338 | 1340 | .mul_add, |
| 1339 | 1341 | |
| 1340 | 1342 | // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248 |
| ... | ... | @@ -3252,3 +3254,25 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue |
| 3252 | 3254 | |
| 3253 | 3255 | return self.buildPointerOffset(operand, @intCast(u32, offset), .new); |
| 3254 | 3256 | } |
| 3257 | |
| 3258 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3259 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 3260 | |
| 3261 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3262 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 3263 | const field_ptr = try self.resolveInst(extra.field_ptr); |
| 3264 | |
| 3265 | const struct_ty = self.air.getRefType(ty_pl.ty).childType(); |
| 3266 | const field_offset = struct_ty.structFieldOffset(extra.field_index, self.target); |
| 3267 | |
| 3268 | if (field_offset == 0) { |
| 3269 | return field_ptr; |
| 3270 | } |
| 3271 | |
| 3272 | const base = try self.buildPointerOffset(field_ptr, 0, .new); |
| 3273 | try self.addLabel(.local_get, base.local); |
| 3274 | try self.addImm32(@bitCast(i32, @intCast(u32, field_offset))); |
| 3275 | try self.addTag(.i32_sub); |
| 3276 | try self.addLabel(.local_set, base.local); |
| 3277 | return base; |
| 3278 | } |