| ... | @@ -1518,26 +1518,8 @@ pub const DeclGen = struct { | ... | @@ -1518,26 +1518,8 @@ pub const DeclGen = struct { |
| 1518 | const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(), .False); | 1518 | const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(), .False); |
| 1519 | return llvm_int.constIntToPtr(try dg.llvmType(tv.ty)); | 1519 | return llvm_int.constIntToPtr(try dg.llvmType(tv.ty)); |
| 1520 | }, | 1520 | }, |
| 1521 | .field_ptr, .opt_payload_ptr, .eu_payload_ptr => { | 1521 | .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => { |
| 1522 | const parent = try dg.lowerParentPtr(tv.val, tv.ty); | 1522 | return dg.lowerParentPtr(tv.val, tv.ty.childType()); |
| 1523 | return parent.llvm_ptr.constBitCast(try dg.llvmType(tv.ty)); | | |
| 1524 | }, | | |
| 1525 | .elem_ptr => { | | |
| 1526 | const elem_ptr = tv.val.castTag(.elem_ptr).?.data; | | |
| 1527 | const parent = try dg.lowerParentPtr(elem_ptr.array_ptr, tv.ty); | | |
| 1528 | const llvm_usize = try dg.llvmType(Type.usize); | | |
| 1529 | if (parent.llvm_ptr.typeOf().getElementType().getTypeKind() == .Array) { | | |
| 1530 | const indices: [2]*const llvm.Value = .{ | | |
| 1531 | llvm_usize.constInt(0, .False), | | |
| 1532 | llvm_usize.constInt(elem_ptr.index, .False), | | |
| 1533 | }; | | |
| 1534 | return parent.llvm_ptr.constInBoundsGEP(&indices, indices.len); | | |
| 1535 | } else { | | |
| 1536 | const indices: [1]*const llvm.Value = .{ | | |
| 1537 | llvm_usize.constInt(elem_ptr.index, .False), | | |
| 1538 | }; | | |
| 1539 | return parent.llvm_ptr.constInBoundsGEP(&indices, indices.len); | | |
| 1540 | } | | |
| 1541 | }, | 1523 | }, |
| 1542 | .null_value, .zero => { | 1524 | .null_value, .zero => { |
| 1543 | const llvm_type = try dg.llvmType(tv.ty); | 1525 | const llvm_type = try dg.llvmType(tv.ty); |
| ... | @@ -2786,7 +2768,7 @@ pub const DeclGen = struct { | ... | @@ -2786,7 +2768,7 @@ pub const DeclGen = struct { |
| 2786 | llvm_ptr: *const llvm.Value, | 2768 | llvm_ptr: *const llvm.Value, |
| 2787 | }; | 2769 | }; |
| 2788 | | 2770 | |
| 2789 | fn lowerParentPtrDecl(dg: *DeclGen, ptr_val: Value, decl: *Module.Decl) Error!ParentPtr { | 2771 | fn lowerParentPtrDecl(dg: *DeclGen, ptr_val: Value, decl: *Module.Decl, ptr_child_ty: Type) Error!*const llvm.Value { |
| 2790 | decl.markAlive(); | 2772 | decl.markAlive(); |
| 2791 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 2773 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 2792 | .base = .{ .tag = .single_mut_pointer }, | 2774 | .base = .{ .tag = .single_mut_pointer }, |
| ... | @@ -2794,123 +2776,104 @@ pub const DeclGen = struct { | ... | @@ -2794,123 +2776,104 @@ pub const DeclGen = struct { |
| 2794 | }; | 2776 | }; |
| 2795 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); | 2777 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 2796 | const llvm_ptr = try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl); | 2778 | const llvm_ptr = try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl); |
| 2797 | return ParentPtr{ | 2779 | |
| 2798 | .llvm_ptr = llvm_ptr, | 2780 | if (ptr_child_ty.eql(decl.ty)) { |
| 2799 | .ty = decl.ty, | 2781 | return llvm_ptr; |
| 2800 | }; | 2782 | } else { |
| | 2783 | return llvm_ptr.constBitCast((try dg.llvmType(ptr_child_ty)).pointerType(0)); |
| | 2784 | } |
| 2801 | } | 2785 | } |
| 2802 | | 2786 | |
| 2803 | fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, base_ty: Type) Error!ParentPtr { | 2787 | fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, ptr_child_ty: Type) Error!*const llvm.Value { |
| 2804 | switch (ptr_val.tag()) { | 2788 | var bitcast_needed: bool = undefined; |
| | 2789 | const llvm_ptr = switch (ptr_val.tag()) { |
| 2805 | .decl_ref_mut => { | 2790 | .decl_ref_mut => { |
| 2806 | const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl; | 2791 | const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl; |
| 2807 | return dg.lowerParentPtrDecl(ptr_val, decl); | 2792 | return dg.lowerParentPtrDecl(ptr_val, decl, ptr_child_ty); |
| 2808 | }, | 2793 | }, |
| 2809 | .decl_ref => { | 2794 | .decl_ref => { |
| 2810 | const decl = ptr_val.castTag(.decl_ref).?.data; | 2795 | const decl = ptr_val.castTag(.decl_ref).?.data; |
| 2811 | return dg.lowerParentPtrDecl(ptr_val, decl); | 2796 | return dg.lowerParentPtrDecl(ptr_val, decl, ptr_child_ty); |
| 2812 | }, | 2797 | }, |
| 2813 | .variable => { | 2798 | .variable => { |
| 2814 | const decl = ptr_val.castTag(.variable).?.data.owner_decl; | 2799 | const decl = ptr_val.castTag(.variable).?.data.owner_decl; |
| 2815 | return dg.lowerParentPtrDecl(ptr_val, decl); | 2800 | return dg.lowerParentPtrDecl(ptr_val, decl, ptr_child_ty); |
| 2816 | }, | 2801 | }, |
| 2817 | .int_i64 => { | 2802 | .int_i64 => { |
| 2818 | const int = ptr_val.castTag(.int_i64).?.data; | 2803 | const int = ptr_val.castTag(.int_i64).?.data; |
| 2819 | const llvm_usize = try dg.llvmType(Type.usize); | 2804 | const llvm_usize = try dg.llvmType(Type.usize); |
| 2820 | const llvm_int = llvm_usize.constInt(@bitCast(u64, int), .False); | 2805 | const llvm_int = llvm_usize.constInt(@bitCast(u64, int), .False); |
| 2821 | return ParentPtr{ | 2806 | return llvm_int.constIntToPtr((try dg.llvmType(ptr_child_ty)).pointerType(0)); |
| 2822 | .llvm_ptr = llvm_int.constIntToPtr(try dg.llvmType(base_ty)), | | |
| 2823 | .ty = base_ty, | | |
| 2824 | }; | | |
| 2825 | }, | 2807 | }, |
| 2826 | .int_u64 => { | 2808 | .int_u64 => { |
| 2827 | const int = ptr_val.castTag(.int_u64).?.data; | 2809 | const int = ptr_val.castTag(.int_u64).?.data; |
| 2828 | const llvm_usize = try dg.llvmType(Type.usize); | 2810 | const llvm_usize = try dg.llvmType(Type.usize); |
| 2829 | const llvm_int = llvm_usize.constInt(int, .False); | 2811 | const llvm_int = llvm_usize.constInt(int, .False); |
| 2830 | return ParentPtr{ | 2812 | return llvm_int.constIntToPtr((try dg.llvmType(ptr_child_ty)).pointerType(0)); |
| 2831 | .llvm_ptr = llvm_int.constIntToPtr(try dg.llvmType(base_ty)), | | |
| 2832 | .ty = base_ty, | | |
| 2833 | }; | | |
| 2834 | }, | 2813 | }, |
| 2835 | .field_ptr => { | 2814 | .field_ptr => blk: { |
| 2836 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | 2815 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 2837 | const parent = try dg.lowerParentPtr(field_ptr.container_ptr, base_ty); | 2816 | const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.container_ptr, field_ptr.container_ty); |
| | 2817 | const parent_ty = field_ptr.container_ty; |
| | 2818 | |
| 2838 | const field_index = @intCast(u32, field_ptr.field_index); | 2819 | const field_index = @intCast(u32, field_ptr.field_index); |
| 2839 | const llvm_u32 = dg.context.intType(32); | 2820 | const llvm_u32 = dg.context.intType(32); |
| 2840 | const target = dg.module.getTarget(); | 2821 | const target = dg.module.getTarget(); |
| 2841 | switch (parent.ty.zigTypeTag()) { | 2822 | switch (parent_ty.zigTypeTag()) { |
| 2842 | .Union => { | 2823 | .Union => { |
| 2843 | const fields = parent.ty.unionFields(); | 2824 | bitcast_needed = true; |
| 2844 | const layout = parent.ty.unionGetLayout(target); | 2825 | |
| 2845 | const field_ty = fields.values()[field_index].ty; | 2826 | const layout = parent_ty.unionGetLayout(target); |
| 2846 | if (layout.payload_size == 0) { | 2827 | if (layout.payload_size == 0) { |
| 2847 | // In this case a pointer to the union and a pointer to any | 2828 | // In this case a pointer to the union and a pointer to any |
| 2848 | // (void) payload is the same. | 2829 | // (void) payload is the same. |
| 2849 | return ParentPtr{ | 2830 | break :blk parent_llvm_ptr; |
| 2850 | .llvm_ptr = parent.llvm_ptr, | | |
| 2851 | .ty = field_ty, | | |
| 2852 | }; | | |
| 2853 | } | | |
| 2854 | if (layout.tag_size == 0) { | | |
| 2855 | const indices: [2]*const llvm.Value = .{ | | |
| 2856 | llvm_u32.constInt(0, .False), | | |
| 2857 | llvm_u32.constInt(0, .False), | | |
| 2858 | }; | | |
| 2859 | return ParentPtr{ | | |
| 2860 | .llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len), | | |
| 2861 | .ty = field_ty, | | |
| 2862 | }; | | |
| 2863 | } | 2831 | } |
| 2864 | const llvm_pl_index = @boolToInt(layout.tag_align >= layout.payload_align); | 2832 | const llvm_pl_index = if (layout.tag_size == 0) 0 else @boolToInt(layout.tag_align >= layout.payload_align); |
| 2865 | const indices: [2]*const llvm.Value = .{ | 2833 | const indices: [2]*const llvm.Value = .{ |
| 2866 | llvm_u32.constInt(0, .False), | 2834 | llvm_u32.constInt(0, .False), |
| 2867 | llvm_u32.constInt(llvm_pl_index, .False), | 2835 | llvm_u32.constInt(llvm_pl_index, .False), |
| 2868 | }; | 2836 | }; |
| 2869 | return ParentPtr{ | 2837 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); |
| 2870 | .llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len), | | |
| 2871 | .ty = field_ty, | | |
| 2872 | }; | | |
| 2873 | }, | 2838 | }, |
| 2874 | .Struct => { | 2839 | .Struct => { |
| | 2840 | const field_ty = parent_ty.structFieldType(field_index); |
| | 2841 | bitcast_needed = !field_ty.eql(ptr_child_ty); |
| | 2842 | |
| 2875 | var ty_buf: Type.Payload.Pointer = undefined; | 2843 | var ty_buf: Type.Payload.Pointer = undefined; |
| 2876 | const llvm_field_index = llvmFieldIndex(parent.ty, field_index, target, &ty_buf).?; | 2844 | const llvm_field_index = llvmFieldIndex(parent_ty, field_index, target, &ty_buf).?; |
| 2877 | const indices: [2]*const llvm.Value = .{ | 2845 | const indices: [2]*const llvm.Value = .{ |
| 2878 | llvm_u32.constInt(0, .False), | 2846 | llvm_u32.constInt(0, .False), |
| 2879 | llvm_u32.constInt(llvm_field_index, .False), | 2847 | llvm_u32.constInt(llvm_field_index, .False), |
| 2880 | }; | 2848 | }; |
| 2881 | return ParentPtr{ | 2849 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); |
| 2882 | .llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len), | | |
| 2883 | .ty = parent.ty.structFieldType(field_index), | | |
| 2884 | }; | | |
| 2885 | }, | 2850 | }, |
| 2886 | else => unreachable, | 2851 | else => unreachable, |
| 2887 | } | 2852 | } |
| 2888 | }, | 2853 | }, |
| 2889 | .elem_ptr => { | 2854 | .elem_ptr => blk: { |
| 2890 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; | 2855 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| 2891 | const parent = try dg.lowerParentPtr(elem_ptr.array_ptr, base_ty); | 2856 | const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr, elem_ptr.elem_ty); |
| | 2857 | bitcast_needed = !elem_ptr.elem_ty.eql(ptr_child_ty); |
| | 2858 | |
| 2892 | const llvm_usize = try dg.llvmType(Type.usize); | 2859 | const llvm_usize = try dg.llvmType(Type.usize); |
| 2893 | const indices: [2]*const llvm.Value = .{ | 2860 | const indices: [1]*const llvm.Value = .{ |
| 2894 | llvm_usize.constInt(0, .False), | | |
| 2895 | llvm_usize.constInt(elem_ptr.index, .False), | 2861 | llvm_usize.constInt(elem_ptr.index, .False), |
| 2896 | }; | 2862 | }; |
| 2897 | return ParentPtr{ | 2863 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); |
| 2898 | .llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len), | | |
| 2899 | .ty = parent.ty.childType(), | | |
| 2900 | }; | | |
| 2901 | }, | 2864 | }, |
| 2902 | .opt_payload_ptr => { | 2865 | .opt_payload_ptr => blk: { |
| 2903 | const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; | 2866 | const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; |
| 2904 | const parent = try dg.lowerParentPtr(opt_payload_ptr.container_ptr, base_ty); | 2867 | const parent_llvm_ptr = try dg.lowerParentPtr(opt_payload_ptr.container_ptr, opt_payload_ptr.container_ty); |
| 2905 | var buf: Type.Payload.ElemType = undefined; | 2868 | var buf: Type.Payload.ElemType = undefined; |
| 2906 | const payload_ty = parent.ty.optionalChild(&buf); | 2869 | |
| 2907 | if (!payload_ty.hasRuntimeBitsIgnoreComptime() or parent.ty.isPtrLikeOptional()) { | 2870 | const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf); |
| | 2871 | bitcast_needed = !payload_ty.eql(ptr_child_ty); |
| | 2872 | |
| | 2873 | if (!payload_ty.hasRuntimeBitsIgnoreComptime() or payload_ty.isPtrLikeOptional()) { |
| 2908 | // In this case, we represent pointer to optional the same as pointer | 2874 | // In this case, we represent pointer to optional the same as pointer |
| 2909 | // to the payload. | 2875 | // to the payload. |
| 2910 | return ParentPtr{ | 2876 | break :blk parent_llvm_ptr; |
| 2911 | .llvm_ptr = parent.llvm_ptr, | | |
| 2912 | .ty = payload_ty, | | |
| 2913 | }; | | |
| 2914 | } | 2877 | } |
| 2915 | | 2878 | |
| 2916 | const llvm_u32 = dg.context.intType(32); | 2879 | const llvm_u32 = dg.context.intType(32); |
| ... | @@ -2918,22 +2881,19 @@ pub const DeclGen = struct { | ... | @@ -2918,22 +2881,19 @@ pub const DeclGen = struct { |
| 2918 | llvm_u32.constInt(0, .False), | 2881 | llvm_u32.constInt(0, .False), |
| 2919 | llvm_u32.constInt(0, .False), | 2882 | llvm_u32.constInt(0, .False), |
| 2920 | }; | 2883 | }; |
| 2921 | return ParentPtr{ | 2884 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); |
| 2922 | .llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len), | | |
| 2923 | .ty = payload_ty, | | |
| 2924 | }; | | |
| 2925 | }, | 2885 | }, |
| 2926 | .eu_payload_ptr => { | 2886 | .eu_payload_ptr => blk: { |
| 2927 | const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; | 2887 | const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; |
| 2928 | const parent = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, base_ty); | 2888 | const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, eu_payload_ptr.container_ty); |
| 2929 | const payload_ty = parent.ty.errorUnionPayload(); | 2889 | |
| | 2890 | const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload(); |
| | 2891 | bitcast_needed = !payload_ty.eql(ptr_child_ty); |
| | 2892 | |
| 2930 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 2893 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 2931 | // In this case, we represent pointer to error union the same as pointer | 2894 | // In this case, we represent pointer to error union the same as pointer |
| 2932 | // to the payload. | 2895 | // to the payload. |
| 2933 | return ParentPtr{ | 2896 | break :blk parent_llvm_ptr; |
| 2934 | .llvm_ptr = parent.llvm_ptr, | | |
| 2935 | .ty = payload_ty, | | |
| 2936 | }; | | |
| 2937 | } | 2897 | } |
| 2938 | | 2898 | |
| 2939 | const llvm_u32 = dg.context.intType(32); | 2899 | const llvm_u32 = dg.context.intType(32); |
| ... | @@ -2941,12 +2901,14 @@ pub const DeclGen = struct { | ... | @@ -2941,12 +2901,14 @@ pub const DeclGen = struct { |
| 2941 | llvm_u32.constInt(0, .False), | 2901 | llvm_u32.constInt(0, .False), |
| 2942 | llvm_u32.constInt(1, .False), | 2902 | llvm_u32.constInt(1, .False), |
| 2943 | }; | 2903 | }; |
| 2944 | return ParentPtr{ | 2904 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); |
| 2945 | .llvm_ptr = parent.llvm_ptr.constInBoundsGEP(&indices, indices.len), | | |
| 2946 | .ty = payload_ty, | | |
| 2947 | }; | | |
| 2948 | }, | 2905 | }, |
| 2949 | else => unreachable, | 2906 | else => unreachable, |
| | 2907 | }; |
| | 2908 | if (bitcast_needed) { |
| | 2909 | return llvm_ptr.constBitCast((try dg.llvmType(ptr_child_ty)).pointerType(0)); |
| | 2910 | } else { |
| | 2911 | return llvm_ptr; |
| 2950 | } | 2912 | } |
| 2951 | } | 2913 | } |
| 2952 | | 2914 | |