| author | |
| committer | |
| log | 47cd0961cb938248a2bc65d2a9d49ba1d37b0764 |
| tree | f5eba03c90218b3e4e15654085ec4466ca4a93d5 |
| parent | 58b38238f51b6a268559144e8bbe7c0646170488 |
Handle packed containers, also fixes packed union lowering for non int type + union field pointer logic fix2 files changed, 34 insertions(+), 35 deletions(-)
src/arch/wasm/CodeGen.zig+34-27| ... | @@ -3154,19 +3154,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro | ... | @@ -3154,19 +3154,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro |
| 3154 | .@"extern", .@"packed" => unreachable, | 3154 | .@"extern", .@"packed" => unreachable, |
| 3155 | }, | 3155 | }, |
| 3156 | .@"union" => switch (base_ty.containerLayout(zcu)) { | 3156 | .@"union" => switch (base_ty.containerLayout(zcu)) { |
| 3157 | .auto => off: { | 3157 | .auto => base_ty.structFieldOffset(@intCast(field.index), zcu), |
| 3158 | // Keep in sync with the `un` case of `generateSymbol`. | ||
| 3159 | const layout = base_ty.unionGetLayout(zcu); | ||
| 3160 | if (layout.payload_size == 0) break :off 0; | ||
| 3161 | if (layout.tag_size == 0) break :off 0; | ||
| 3162 | if (layout.tag_align.compare(.gte, layout.payload_align)) { | ||
| 3163 | // Tag first. | ||
| 3164 | break :off layout.tag_size; | ||
| 3165 | } else { | ||
| 3166 | // Payload first. | ||
| 3167 | break :off 0; | ||
| 3168 | } | ||
| 3169 | }, | ||
| 3170 | .@"extern", .@"packed" => unreachable, | 3158 | .@"extern", .@"packed" => unreachable, |
| 3171 | }, | 3159 | }, |
| 3172 | else => unreachable, | 3160 | else => unreachable, |
| ... | @@ -3312,16 +3300,16 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { | ... | @@ -3312,16 +3300,16 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3312 | }, | 3300 | }, |
| 3313 | else => unreachable, | 3301 | else => unreachable, |
| 3314 | }, | 3302 | }, |
| 3315 | .un => |un| { | 3303 | .un => { |
| 3316 | // in this case we have a packed union which will not be passed by reference. | 3304 | const int_type = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); |
| 3317 | const constant_ty = if (un.tag == .none) | 3305 | |
| 3318 | try ty.unionBackingType(pt) | 3306 | var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer |
| 3319 | else field_ty: { | 3307 | val.writeToPackedMemory(ty, pt, &buf, 0) catch unreachable; |
| 3320 | const union_obj = zcu.typeToUnion(ty).?; | 3308 | const int_val = try pt.intValue( |
| 3321 | const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; | 3309 | int_type, |
| 3322 | break :field_ty Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | 3310 | mem.readInt(u64, &buf, .little), |
| 3323 | }; | 3311 | ); |
| 3324 | return cg.lowerConstant(Value.fromInterned(un.val), constant_ty); | 3312 | return cg.lowerConstant(int_val, int_type); |
| 3325 | }, | 3313 | }, |
| 3326 | .memoized_call => unreachable, | 3314 | .memoized_call => unreachable, |
| 3327 | } | 3315 | } |
| ... | @@ -3369,6 +3357,14 @@ fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -3369,6 +3357,14 @@ fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue { |
| 3369 | const packed_struct = zcu.typeToPackedStruct(ty).?; | 3357 | const packed_struct = zcu.typeToPackedStruct(ty).?; |
| 3370 | return cg.emitUndefined(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip))); | 3358 | return cg.emitUndefined(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip))); |
| 3371 | }, | 3359 | }, |
| 3360 | .@"union" => switch (ty.containerLayout(zcu)) { | ||
| 3361 | .@"packed" => switch (ty.bitSize(zcu)) { | ||
| 3362 | 0...32 => return .{ .imm32 = 0xaaaaaaaa }, | ||
| 3363 | 33...64 => return .{ .imm64 = 0xaaaaaaaaaaaaaaaa }, | ||
| 3364 | else => unreachable, | ||
| 3365 | }, | ||
| 3366 | else => unreachable, | ||
| 3367 | }, | ||
| 3372 | else => return cg.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty.zigTypeTag(zcu)}), | 3368 | else => return cg.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty.zigTypeTag(zcu)}), |
| 3373 | } | 3369 | } |
| 3374 | } | 3370 | } |
| ... | @@ -4211,7 +4207,6 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) | ... | @@ -4211,7 +4207,6 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) |
| 4211 | assert(isByRef(eu_ty, zcu, cg.target)); | 4207 | assert(isByRef(eu_ty, zcu, cg.target)); |
| 4212 | break :result try cg.load(operand, payload_ty, pl_offset); | 4208 | break :result try cg.load(operand, payload_ty, pl_offset); |
| 4213 | } | 4209 | } |
| 4214 | |||
| 4215 | }; | 4210 | }; |
| 4216 | return cg.finishAir(inst, result, &.{ty_op.operand}); | 4211 | return cg.finishAir(inst, result, &.{ty_op.operand}); |
| 4217 | } | 4212 | } |
| ... | @@ -5691,13 +5686,25 @@ fn airErrUnionPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void | ... | @@ -5691,13 +5686,25 @@ fn airErrUnionPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void |
| 5691 | } | 5686 | } |
| 5692 | 5687 | ||
| 5693 | fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5688 | fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5694 | const zcu = cg.pt.zcu; | 5689 | const pt = cg.pt; |
| 5690 | const zcu = pt.zcu; | ||
| 5695 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 5691 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5696 | const extra = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 5692 | const extra = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 5697 | 5693 | ||
| 5698 | const field_ptr = try cg.resolveInst(extra.field_ptr); | 5694 | const field_ptr = try cg.resolveInst(extra.field_ptr); |
| 5699 | const parent_ty = ty_pl.ty.toType().childType(zcu); | 5695 | const parent_ptr_ty = cg.typeOfIndex(inst); |
| 5700 | const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu); | 5696 | const parent_ty = parent_ptr_ty.childType(zcu); |
| 5697 | const field_ptr_ty = cg.typeOf(extra.field_ptr); | ||
| 5698 | const field_index = extra.field_index; | ||
| 5699 | const field_offset = switch (parent_ty.containerLayout(zcu)) { | ||
| 5700 | .auto, .@"extern" => parent_ty.structFieldOffset(field_index, zcu), | ||
| 5701 | .@"packed" => offset: { | ||
| 5702 | const parent_ptr_offset = parent_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset; | ||
| 5703 | const field_offset = if (zcu.typeToStruct(parent_ty)) |loaded_struct| pt.structPackedFieldBitOffset(loaded_struct, field_index) else 0; | ||
| 5704 | const field_ptr_offset = field_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset; | ||
| 5705 | break :offset @divExact(parent_ptr_offset + field_offset - field_ptr_offset, 8); | ||
| 5706 | }, | ||
| 5707 | }; | ||
| 5701 | 5708 | ||
| 5702 | const result = if (field_offset != 0) result: { | 5709 | const result = if (field_offset != 0) result: { |
| 5703 | const base = try cg.buildPointerOffset(field_ptr, 0, .new); | 5710 | const base = try cg.buildPointerOffset(field_ptr, 0, .new); |
test/behavior/field_parent_ptr.zig-8| ... | @@ -588,7 +588,6 @@ test "@fieldParentPtr extern struct last zero-bit field" { | ... | @@ -588,7 +588,6 @@ test "@fieldParentPtr extern struct last zero-bit field" { |
| 588 | test "@fieldParentPtr unaligned packed struct" { | 588 | test "@fieldParentPtr unaligned packed struct" { |
| 589 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 589 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 590 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | 590 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 591 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 592 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 591 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 593 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 592 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 594 | 593 | ||
| ... | @@ -727,7 +726,6 @@ test "@fieldParentPtr unaligned packed struct" { | ... | @@ -727,7 +726,6 @@ test "@fieldParentPtr unaligned packed struct" { |
| 727 | test "@fieldParentPtr aligned packed struct" { | 726 | test "@fieldParentPtr aligned packed struct" { |
| 728 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 727 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 729 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | 728 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 730 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 731 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 729 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 732 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 730 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 733 | 731 | ||
| ... | @@ -865,7 +863,6 @@ test "@fieldParentPtr aligned packed struct" { | ... | @@ -865,7 +863,6 @@ test "@fieldParentPtr aligned packed struct" { |
| 865 | 863 | ||
| 866 | test "@fieldParentPtr nested packed struct" { | 864 | test "@fieldParentPtr nested packed struct" { |
| 867 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | 865 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 868 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 869 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 866 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 870 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 867 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 871 | 868 | ||
| ... | @@ -1028,7 +1025,6 @@ test "@fieldParentPtr nested packed struct" { | ... | @@ -1028,7 +1025,6 @@ test "@fieldParentPtr nested packed struct" { |
| 1028 | 1025 | ||
| 1029 | test "@fieldParentPtr packed struct first zero-bit field" { | 1026 | test "@fieldParentPtr packed struct first zero-bit field" { |
| 1030 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | 1027 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 1031 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 1032 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 1028 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1033 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 1029 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1034 | 1030 | ||
| ... | @@ -1134,7 +1130,6 @@ test "@fieldParentPtr packed struct first zero-bit field" { | ... | @@ -1134,7 +1130,6 @@ test "@fieldParentPtr packed struct first zero-bit field" { |
| 1134 | 1130 | ||
| 1135 | test "@fieldParentPtr packed struct middle zero-bit field" { | 1131 | test "@fieldParentPtr packed struct middle zero-bit field" { |
| 1136 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | 1132 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 1137 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 1138 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 1133 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1139 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 1134 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1140 | 1135 | ||
| ... | @@ -1240,7 +1235,6 @@ test "@fieldParentPtr packed struct middle zero-bit field" { | ... | @@ -1240,7 +1235,6 @@ test "@fieldParentPtr packed struct middle zero-bit field" { |
| 1240 | 1235 | ||
| 1241 | test "@fieldParentPtr packed struct last zero-bit field" { | 1236 | test "@fieldParentPtr packed struct last zero-bit field" { |
| 1242 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | 1237 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 1243 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 1244 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 1238 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1245 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 1239 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1246 | 1240 | ||
| ... | @@ -1753,7 +1747,6 @@ test "@fieldParentPtr extern union" { | ... | @@ -1753,7 +1747,6 @@ test "@fieldParentPtr extern union" { |
| 1753 | } | 1747 | } |
| 1754 | 1748 | ||
| 1755 | test "@fieldParentPtr packed union" { | 1749 | test "@fieldParentPtr packed union" { |
| 1756 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 1757 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 1750 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1758 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 1751 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1759 | if (builtin.target.cpu.arch.endian() == .big) return error.SkipZigTest; // TODO | 1752 | if (builtin.target.cpu.arch.endian() == .big) return error.SkipZigTest; // TODO |
| ... | @@ -1892,7 +1885,6 @@ test "@fieldParentPtr packed union" { | ... | @@ -1892,7 +1885,6 @@ test "@fieldParentPtr packed union" { |
| 1892 | 1885 | ||
| 1893 | test "@fieldParentPtr tagged union all zero-bit fields" { | 1886 | test "@fieldParentPtr tagged union all zero-bit fields" { |
| 1894 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | 1887 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 1895 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 1896 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 1888 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1897 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 1889 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1898 | 1890 |