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