authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-03-08 22:13:47+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-09 13:53:10-07:00
log3ea113e00887638bf8bfb1d00bae5649db7ded35
treeb9dfe76c4cc10121d099ac32e3aab6a6762a48fa
parentf931c0638da6b0935de31044be93c8ab1387e04e

wasm: Implement `field_parent_ptr`


1 files changed, 36 insertions(+), 12 deletions(-)

src/arch/wasm/CodeGen.zig+36-12
...@@ -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.
1158fn buildPointerOffset(self: *Self, ptr_value: WValue, offset: u64, action: enum { modify, new }) InnerError!WValue {1158fn 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),
12701273
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,
13391341
1340 // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/102481342 // 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
32523254
3253 return self.buildPointerOffset(operand, @intCast(u32, offset), .new);3255 return self.buildPointerOffset(operand, @intCast(u32, offset), .new);
3254}3256}
3257
3258fn 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}