| ... | ... | @@ -625,6 +625,49 @@ pub fn layoutType(cg: *CodeGen, ty: Type, is_block_root: bool) Error!Id { |
| 625 | 625 | }); |
| 626 | 626 | break :id id; |
| 627 | 627 | }, |
| 628 | .@"union" => id: { |
| 629 | const union_obj = zcu.typeToUnion(ty).?; |
| 630 | if (union_obj.layout == .@"packed") return cg.resolveType(ty, .indirect); |
| 631 | |
| 632 | const layout = cg.unionLayout(ty); |
| 633 | if (!layout.has_payload) return cg.resolveType(ty, .indirect); |
| 634 | |
| 635 | const id = cg.allocId(); |
| 636 | if (is_block_root) try cg.decorate(id, .block); |
| 637 | |
| 638 | var member_types: [4]Id = undefined; |
| 639 | const u8_id = try cg.resolveType(.u8, .direct); |
| 640 | if (layout.tag_size != 0) { |
| 641 | const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); |
| 642 | try cg.decorateMember(id, layout.tag_index, .{ .offset = .{ |
| 643 | .byte_offset = @intCast(ty.unionGetLayout(zcu).tagOffset()), |
| 644 | } }); |
| 645 | member_types[layout.tag_index] = try cg.layoutType(tag_ty, false); |
| 646 | } |
| 647 | if (layout.payload_size != 0) { |
| 648 | try cg.decorateMember(id, layout.payload_index, .{ .offset = .{ |
| 649 | .byte_offset = @intCast(ty.unionGetLayout(zcu).payloadOffset()), |
| 650 | } }); |
| 651 | member_types[layout.payload_index] = try cg.layoutType(layout.payload_ty, false); |
| 652 | } |
| 653 | if (layout.payload_padding_size != 0) { |
| 654 | const len_id = try cg.constInt(.u32, layout.payload_padding_size); |
| 655 | const arr_id = try cg.arrayType(len_id, u8_id); |
| 656 | try cg.decorate(arr_id, .{ .array_stride = .{ .array_stride = 1 } }); |
| 657 | member_types[layout.payload_padding_index] = arr_id; |
| 658 | } |
| 659 | if (layout.padding_size != 0) { |
| 660 | const len_id = try cg.constInt(.u32, layout.padding_size); |
| 661 | const arr_id = try cg.arrayType(len_id, u8_id); |
| 662 | try cg.decorate(arr_id, .{ .array_stride = .{ .array_stride = 1 } }); |
| 663 | member_types[layout.padding_index] = arr_id; |
| 664 | } |
| 665 | try cg.sections.globals.emit(gpa, .OpTypeStruct, .{ |
| 666 | .id_result = id, |
| 667 | .id_ref = member_types[0..layout.total_fields], |
| 668 | }); |
| 669 | break :id id; |
| 670 | }, |
| 628 | 671 | .array => id: { |
| 629 | 672 | const elem_ty = ty.childType(zcu); |
| 630 | 673 | const elem_ty_id = try cg.layoutType(elem_ty, false); |
| ... | ... | @@ -1883,8 +1926,13 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { |
| 1883 | 1926 | |
| 1884 | 1927 | const nav_ty_id = try cg.resolveType(nav_ty, .indirect); |
| 1885 | 1928 | const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, storage_class); |
| 1886 | | if (nav_ty.zigTypeTag(zcu) == .@"struct" and cg.needsLayout(nav.resolved.?.@"addrspace", nav_ty)) { |
| 1887 | | try cg.block_var_ids.put(gpa, spv_decl.result_id, {}); |
| 1929 | switch (nav_ty.zigTypeTag(zcu)) { |
| 1930 | .@"struct", .@"union" => { |
| 1931 | if (cg.needsLayout(nav.resolved.?.@"addrspace", nav_ty)) { |
| 1932 | try cg.block_var_ids.put(gpa, spv_decl.result_id, {}); |
| 1933 | } |
| 1934 | }, |
| 1935 | else => {}, |
| 1888 | 1936 | } |
| 1889 | 1937 | if (decl_ptr_ty_id == ty_id) return spv_decl.result_id; |
| 1890 | 1938 | switch (target.os.tag) { |
| ... | ... | @@ -4175,7 +4223,7 @@ fn needsLayout(cg: *CodeGen, as: std.lang.AddressSpace, pointee_ty: Type) bool { |
| 4175 | 4223 | else => return false, |
| 4176 | 4224 | } |
| 4177 | 4225 | return switch (pointee_ty.zigTypeTag(cg.zcu)) { |
| 4178 | | .@"struct", .array => true, |
| 4226 | .@"struct", .@"union", .array => true, |
| 4179 | 4227 | .spirv => pointee_ty.isSpirvRuntimeArray(cg.zcu), |
| 4180 | 4228 | else => false, |
| 4181 | 4229 | }; |
| ... | ... | @@ -6905,6 +6953,16 @@ fn airAggFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6905 | 6953 | return try cg.load(field_ty, pl_ptr_id, .{}); |
| 6906 | 6954 | } |
| 6907 | 6955 | |
| 6956 | switch (zcu.getTarget().os.tag) { |
| 6957 | .vulkan, .opengl => { |
| 6958 | // Logical addressing forbids OpBitcast on pointers. Load the |
| 6959 | // payload as its type and bitcast the value instead. |
| 6960 | const payload_id = try cg.load(layout.payload_ty, pl_ptr_id, .{}); |
| 6961 | return try cg.bitCast(field_ty, layout.payload_ty, payload_id); |
| 6962 | }, |
| 6963 | else => {}, |
| 6964 | } |
| 6965 | |
| 6908 | 6966 | const field_ty_id = try cg.resolveType(field_ty, .indirect); |
| 6909 | 6967 | const active_pl_ptr_ty_id = try cg.ptrType(field_ty_id, .function); |
| 6910 | 6968 | const active_pl_ptr_id = cg.allocId(); |
| ... | ... | @@ -7023,6 +7081,17 @@ fn structFieldPtr( |
| 7023 | 7081 | return try cg.accessChain(result_ty_id, object_ptr, &.{layout.payload_index}); |
| 7024 | 7082 | } |
| 7025 | 7083 | |
| 7084 | switch (zcu.getTarget().os.tag) { |
| 7085 | .vulkan, .opengl => { |
| 7086 | // Logical addressing forbids OpBitcast on pointers. If the field |
| 7087 | // type is structurally identical to the payload type (dedup will |
| 7088 | // unify them) the access chain typed as the field type is valid. |
| 7089 | if (object_ty.containerLayout(zcu) == .@"packed") return object_ptr; |
| 7090 | return try cg.accessChain(result_ty_id, object_ptr, &.{layout.payload_index}); |
| 7091 | }, |
| 7092 | else => {}, |
| 7093 | } |
| 7094 | |
| 7026 | 7095 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); |
| 7027 | 7096 | const pl_ptr_ty_id = try cg.ptrType(layout_payload_ty_id, storage_class); |
| 7028 | 7097 | const pl_ptr_id = blk: { |