| ... | @@ -1157,22 +1157,24 @@ fn isByRef(ty: Type, target: std.Target) bool { | ... | @@ -1157,22 +1157,24 @@ fn isByRef(ty: Type, target: std.Target) bool { |
| 1157 | /// local value to store the pointer. This allows for local re-use and improves binary size. | 1157 | /// local value to store the pointer. This allows for local re-use and improves binary size. |
| 1158 | fn buildPointerOffset(self: *Self, ptr_value: WValue, offset: u64, action: enum { modify, new }) InnerError!WValue { | 1158 | fn buildPointerOffset(self: *Self, ptr_value: WValue, offset: u64, action: enum { modify, new }) InnerError!WValue { |
| 1159 | // do not perform arithmetic when offset is 0. | 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 | const result_ptr: WValue = switch (action) { | 1161 | const result_ptr: WValue = switch (action) { |
| 1162 | .new => try self.allocLocal(Type.usize), | 1162 | .new => try self.allocLocal(Type.usize), |
| 1163 | .modify => ptr_value, | 1163 | .modify => ptr_value, |
| 1164 | }; | 1164 | }; |
| 1165 | try self.emitWValue(ptr_value); | 1165 | try self.emitWValue(ptr_value); |
| 1166 | switch (self.arch()) { | 1166 | if (offset + ptr_value.offset() > 0) { |
| 1167 | .wasm32 => { | 1167 | switch (self.arch()) { |
| 1168 | try self.addImm32(@bitCast(i32, @intCast(u32, offset + ptr_value.offset()))); | 1168 | .wasm32 => { |
| 1169 | try self.addTag(.i32_add); | 1169 | try self.addImm32(@bitCast(i32, @intCast(u32, offset + ptr_value.offset()))); |
| 1170 | }, | 1170 | try self.addTag(.i32_add); |
| 1171 | .wasm64 => { | 1171 | }, |
| 1172 | try self.addImm64(offset + ptr_value.offset()); | 1172 | .wasm64 => { |
| 1173 | try self.addTag(.i64_add); | 1173 | try self.addImm64(offset + ptr_value.offset()); |
| 1174 | }, | 1174 | try self.addTag(.i64_add); |
| 1175 | else => unreachable, | 1175 | }, |
| | 1176 | else => unreachable, |
| | 1177 | } |
| 1176 | } | 1178 | } |
| 1177 | try self.addLabel(.local_set, result_ptr.local); | 1179 | try self.addLabel(.local_set, result_ptr.local); |
| 1178 | return result_ptr; | 1180 | return result_ptr; |
| ... | @@ -1267,6 +1269,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1267,6 +1269,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1267 | .struct_field_ptr_index_2 => self.airStructFieldPtrIndex(inst, 2), | 1269 | .struct_field_ptr_index_2 => self.airStructFieldPtrIndex(inst, 2), |
| 1268 | .struct_field_ptr_index_3 => self.airStructFieldPtrIndex(inst, 3), | 1270 | .struct_field_ptr_index_3 => self.airStructFieldPtrIndex(inst, 3), |
| 1269 | .struct_field_val => self.airStructFieldVal(inst), | 1271 | .struct_field_val => self.airStructFieldVal(inst), |
| | 1272 | .field_parent_ptr => self.airFieldParentPtr(inst), |
| 1270 | | 1273 | |
| 1271 | .switch_br => self.airSwitchBr(inst), | 1274 | .switch_br => self.airSwitchBr(inst), |
| 1272 | .trunc => self.airTrunc(inst), | 1275 | .trunc => self.airTrunc(inst), |
| ... | @@ -1334,7 +1337,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1334,7 +1337,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1334 | .atomic_rmw, | 1337 | .atomic_rmw, |
| 1335 | .tag_name, | 1338 | .tag_name, |
| 1336 | .error_name, | 1339 | .error_name, |
| 1337 | .field_parent_ptr, | | |
| 1338 | .mul_add, | 1340 | .mul_add, |
| 1339 | | 1341 | |
| 1340 | // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248 | 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,3 +3254,25 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue |
| 3252 | | 3254 | |
| 3253 | return self.buildPointerOffset(operand, @intCast(u32, offset), .new); | 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 | } |