| ... | ... | @@ -3789,10 +3789,7 @@ pub const DeclGen = struct { |
| 3789 | 3789 | |
| 3790 | 3790 | fn lowerIntAsPtr(dg: *DeclGen, val: Value) Error!*llvm.Value { |
| 3791 | 3791 | switch (dg.module.intern_pool.indexToKey(val.toIntern())) { |
| 3792 | | .undef => { |
| 3793 | | const llvm_usize = try dg.lowerType(Type.usize); |
| 3794 | | return llvm_usize.getUndef(); |
| 3795 | | }, |
| 3792 | .undef => return dg.context.pointerType(0).getUndef(), |
| 3796 | 3793 | .int => { |
| 3797 | 3794 | var bigint_space: Value.BigIntSpace = undefined; |
| 3798 | 3795 | const bigint = val.toBigInt(&bigint_space, dg.module); |
| ... | ... | @@ -3847,141 +3844,137 @@ pub const DeclGen = struct { |
| 3847 | 3844 | fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { |
| 3848 | 3845 | const mod = dg.module; |
| 3849 | 3846 | const target = mod.getTarget(); |
| 3850 | | return switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) { |
| 3851 | | .int => dg.lowerIntAsPtr(ptr_val), |
| 3852 | | .ptr => |ptr| switch (ptr.addr) { |
| 3853 | | .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl), |
| 3854 | | .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl), |
| 3855 | | .int => |int| dg.lowerIntAsPtr(int.toValue()), |
| 3856 | | .eu_payload => |eu_ptr| { |
| 3857 | | const parent_llvm_ptr = try dg.lowerParentPtr(eu_ptr.toValue(), true); |
| 3858 | | |
| 3859 | | const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod); |
| 3860 | | const payload_ty = eu_ty.errorUnionPayload(mod); |
| 3861 | | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3862 | | // In this case, we represent pointer to error union the same as pointer |
| 3863 | | // to the payload. |
| 3864 | | return parent_llvm_ptr; |
| 3865 | | } |
| 3847 | return switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { |
| 3848 | .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl), |
| 3849 | .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl), |
| 3850 | .int => |int| dg.lowerIntAsPtr(int.toValue()), |
| 3851 | .eu_payload => |eu_ptr| { |
| 3852 | const parent_llvm_ptr = try dg.lowerParentPtr(eu_ptr.toValue(), true); |
| 3853 | |
| 3854 | const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod); |
| 3855 | const payload_ty = eu_ty.errorUnionPayload(mod); |
| 3856 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3857 | // In this case, we represent pointer to error union the same as pointer |
| 3858 | // to the payload. |
| 3859 | return parent_llvm_ptr; |
| 3860 | } |
| 3866 | 3861 | |
| 3867 | | const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1; |
| 3868 | | const llvm_u32 = dg.context.intType(32); |
| 3869 | | const indices: [2]*llvm.Value = .{ |
| 3870 | | llvm_u32.constInt(0, .False), |
| 3871 | | llvm_u32.constInt(payload_offset, .False), |
| 3872 | | }; |
| 3873 | | const eu_llvm_ty = try dg.lowerType(eu_ty); |
| 3874 | | return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3875 | | }, |
| 3876 | | .opt_payload => |opt_ptr| { |
| 3877 | | const parent_llvm_ptr = try dg.lowerParentPtr(opt_ptr.toValue(), true); |
| 3862 | const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1; |
| 3863 | const llvm_u32 = dg.context.intType(32); |
| 3864 | const indices: [2]*llvm.Value = .{ |
| 3865 | llvm_u32.constInt(0, .False), |
| 3866 | llvm_u32.constInt(payload_offset, .False), |
| 3867 | }; |
| 3868 | const eu_llvm_ty = try dg.lowerType(eu_ty); |
| 3869 | return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3870 | }, |
| 3871 | .opt_payload => |opt_ptr| { |
| 3872 | const parent_llvm_ptr = try dg.lowerParentPtr(opt_ptr.toValue(), true); |
| 3878 | 3873 | |
| 3879 | | const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod); |
| 3880 | | const payload_ty = opt_ty.optionalChild(mod); |
| 3881 | | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or |
| 3882 | | payload_ty.optionalReprIsPayload(mod)) |
| 3883 | | { |
| 3884 | | // In this case, we represent pointer to optional the same as pointer |
| 3885 | | // to the payload. |
| 3886 | | return parent_llvm_ptr; |
| 3887 | | } |
| 3874 | const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod); |
| 3875 | const payload_ty = opt_ty.optionalChild(mod); |
| 3876 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or |
| 3877 | payload_ty.optionalReprIsPayload(mod)) |
| 3878 | { |
| 3879 | // In this case, we represent pointer to optional the same as pointer |
| 3880 | // to the payload. |
| 3881 | return parent_llvm_ptr; |
| 3882 | } |
| 3888 | 3883 | |
| 3889 | | const llvm_u32 = dg.context.intType(32); |
| 3890 | | const indices: [2]*llvm.Value = .{ |
| 3891 | | llvm_u32.constInt(0, .False), |
| 3892 | | llvm_u32.constInt(0, .False), |
| 3893 | | }; |
| 3894 | | const opt_llvm_ty = try dg.lowerType(opt_ty); |
| 3895 | | return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3896 | | }, |
| 3897 | | .comptime_field => unreachable, |
| 3898 | | .elem => |elem_ptr| { |
| 3899 | | const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.base.toValue(), true); |
| 3884 | const llvm_u32 = dg.context.intType(32); |
| 3885 | const indices: [2]*llvm.Value = .{ |
| 3886 | llvm_u32.constInt(0, .False), |
| 3887 | llvm_u32.constInt(0, .False), |
| 3888 | }; |
| 3889 | const opt_llvm_ty = try dg.lowerType(opt_ty); |
| 3890 | return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3891 | }, |
| 3892 | .comptime_field => unreachable, |
| 3893 | .elem => |elem_ptr| { |
| 3894 | const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.base.toValue(), true); |
| 3900 | 3895 | |
| 3901 | | const llvm_usize = try dg.lowerType(Type.usize); |
| 3902 | | const indices: [1]*llvm.Value = .{ |
| 3903 | | llvm_usize.constInt(elem_ptr.index, .False), |
| 3904 | | }; |
| 3905 | | const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod); |
| 3906 | | const elem_llvm_ty = try dg.lowerType(elem_ty); |
| 3907 | | return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3908 | | }, |
| 3909 | | .field => |field_ptr| { |
| 3910 | | const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.base.toValue(), byte_aligned); |
| 3911 | | const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); |
| 3912 | | |
| 3913 | | const field_index = @intCast(u32, field_ptr.index); |
| 3914 | | const llvm_u32 = dg.context.intType(32); |
| 3915 | | switch (parent_ty.zigTypeTag(mod)) { |
| 3916 | | .Union => { |
| 3917 | | if (parent_ty.containerLayout(mod) == .Packed) { |
| 3918 | | return parent_llvm_ptr; |
| 3919 | | } |
| 3896 | const llvm_usize = try dg.lowerType(Type.usize); |
| 3897 | const indices: [1]*llvm.Value = .{ |
| 3898 | llvm_usize.constInt(elem_ptr.index, .False), |
| 3899 | }; |
| 3900 | const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod); |
| 3901 | const elem_llvm_ty = try dg.lowerType(elem_ty); |
| 3902 | return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3903 | }, |
| 3904 | .field => |field_ptr| { |
| 3905 | const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.base.toValue(), byte_aligned); |
| 3906 | const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); |
| 3907 | |
| 3908 | const field_index = @intCast(u32, field_ptr.index); |
| 3909 | const llvm_u32 = dg.context.intType(32); |
| 3910 | switch (parent_ty.zigTypeTag(mod)) { |
| 3911 | .Union => { |
| 3912 | if (parent_ty.containerLayout(mod) == .Packed) { |
| 3913 | return parent_llvm_ptr; |
| 3914 | } |
| 3920 | 3915 | |
| 3921 | | const layout = parent_ty.unionGetLayout(mod); |
| 3922 | | if (layout.payload_size == 0) { |
| 3923 | | // In this case a pointer to the union and a pointer to any |
| 3924 | | // (void) payload is the same. |
| 3925 | | return parent_llvm_ptr; |
| 3926 | | } |
| 3927 | | const llvm_pl_index = if (layout.tag_size == 0) |
| 3928 | | 0 |
| 3929 | | else |
| 3930 | | @boolToInt(layout.tag_align >= layout.payload_align); |
| 3931 | | const indices: [2]*llvm.Value = .{ |
| 3932 | | llvm_u32.constInt(0, .False), |
| 3933 | | llvm_u32.constInt(llvm_pl_index, .False), |
| 3916 | const layout = parent_ty.unionGetLayout(mod); |
| 3917 | if (layout.payload_size == 0) { |
| 3918 | // In this case a pointer to the union and a pointer to any |
| 3919 | // (void) payload is the same. |
| 3920 | return parent_llvm_ptr; |
| 3921 | } |
| 3922 | const llvm_pl_index = if (layout.tag_size == 0) |
| 3923 | 0 |
| 3924 | else |
| 3925 | @boolToInt(layout.tag_align >= layout.payload_align); |
| 3926 | const indices: [2]*llvm.Value = .{ |
| 3927 | llvm_u32.constInt(0, .False), |
| 3928 | llvm_u32.constInt(llvm_pl_index, .False), |
| 3929 | }; |
| 3930 | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| 3931 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3932 | }, |
| 3933 | .Struct => { |
| 3934 | if (parent_ty.containerLayout(mod) == .Packed) { |
| 3935 | if (!byte_aligned) return parent_llvm_ptr; |
| 3936 | const llvm_usize = dg.context.intType(target.ptrBitWidth()); |
| 3937 | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); |
| 3938 | // count bits of fields before this one |
| 3939 | const prev_bits = b: { |
| 3940 | var b: usize = 0; |
| 3941 | for (parent_ty.structFields(mod).values()[0..field_index]) |field| { |
| 3942 | if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 3943 | b += @intCast(usize, field.ty.bitSize(mod)); |
| 3944 | } |
| 3945 | break :b b; |
| 3934 | 3946 | }; |
| 3935 | | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| 3936 | | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3937 | | }, |
| 3938 | | .Struct => { |
| 3939 | | if (parent_ty.containerLayout(mod) == .Packed) { |
| 3940 | | if (!byte_aligned) return parent_llvm_ptr; |
| 3941 | | const llvm_usize = dg.context.intType(target.ptrBitWidth()); |
| 3942 | | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); |
| 3943 | | // count bits of fields before this one |
| 3944 | | const prev_bits = b: { |
| 3945 | | var b: usize = 0; |
| 3946 | | for (parent_ty.structFields(mod).values()[0..field_index]) |field| { |
| 3947 | | if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 3948 | | b += @intCast(usize, field.ty.bitSize(mod)); |
| 3949 | | } |
| 3950 | | break :b b; |
| 3951 | | }; |
| 3952 | | const byte_offset = llvm_usize.constInt(prev_bits / 8, .False); |
| 3953 | | const field_addr = base_addr.constAdd(byte_offset); |
| 3954 | | const final_llvm_ty = dg.context.pointerType(0); |
| 3955 | | return field_addr.constIntToPtr(final_llvm_ty); |
| 3956 | | } |
| 3947 | const byte_offset = llvm_usize.constInt(prev_bits / 8, .False); |
| 3948 | const field_addr = base_addr.constAdd(byte_offset); |
| 3949 | const final_llvm_ty = dg.context.pointerType(0); |
| 3950 | return field_addr.constIntToPtr(final_llvm_ty); |
| 3951 | } |
| 3957 | 3952 | |
| 3958 | | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| 3959 | | if (llvmField(parent_ty, field_index, mod)) |llvm_field| { |
| 3960 | | const indices: [2]*llvm.Value = .{ |
| 3961 | | llvm_u32.constInt(0, .False), |
| 3962 | | llvm_u32.constInt(llvm_field.index, .False), |
| 3963 | | }; |
| 3964 | | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3965 | | } else { |
| 3966 | | const llvm_index = llvm_u32.constInt(@boolToInt(parent_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); |
| 3967 | | const indices: [1]*llvm.Value = .{llvm_index}; |
| 3968 | | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3969 | | } |
| 3970 | | }, |
| 3971 | | .Pointer => { |
| 3972 | | assert(parent_ty.isSlice(mod)); |
| 3953 | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| 3954 | if (llvmField(parent_ty, field_index, mod)) |llvm_field| { |
| 3973 | 3955 | const indices: [2]*llvm.Value = .{ |
| 3974 | 3956 | llvm_u32.constInt(0, .False), |
| 3975 | | llvm_u32.constInt(field_index, .False), |
| 3957 | llvm_u32.constInt(llvm_field.index, .False), |
| 3976 | 3958 | }; |
| 3977 | | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| 3978 | 3959 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3979 | | }, |
| 3980 | | else => unreachable, |
| 3981 | | } |
| 3982 | | }, |
| 3960 | } else { |
| 3961 | const llvm_index = llvm_u32.constInt(@boolToInt(parent_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); |
| 3962 | const indices: [1]*llvm.Value = .{llvm_index}; |
| 3963 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3964 | } |
| 3965 | }, |
| 3966 | .Pointer => { |
| 3967 | assert(parent_ty.isSlice(mod)); |
| 3968 | const indices: [2]*llvm.Value = .{ |
| 3969 | llvm_u32.constInt(0, .False), |
| 3970 | llvm_u32.constInt(field_index, .False), |
| 3971 | }; |
| 3972 | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| 3973 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3974 | }, |
| 3975 | else => unreachable, |
| 3976 | } |
| 3983 | 3977 | }, |
| 3984 | | else => unreachable, |
| 3985 | 3978 | }; |
| 3986 | 3979 | } |
| 3987 | 3980 | |