| ... | ... | @@ -611,7 +611,7 @@ pub const Object = struct { |
| 611 | 611 | }; |
| 612 | 612 | errdefer builder.llvm_context.dispose(); |
| 613 | 613 | |
| 614 | | initializeLLVMTarget(options.target.cpu.arch); |
| 614 | builder.initializeLLVMTarget(options.target.cpu.arch); |
| 615 | 615 | |
| 616 | 616 | builder.llvm_module = llvm.Module.createWithName(options.root_name.ptr, builder.llvm_context); |
| 617 | 617 | errdefer builder.llvm_module.dispose(); |
| ... | ... | @@ -832,7 +832,7 @@ pub const Object = struct { |
| 832 | 832 | |
| 833 | 833 | const slice_fields = [_]*llvm.Value{ |
| 834 | 834 | str_global, |
| 835 | | llvm_usize_ty.toLlvm(&o.builder).constInt(name.len, .False), |
| 835 | (try o.builder.intConst(llvm_usize_ty, name.len)).toLlvm(&o.builder), |
| 836 | 836 | }; |
| 837 | 837 | llvm_error.* = llvm_slice_ty.constNamedStruct(&slice_fields, slice_fields.len); |
| 838 | 838 | } |
| ... | ... | @@ -874,8 +874,8 @@ pub const Object = struct { |
| 874 | 874 | // } |
| 875 | 875 | |
| 876 | 876 | const lhs = llvm_fn.getParam(0); |
| 877 | | const rhs = lhs.typeOf().constInt(errors_len, .False); |
| 878 | | const is_lt = builder.buildICmp(.ULT, lhs, rhs, ""); |
| 877 | const rhs = try object.builder.intConst(Builder.Type.err_int, errors_len); |
| 878 | const is_lt = builder.buildICmp(.ULT, lhs, rhs.toLlvm(&object.builder), ""); |
| 879 | 879 | _ = builder.buildRet(is_lt); |
| 880 | 880 | } |
| 881 | 881 | |
| ... | ... | @@ -3474,10 +3474,8 @@ pub const Object = struct { |
| 3474 | 3474 | .@"unreachable", |
| 3475 | 3475 | .generic_poison, |
| 3476 | 3476 | => unreachable, // non-runtime values |
| 3477 | | .false, .true => { |
| 3478 | | const llvm_type = (try o.lowerType(tv.ty)).toLlvm(&o.builder); |
| 3479 | | return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(); |
| 3480 | | }, |
| 3477 | .false => return Builder.Constant.false.toLlvm(&o.builder), |
| 3478 | .true => return Builder.Constant.true.toLlvm(&o.builder), |
| 3481 | 3479 | }, |
| 3482 | 3480 | .variable, |
| 3483 | 3481 | .enum_literal, |
| ... | ... | @@ -3503,9 +3501,9 @@ pub const Object = struct { |
| 3503 | 3501 | return lowerBigInt(o, tv.ty, bigint); |
| 3504 | 3502 | }, |
| 3505 | 3503 | .err => |err| { |
| 3506 | | const llvm_ty = Builder.Type.err_int.toLlvm(&o.builder); |
| 3507 | 3504 | const int = try mod.getErrorValue(err.name); |
| 3508 | | return llvm_ty.constInt(int, .False); |
| 3505 | const llvm_int = try o.builder.intConst(Builder.Type.err_int, int); |
| 3506 | return llvm_int.toLlvm(&o.builder); |
| 3509 | 3507 | }, |
| 3510 | 3508 | .error_union => |error_union| { |
| 3511 | 3509 | const err_tv: TypedValue = switch (error_union.val) { |
| ... | ... | @@ -3556,79 +3554,33 @@ pub const Object = struct { |
| 3556 | 3554 | return o.context.constStruct(&fields_buf, llvm_field_count, .False); |
| 3557 | 3555 | } |
| 3558 | 3556 | }, |
| 3559 | | .enum_tag => { |
| 3560 | | const int_val = try tv.intFromEnum(mod); |
| 3561 | | |
| 3562 | | var bigint_space: Value.BigIntSpace = undefined; |
| 3563 | | const bigint = int_val.toBigInt(&bigint_space, mod); |
| 3564 | | |
| 3565 | | const int_info = tv.ty.intInfo(mod); |
| 3566 | | const llvm_type = (try o.builder.intType(@intCast(int_info.bits))).toLlvm(&o.builder); |
| 3567 | | |
| 3568 | | const unsigned_val = v: { |
| 3569 | | if (bigint.limbs.len == 1) { |
| 3570 | | break :v llvm_type.constInt(bigint.limbs[0], .False); |
| 3571 | | } |
| 3572 | | if (@sizeOf(usize) == @sizeOf(u64)) { |
| 3573 | | break :v llvm_type.constIntOfArbitraryPrecision( |
| 3574 | | @as(c_uint, @intCast(bigint.limbs.len)), |
| 3575 | | bigint.limbs.ptr, |
| 3576 | | ); |
| 3577 | | } |
| 3578 | | @panic("TODO implement bigint to llvm int for 32-bit compiler builds"); |
| 3579 | | }; |
| 3580 | | if (!bigint.positive) { |
| 3581 | | return llvm.constNeg(unsigned_val); |
| 3582 | | } |
| 3583 | | return unsigned_val; |
| 3584 | | }, |
| 3585 | | .float => { |
| 3586 | | const llvm_ty = (try o.lowerType(tv.ty)).toLlvm(&o.builder); |
| 3587 | | switch (tv.ty.floatBits(target)) { |
| 3588 | | 16 => { |
| 3589 | | const repr = @as(u16, @bitCast(tv.val.toFloat(f16, mod))); |
| 3590 | | const llvm_i16 = Builder.Type.i16.toLlvm(&o.builder); |
| 3591 | | const int = llvm_i16.constInt(repr, .False); |
| 3592 | | return int.constBitCast(llvm_ty); |
| 3593 | | }, |
| 3594 | | 32 => { |
| 3595 | | const repr = @as(u32, @bitCast(tv.val.toFloat(f32, mod))); |
| 3596 | | const llvm_i32 = Builder.Type.i32.toLlvm(&o.builder); |
| 3597 | | const int = llvm_i32.constInt(repr, .False); |
| 3598 | | return int.constBitCast(llvm_ty); |
| 3599 | | }, |
| 3600 | | 64 => { |
| 3601 | | const repr = @as(u64, @bitCast(tv.val.toFloat(f64, mod))); |
| 3602 | | const llvm_i64 = Builder.Type.i64.toLlvm(&o.builder); |
| 3603 | | const int = llvm_i64.constInt(repr, .False); |
| 3604 | | return int.constBitCast(llvm_ty); |
| 3605 | | }, |
| 3606 | | 80 => { |
| 3607 | | const float = tv.val.toFloat(f80, mod); |
| 3608 | | const repr = std.math.break_f80(float); |
| 3609 | | const llvm_i80 = Builder.Type.i80.toLlvm(&o.builder); |
| 3610 | | var x = llvm_i80.constInt(repr.exp, .False); |
| 3611 | | x = x.constShl(llvm_i80.constInt(64, .False)); |
| 3612 | | x = x.constOr(llvm_i80.constInt(repr.fraction, .False)); |
| 3613 | | if (backendSupportsF80(target)) { |
| 3614 | | return x.constBitCast(llvm_ty); |
| 3615 | | } else { |
| 3616 | | return x; |
| 3617 | | } |
| 3618 | | }, |
| 3619 | | 128 => { |
| 3620 | | var buf: [2]u64 = @as([2]u64, @bitCast(tv.val.toFloat(f128, mod))); |
| 3621 | | // LLVM seems to require that the lower half of the f128 be placed first |
| 3622 | | // in the buffer. |
| 3623 | | if (native_endian == .Big) { |
| 3624 | | std.mem.swap(u64, &buf[0], &buf[1]); |
| 3625 | | } |
| 3626 | | const int = Builder.Type.i128.toLlvm(&o.builder).constIntOfArbitraryPrecision(buf.len, &buf); |
| 3627 | | return int.constBitCast(llvm_ty); |
| 3628 | | }, |
| 3629 | | else => unreachable, |
| 3630 | | } |
| 3631 | | }, |
| 3557 | .enum_tag => |enum_tag| return o.lowerValue(.{ |
| 3558 | .ty = mod.intern_pool.typeOf(enum_tag.int).toType(), |
| 3559 | .val = enum_tag.int.toValue(), |
| 3560 | }), |
| 3561 | .float => return switch (tv.ty.floatBits(target)) { |
| 3562 | 16 => int: { |
| 3563 | const repr: i16 = @bitCast(tv.val.toFloat(f16, mod)); |
| 3564 | break :int try o.builder.intConst(.i16, repr); |
| 3565 | }, |
| 3566 | 32 => int: { |
| 3567 | const repr: i32 = @bitCast(tv.val.toFloat(f32, mod)); |
| 3568 | break :int try o.builder.intConst(.i32, repr); |
| 3569 | }, |
| 3570 | 64 => int: { |
| 3571 | const repr: i64 = @bitCast(tv.val.toFloat(f64, mod)); |
| 3572 | break :int try o.builder.intConst(.i64, repr); |
| 3573 | }, |
| 3574 | 80 => int: { |
| 3575 | const repr: i80 = @bitCast(tv.val.toFloat(f80, mod)); |
| 3576 | break :int try o.builder.intConst(.i80, repr); |
| 3577 | }, |
| 3578 | 128 => int: { |
| 3579 | const repr: i128 = @bitCast(tv.val.toFloat(f128, mod)); |
| 3580 | break :int try o.builder.intConst(.i128, repr); |
| 3581 | }, |
| 3582 | else => unreachable, |
| 3583 | }.toLlvm(&o.builder).constBitCast((try o.lowerType(tv.ty)).toLlvm(&o.builder)), |
| 3632 | 3584 | .ptr => |ptr| { |
| 3633 | 3585 | const ptr_tv: TypedValue = switch (ptr.len) { |
| 3634 | 3586 | .none => tv, |
| ... | ... | @@ -3660,11 +3612,7 @@ pub const Object = struct { |
| 3660 | 3612 | comptime assert(optional_layout_version == 3); |
| 3661 | 3613 | const payload_ty = tv.ty.optionalChild(mod); |
| 3662 | 3614 | |
| 3663 | | const llvm_i8 = Builder.Type.i8.toLlvm(&o.builder); |
| 3664 | | const non_null_bit = switch (opt.val) { |
| 3665 | | .none => llvm_i8.constNull(), |
| 3666 | | else => llvm_i8.constInt(1, .False), |
| 3667 | | }; |
| 3615 | const non_null_bit = (try o.builder.intConst(.i8, @intFromBool(opt.val != .none))).toLlvm(&o.builder); |
| 3668 | 3616 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3669 | 3617 | return non_null_bit; |
| 3670 | 3618 | } |
| ... | ... | @@ -3761,10 +3709,9 @@ pub const Object = struct { |
| 3761 | 3709 | const elem_ty = vector_type.child.toType(); |
| 3762 | 3710 | const llvm_elems = try gpa.alloc(*llvm.Value, vector_type.len); |
| 3763 | 3711 | defer gpa.free(llvm_elems); |
| 3764 | | const llvm_i8 = Builder.Type.i8.toLlvm(&o.builder); |
| 3765 | 3712 | for (llvm_elems, 0..) |*llvm_elem, i| { |
| 3766 | 3713 | llvm_elem.* = switch (aggregate.storage) { |
| 3767 | | .bytes => |bytes| llvm_i8.constInt(bytes[i], .False), |
| 3714 | .bytes => |bytes| (try o.builder.intConst(.i8, bytes[i])).toLlvm(&o.builder), |
| 3768 | 3715 | .elems => |elems| try o.lowerValue(.{ |
| 3769 | 3716 | .ty = elem_ty, |
| 3770 | 3717 | .val = elems[i].toValue(), |
| ... | ... | @@ -3802,10 +3749,10 @@ pub const Object = struct { |
| 3802 | 3749 | |
| 3803 | 3750 | const padding_len = offset - prev_offset; |
| 3804 | 3751 | if (padding_len > 0) { |
| 3805 | | const llvm_array_ty = Builder.Type.i8.toLlvm(&o.builder).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3752 | const llvm_array_ty = try o.builder.arrayType(padding_len, .i8); |
| 3806 | 3753 | // TODO make this and all other padding elsewhere in debug |
| 3807 | 3754 | // builds be 0xaa not undef. |
| 3808 | | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 3755 | llvm_fields.appendAssumeCapacity(llvm_array_ty.toLlvm(&o.builder).getUndef()); |
| 3809 | 3756 | } |
| 3810 | 3757 | |
| 3811 | 3758 | const field_llvm_val = try o.lowerValue(.{ |
| ... | ... | @@ -3824,8 +3771,8 @@ pub const Object = struct { |
| 3824 | 3771 | offset = std.mem.alignForward(u64, offset, big_align); |
| 3825 | 3772 | const padding_len = offset - prev_offset; |
| 3826 | 3773 | if (padding_len > 0) { |
| 3827 | | const llvm_array_ty = Builder.Type.i8.toLlvm(&o.builder).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3828 | | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 3774 | const llvm_array_ty = try o.builder.arrayType(padding_len, .i8); |
| 3775 | llvm_fields.appendAssumeCapacity(llvm_array_ty.toLlvm(&o.builder).getUndef()); |
| 3829 | 3776 | } |
| 3830 | 3777 | } |
| 3831 | 3778 | |
| ... | ... | @@ -3850,10 +3797,10 @@ pub const Object = struct { |
| 3850 | 3797 | if (struct_obj.layout == .Packed) { |
| 3851 | 3798 | assert(struct_obj.haveLayout()); |
| 3852 | 3799 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); |
| 3853 | | const int_llvm_ty = (try o.builder.intType(@intCast(big_bits))).toLlvm(&o.builder); |
| 3800 | const int_llvm_ty = try o.builder.intType(@intCast(big_bits)); |
| 3854 | 3801 | const fields = struct_obj.fields.values(); |
| 3855 | 3802 | comptime assert(Type.packed_struct_layout_version == 2); |
| 3856 | | var running_int: *llvm.Value = int_llvm_ty.constNull(); |
| 3803 | var running_int = (try o.builder.intConst(int_llvm_ty, 0)).toLlvm(&o.builder); |
| 3857 | 3804 | var running_bits: u16 = 0; |
| 3858 | 3805 | for (fields, 0..) |field, i| { |
| 3859 | 3806 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| ... | ... | @@ -3868,11 +3815,11 @@ pub const Object = struct { |
| 3868 | 3815 | non_int_val.constPtrToInt(small_int_ty) |
| 3869 | 3816 | else |
| 3870 | 3817 | non_int_val.constBitCast(small_int_ty); |
| 3871 | | const shift_rhs = int_llvm_ty.constInt(running_bits, .False); |
| 3818 | const shift_rhs = (try o.builder.intConst(int_llvm_ty, running_bits)).toLlvm(&o.builder); |
| 3872 | 3819 | // If the field is as large as the entire packed struct, this |
| 3873 | 3820 | // zext would go from, e.g. i16 to i16. This is legal with |
| 3874 | 3821 | // constZExtOrBitCast but not legal with constZExt. |
| 3875 | | const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty); |
| 3822 | const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty.toLlvm(&o.builder)); |
| 3876 | 3823 | const shifted = extended_int_val.constShl(shift_rhs); |
| 3877 | 3824 | running_int = running_int.constOr(shifted); |
| 3878 | 3825 | running_bits += ty_bit_size; |
| ... | ... | @@ -3899,10 +3846,10 @@ pub const Object = struct { |
| 3899 | 3846 | |
| 3900 | 3847 | const padding_len = offset - prev_offset; |
| 3901 | 3848 | if (padding_len > 0) { |
| 3902 | | const llvm_array_ty = Builder.Type.i8.toLlvm(&o.builder).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3849 | const llvm_array_ty = try o.builder.arrayType(padding_len, .i8); |
| 3903 | 3850 | // TODO make this and all other padding elsewhere in debug |
| 3904 | 3851 | // builds be 0xaa not undef. |
| 3905 | | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 3852 | llvm_fields.appendAssumeCapacity(llvm_array_ty.toLlvm(&o.builder).getUndef()); |
| 3906 | 3853 | } |
| 3907 | 3854 | |
| 3908 | 3855 | const field_llvm_val = try o.lowerValue(.{ |
| ... | ... | @@ -3921,8 +3868,8 @@ pub const Object = struct { |
| 3921 | 3868 | offset = std.mem.alignForward(u64, offset, big_align); |
| 3922 | 3869 | const padding_len = offset - prev_offset; |
| 3923 | 3870 | if (padding_len > 0) { |
| 3924 | | const llvm_array_ty = Builder.Type.i8.toLlvm(&o.builder).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3925 | | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 3871 | const llvm_array_ty = try o.builder.arrayType(padding_len, .i8); |
| 3872 | llvm_fields.appendAssumeCapacity(llvm_array_ty.toLlvm(&o.builder).getUndef()); |
| 3926 | 3873 | } |
| 3927 | 3874 | } |
| 3928 | 3875 | |
| ... | ... | @@ -3985,7 +3932,7 @@ pub const Object = struct { |
| 3985 | 3932 | const payload = p: { |
| 3986 | 3933 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3987 | 3934 | const padding_len = @as(c_uint, @intCast(layout.payload_size)); |
| 3988 | | break :p Builder.Type.i8.toLlvm(&o.builder).arrayType(padding_len).getUndef(); |
| 3935 | break :p (try o.builder.arrayType(padding_len, .i8)).toLlvm(&o.builder).getUndef(); |
| 3989 | 3936 | } |
| 3990 | 3937 | const field = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 3991 | 3938 | need_unnamed = need_unnamed or o.isUnnamedType(field_ty, field); |
| ... | ... | @@ -3995,7 +3942,7 @@ pub const Object = struct { |
| 3995 | 3942 | } |
| 3996 | 3943 | const padding_len = @as(c_uint, @intCast(layout.payload_size - field_size)); |
| 3997 | 3944 | const fields: [2]*llvm.Value = .{ |
| 3998 | | field, Builder.Type.i8.toLlvm(&o.builder).arrayType(padding_len).getUndef(), |
| 3945 | field, (try o.builder.arrayType(padding_len, .i8)).toLlvm(&o.builder).getUndef(), |
| 3999 | 3946 | }; |
| 4000 | 3947 | break :p o.context.constStruct(&fields, fields.len, .True); |
| 4001 | 3948 | }; |
| ... | ... | @@ -4020,7 +3967,7 @@ pub const Object = struct { |
| 4020 | 3967 | fields = .{ payload, llvm_tag_value, undefined }; |
| 4021 | 3968 | } |
| 4022 | 3969 | if (layout.padding != 0) { |
| 4023 | | fields[2] = Builder.Type.i8.toLlvm(&o.builder).arrayType(layout.padding).getUndef(); |
| 3970 | fields[2] = (try o.builder.arrayType(layout.padding, .i8)).toLlvm(&o.builder).getUndef(); |
| 4024 | 3971 | fields_len = 3; |
| 4025 | 3972 | } |
| 4026 | 3973 | if (need_unnamed) { |
| ... | ... | @@ -4048,27 +3995,8 @@ pub const Object = struct { |
| 4048 | 3995 | } |
| 4049 | 3996 | |
| 4050 | 3997 | fn lowerBigInt(o: *Object, ty: Type, bigint: std.math.big.int.Const) Allocator.Error!*llvm.Value { |
| 4051 | | const mod = o.module; |
| 4052 | | const int_info = ty.intInfo(mod); |
| 4053 | | assert(int_info.bits != 0); |
| 4054 | | const llvm_type = (try o.builder.intType(@intCast(int_info.bits))).toLlvm(&o.builder); |
| 4055 | | |
| 4056 | | const unsigned_val = v: { |
| 4057 | | if (bigint.limbs.len == 1) { |
| 4058 | | break :v llvm_type.constInt(bigint.limbs[0], .False); |
| 4059 | | } |
| 4060 | | if (@sizeOf(usize) == @sizeOf(u64)) { |
| 4061 | | break :v llvm_type.constIntOfArbitraryPrecision( |
| 4062 | | @as(c_uint, @intCast(bigint.limbs.len)), |
| 4063 | | bigint.limbs.ptr, |
| 4064 | | ); |
| 4065 | | } |
| 4066 | | @panic("TODO implement bigint to llvm int for 32-bit compiler builds"); |
| 4067 | | }; |
| 4068 | | if (!bigint.positive) { |
| 4069 | | return llvm.constNeg(unsigned_val); |
| 4070 | | } |
| 4071 | | return unsigned_val; |
| 3998 | return (try o.builder.bigIntConst(try o.builder.intType(ty.intInfo(o.module).bits), bigint)) |
| 3999 | .toLlvm(&o.builder); |
| 4072 | 4000 | } |
| 4073 | 4001 | |
| 4074 | 4002 | const ParentPtr = struct { |
| ... | ... | @@ -4106,10 +4034,9 @@ pub const Object = struct { |
| 4106 | 4034 | } |
| 4107 | 4035 | |
| 4108 | 4036 | const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1; |
| 4109 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 4110 | 4037 | const indices: [2]*llvm.Value = .{ |
| 4111 | | llvm_u32.constInt(0, .False), |
| 4112 | | llvm_u32.constInt(payload_offset, .False), |
| 4038 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 4039 | (try o.builder.intConst(.i32, payload_offset)).toLlvm(&o.builder), |
| 4113 | 4040 | }; |
| 4114 | 4041 | const eu_llvm_ty = (try o.lowerType(eu_ty)).toLlvm(&o.builder); |
| 4115 | 4042 | return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| ... | ... | @@ -4127,11 +4054,9 @@ pub const Object = struct { |
| 4127 | 4054 | return parent_llvm_ptr; |
| 4128 | 4055 | } |
| 4129 | 4056 | |
| 4130 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 4131 | 4057 | const indices: [2]*llvm.Value = .{ |
| 4132 | | llvm_u32.constInt(0, .False), |
| 4133 | | llvm_u32.constInt(0, .False), |
| 4134 | | }; |
| 4058 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 4059 | } ** 2; |
| 4135 | 4060 | const opt_llvm_ty = (try o.lowerType(opt_ty)).toLlvm(&o.builder); |
| 4136 | 4061 | return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 4137 | 4062 | }, |
| ... | ... | @@ -4139,9 +4064,8 @@ pub const Object = struct { |
| 4139 | 4064 | .elem => |elem_ptr| { |
| 4140 | 4065 | const parent_llvm_ptr = try o.lowerParentPtr(elem_ptr.base.toValue(), true); |
| 4141 | 4066 | |
| 4142 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 4143 | 4067 | const indices: [1]*llvm.Value = .{ |
| 4144 | | llvm_usize.constInt(elem_ptr.index, .False), |
| 4068 | (try o.builder.intConst(try o.lowerType(Type.usize), elem_ptr.index)).toLlvm(&o.builder), |
| 4145 | 4069 | }; |
| 4146 | 4070 | const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod); |
| 4147 | 4071 | const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| ... | ... | @@ -4152,7 +4076,6 @@ pub const Object = struct { |
| 4152 | 4076 | const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); |
| 4153 | 4077 | |
| 4154 | 4078 | const field_index = @as(u32, @intCast(field_ptr.index)); |
| 4155 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 4156 | 4079 | switch (parent_ty.zigTypeTag(mod)) { |
| 4157 | 4080 | .Union => { |
| 4158 | 4081 | if (parent_ty.containerLayout(mod) == .Packed) { |
| ... | ... | @@ -4170,8 +4093,8 @@ pub const Object = struct { |
| 4170 | 4093 | else |
| 4171 | 4094 | @intFromBool(layout.tag_align >= layout.payload_align); |
| 4172 | 4095 | const indices: [2]*llvm.Value = .{ |
| 4173 | | llvm_u32.constInt(0, .False), |
| 4174 | | llvm_u32.constInt(llvm_pl_index, .False), |
| 4096 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 4097 | (try o.builder.intConst(.i32, llvm_pl_index)).toLlvm(&o.builder), |
| 4175 | 4098 | }; |
| 4176 | 4099 | const parent_llvm_ty = (try o.lowerType(parent_ty)).toLlvm(&o.builder); |
| 4177 | 4100 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| ... | ... | @@ -4179,8 +4102,8 @@ pub const Object = struct { |
| 4179 | 4102 | .Struct => { |
| 4180 | 4103 | if (parent_ty.containerLayout(mod) == .Packed) { |
| 4181 | 4104 | if (!byte_aligned) return parent_llvm_ptr; |
| 4182 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 4183 | | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); |
| 4105 | const llvm_usize = try o.lowerType(Type.usize); |
| 4106 | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize.toLlvm(&o.builder)); |
| 4184 | 4107 | // count bits of fields before this one |
| 4185 | 4108 | const prev_bits = b: { |
| 4186 | 4109 | var b: usize = 0; |
| ... | ... | @@ -4190,7 +4113,7 @@ pub const Object = struct { |
| 4190 | 4113 | } |
| 4191 | 4114 | break :b b; |
| 4192 | 4115 | }; |
| 4193 | | const byte_offset = llvm_usize.constInt(prev_bits / 8, .False); |
| 4116 | const byte_offset = (try o.builder.intConst(llvm_usize, prev_bits / 8)).toLlvm(&o.builder); |
| 4194 | 4117 | const field_addr = base_addr.constAdd(byte_offset); |
| 4195 | 4118 | const final_llvm_ty = o.context.pointerType(0); |
| 4196 | 4119 | return field_addr.constIntToPtr(final_llvm_ty); |
| ... | ... | @@ -4199,21 +4122,22 @@ pub const Object = struct { |
| 4199 | 4122 | const parent_llvm_ty = (try o.lowerType(parent_ty)).toLlvm(&o.builder); |
| 4200 | 4123 | if (llvmField(parent_ty, field_index, mod)) |llvm_field| { |
| 4201 | 4124 | const indices: [2]*llvm.Value = .{ |
| 4202 | | llvm_u32.constInt(0, .False), |
| 4203 | | llvm_u32.constInt(llvm_field.index, .False), |
| 4125 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 4126 | (try o.builder.intConst(.i32, llvm_field.index)).toLlvm(&o.builder), |
| 4204 | 4127 | }; |
| 4205 | 4128 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 4206 | 4129 | } else { |
| 4207 | | const llvm_index = llvm_u32.constInt(@intFromBool(parent_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); |
| 4208 | | const indices: [1]*llvm.Value = .{llvm_index}; |
| 4130 | const indices: [1]*llvm.Value = .{ |
| 4131 | (try o.builder.intConst(.i32, @intFromBool(parent_ty.hasRuntimeBitsIgnoreComptime(mod)))).toLlvm(&o.builder), |
| 4132 | }; |
| 4209 | 4133 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 4210 | 4134 | } |
| 4211 | 4135 | }, |
| 4212 | 4136 | .Pointer => { |
| 4213 | 4137 | assert(parent_ty.isSlice(mod)); |
| 4214 | 4138 | const indices: [2]*llvm.Value = .{ |
| 4215 | | llvm_u32.constInt(0, .False), |
| 4216 | | llvm_u32.constInt(field_index, .False), |
| 4139 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 4140 | (try o.builder.intConst(.i32, field_index)).toLlvm(&o.builder), |
| 4217 | 4141 | }; |
| 4218 | 4142 | const parent_llvm_ty = (try o.lowerType(parent_ty)).toLlvm(&o.builder); |
| 4219 | 4143 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| ... | ... | @@ -4284,10 +4208,10 @@ pub const Object = struct { |
| 4284 | 4208 | // The value cannot be undefined, because we use the `nonnull` annotation |
| 4285 | 4209 | // for non-optional pointers. We also need to respect the alignment, even though |
| 4286 | 4210 | // the address will never be dereferenced. |
| 4287 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 4211 | const llvm_usize = try o.lowerType(Type.usize); |
| 4288 | 4212 | const llvm_ptr_ty = (try o.lowerType(ptr_ty)).toLlvm(&o.builder); |
| 4289 | 4213 | if (ptr_ty.ptrInfo(mod).flags.alignment.toByteUnitsOptional()) |alignment| { |
| 4290 | | return llvm_usize.constInt(alignment, .False).constIntToPtr(llvm_ptr_ty); |
| 4214 | return (try o.builder.intConst(llvm_usize, alignment)).toLlvm(&o.builder).constIntToPtr(llvm_ptr_ty); |
| 4291 | 4215 | } |
| 4292 | 4216 | // Note that these 0xaa values are appropriate even in release-optimized builds |
| 4293 | 4217 | // because we need a well-defined value that is not null, and LLVM does not |
| ... | ... | @@ -4295,13 +4219,13 @@ pub const Object = struct { |
| 4295 | 4219 | // instruction is followed by a `wrap_optional`, it will return this value |
| 4296 | 4220 | // verbatim, and the result should test as non-null. |
| 4297 | 4221 | const target = mod.getTarget(); |
| 4298 | | const int = switch (target.ptrBitWidth()) { |
| 4299 | | 16 => llvm_usize.constInt(0xaaaa, .False), |
| 4300 | | 32 => llvm_usize.constInt(0xaaaaaaaa, .False), |
| 4301 | | 64 => llvm_usize.constInt(0xaaaaaaaa_aaaaaaaa, .False), |
| 4222 | const int = try o.builder.intConst(llvm_usize, @as(u64, switch (target.ptrBitWidth()) { |
| 4223 | 16 => 0xaaaa, |
| 4224 | 32 => 0xaaaaaaaa, |
| 4225 | 64 => 0xaaaaaaaa_aaaaaaaa, |
| 4302 | 4226 | else => unreachable, |
| 4303 | | }; |
| 4304 | | return int.constIntToPtr(llvm_ptr_ty); |
| 4227 | })); |
| 4228 | return int.toLlvm(&o.builder).constIntToPtr(llvm_ptr_ty); |
| 4305 | 4229 | } |
| 4306 | 4230 | |
| 4307 | 4231 | fn addAttr(o: *Object, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void { |
| ... | ... | @@ -5118,11 +5042,11 @@ pub const FuncGen = struct { |
| 5118 | 5042 | llvm_arg = store_inst; |
| 5119 | 5043 | } |
| 5120 | 5044 | |
| 5121 | | const float_ty = (try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, mod).?)).toLlvm(&o.builder); |
| 5122 | | const array_llvm_ty = float_ty.arrayType(count); |
| 5045 | const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, mod).?); |
| 5046 | const array_ty = try o.builder.arrayType(count, float_ty); |
| 5123 | 5047 | |
| 5124 | 5048 | const alignment = arg_ty.abiAlignment(mod); |
| 5125 | | const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, ""); |
| 5049 | const load_inst = self.builder.buildLoad(array_ty.toLlvm(&o.builder), llvm_arg, ""); |
| 5126 | 5050 | load_inst.setAlignment(alignment); |
| 5127 | 5051 | try llvm_args.append(load_inst); |
| 5128 | 5052 | }, |
| ... | ... | @@ -5138,9 +5062,9 @@ pub const FuncGen = struct { |
| 5138 | 5062 | llvm_arg = store_inst; |
| 5139 | 5063 | } |
| 5140 | 5064 | |
| 5141 | | const array_llvm_ty = (try o.builder.intType(@intCast(elem_size))).toLlvm(&o.builder).arrayType(arr_len); |
| 5065 | const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size))); |
| 5142 | 5066 | const alignment = arg_ty.abiAlignment(mod); |
| 5143 | | const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, ""); |
| 5067 | const load_inst = self.builder.buildLoad(array_ty.toLlvm(&o.builder), llvm_arg, ""); |
| 5144 | 5068 | load_inst.setAlignment(alignment); |
| 5145 | 5069 | try llvm_args.append(load_inst); |
| 5146 | 5070 | }, |
| ... | ... | @@ -5279,7 +5203,7 @@ pub const FuncGen = struct { |
| 5279 | 5203 | }); |
| 5280 | 5204 | const null_opt_addr_global = try o.getNullOptAddr(); |
| 5281 | 5205 | const target = mod.getTarget(); |
| 5282 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 5206 | const llvm_usize = try o.lowerType(Type.usize); |
| 5283 | 5207 | // example: |
| 5284 | 5208 | // call fastcc void @test2.panic( |
| 5285 | 5209 | // ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr |
| ... | ... | @@ -5289,7 +5213,7 @@ pub const FuncGen = struct { |
| 5289 | 5213 | // ) |
| 5290 | 5214 | const args = [4]*llvm.Value{ |
| 5291 | 5215 | msg_ptr, |
| 5292 | | llvm_usize.constInt(msg_len, .False), |
| 5216 | (try o.builder.intConst(llvm_usize, msg_len)).toLlvm(&o.builder), |
| 5293 | 5217 | fg.context.pointerType(0).constNull(), |
| 5294 | 5218 | null_opt_addr_global, |
| 5295 | 5219 | }; |
| ... | ... | @@ -5327,8 +5251,8 @@ pub const FuncGen = struct { |
| 5327 | 5251 | // Functions with an empty error set are emitted with an error code |
| 5328 | 5252 | // return type and return zero so they can be function pointers coerced |
| 5329 | 5253 | // to functions that return anyerror. |
| 5330 | | const err_int = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder); |
| 5331 | | _ = self.builder.buildRet(err_int.constInt(0, .False)); |
| 5254 | const int = try o.builder.intConst(Builder.Type.err_int, 0); |
| 5255 | _ = self.builder.buildRet(int.toLlvm(&o.builder)); |
| 5332 | 5256 | } else { |
| 5333 | 5257 | _ = self.builder.buildRetVoid(); |
| 5334 | 5258 | } |
| ... | ... | @@ -5375,8 +5299,8 @@ pub const FuncGen = struct { |
| 5375 | 5299 | // Functions with an empty error set are emitted with an error code |
| 5376 | 5300 | // return type and return zero so they can be function pointers coerced |
| 5377 | 5301 | // to functions that return anyerror. |
| 5378 | | const err_int = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder); |
| 5379 | | _ = self.builder.buildRet(err_int.constInt(0, .False)); |
| 5302 | const int = try o.builder.intConst(Builder.Type.err_int, 0); |
| 5303 | _ = self.builder.buildRet(int.toLlvm(&o.builder)); |
| 5380 | 5304 | } else { |
| 5381 | 5305 | _ = self.builder.buildRetVoid(); |
| 5382 | 5306 | } |
| ... | ... | @@ -5531,22 +5455,22 @@ pub const FuncGen = struct { |
| 5531 | 5455 | // of optionals that are not pointers. |
| 5532 | 5456 | const is_by_ref = isByRef(scalar_ty, mod); |
| 5533 | 5457 | const opt_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); |
| 5534 | | const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); |
| 5535 | | const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); |
| 5536 | | const llvm_i2 = (try o.builder.intType(2)).toLlvm(&o.builder); |
| 5537 | | const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2, ""); |
| 5538 | | const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2, ""); |
| 5539 | | const lhs_shifted = self.builder.buildShl(lhs_non_null_i2, llvm_i2.constInt(1, .False), ""); |
| 5458 | const lhs_non_null = try self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); |
| 5459 | const rhs_non_null = try self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); |
| 5460 | const llvm_i2 = try o.builder.intType(2); |
| 5461 | const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2.toLlvm(&o.builder), ""); |
| 5462 | const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2.toLlvm(&o.builder), ""); |
| 5463 | const lhs_shifted = self.builder.buildShl(lhs_non_null_i2, (try o.builder.intConst(llvm_i2, 1)).toLlvm(&o.builder), ""); |
| 5540 | 5464 | const lhs_rhs_ored = self.builder.buildOr(lhs_shifted, rhs_non_null_i2, ""); |
| 5541 | 5465 | const both_null_block = self.context.appendBasicBlock(self.llvm_func, "BothNull"); |
| 5542 | 5466 | const mixed_block = self.context.appendBasicBlock(self.llvm_func, "Mixed"); |
| 5543 | 5467 | const both_pl_block = self.context.appendBasicBlock(self.llvm_func, "BothNonNull"); |
| 5544 | 5468 | const end_block = self.context.appendBasicBlock(self.llvm_func, "End"); |
| 5545 | 5469 | const llvm_switch = self.builder.buildSwitch(lhs_rhs_ored, mixed_block, 2); |
| 5546 | | const llvm_i2_00 = llvm_i2.constInt(0b00, .False); |
| 5547 | | const llvm_i2_11 = llvm_i2.constInt(0b11, .False); |
| 5548 | | llvm_switch.addCase(llvm_i2_00, both_null_block); |
| 5549 | | llvm_switch.addCase(llvm_i2_11, both_pl_block); |
| 5470 | const llvm_i2_00 = try o.builder.intConst(llvm_i2, 0b00); |
| 5471 | const llvm_i2_11 = try o.builder.intConst(llvm_i2, 0b11); |
| 5472 | llvm_switch.addCase(llvm_i2_00.toLlvm(&o.builder), both_null_block); |
| 5473 | llvm_switch.addCase(llvm_i2_11.toLlvm(&o.builder), both_pl_block); |
| 5550 | 5474 | |
| 5551 | 5475 | self.builder.positionBuilderAtEnd(both_null_block); |
| 5552 | 5476 | _ = self.builder.buildBr(end_block); |
| ... | ... | @@ -5567,9 +5491,8 @@ pub const FuncGen = struct { |
| 5567 | 5491 | mixed_block, |
| 5568 | 5492 | both_pl_block_end, |
| 5569 | 5493 | }; |
| 5570 | | const llvm_i1 = Builder.Type.i1.toLlvm(&o.builder); |
| 5571 | | const llvm_i1_0 = llvm_i1.constInt(0, .False); |
| 5572 | | const llvm_i1_1 = llvm_i1.constInt(1, .False); |
| 5494 | const llvm_i1_0 = Builder.Constant.false.toLlvm(&o.builder); |
| 5495 | const llvm_i1_1 = Builder.Constant.true.toLlvm(&o.builder); |
| 5573 | 5496 | const incoming_values: [3]*llvm.Value = .{ |
| 5574 | 5497 | switch (op) { |
| 5575 | 5498 | .eq => llvm_i1_1, |
| ... | ... | @@ -5584,7 +5507,7 @@ pub const FuncGen = struct { |
| 5584 | 5507 | payload_cmp, |
| 5585 | 5508 | }; |
| 5586 | 5509 | |
| 5587 | | const phi_node = self.builder.buildPhi(llvm_i1, ""); |
| 5510 | const phi_node = self.builder.buildPhi(Builder.Type.i1.toLlvm(&o.builder), ""); |
| 5588 | 5511 | comptime assert(incoming_values.len == incoming_blocks.len); |
| 5589 | 5512 | phi_node.addIncoming( |
| 5590 | 5513 | &incoming_values, |
| ... | ... | @@ -5882,8 +5805,8 @@ pub const FuncGen = struct { |
| 5882 | 5805 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5883 | 5806 | const operand_ty = self.typeOf(ty_op.operand); |
| 5884 | 5807 | const array_ty = operand_ty.childType(mod); |
| 5885 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 5886 | | const len = llvm_usize.constInt(array_ty.arrayLen(mod), .False); |
| 5808 | const llvm_usize = try o.lowerType(Type.usize); |
| 5809 | const len = (try o.builder.intConst(llvm_usize, array_ty.arrayLen(mod))).toLlvm(&o.builder); |
| 5887 | 5810 | const slice_llvm_ty = (try o.lowerType(self.typeOfIndex(inst))).toLlvm(&o.builder); |
| 5888 | 5811 | const operand = try self.resolveInst(ty_op.operand); |
| 5889 | 5812 | if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| ... | ... | @@ -5891,8 +5814,8 @@ pub const FuncGen = struct { |
| 5891 | 5814 | return self.builder.buildInsertValue(partial, len, 1, ""); |
| 5892 | 5815 | } |
| 5893 | 5816 | const indices: [2]*llvm.Value = .{ |
| 5894 | | llvm_usize.constNull(), llvm_usize.constNull(), |
| 5895 | | }; |
| 5817 | (try o.builder.intConst(llvm_usize, 0)).toLlvm(&o.builder), |
| 5818 | } ** 2; |
| 5896 | 5819 | const array_llvm_ty = (try o.lowerType(array_ty)).toLlvm(&o.builder); |
| 5897 | 5820 | const ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indices, indices.len, ""); |
| 5898 | 5821 | const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, ""); |
| ... | ... | @@ -6024,21 +5947,21 @@ pub const FuncGen = struct { |
| 6024 | 5947 | fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: *llvm.Value, ty: Type) Allocator.Error!*llvm.Value { |
| 6025 | 5948 | const o = fg.dg.object; |
| 6026 | 5949 | const mod = o.module; |
| 6027 | | const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 5950 | const llvm_usize = try o.lowerType(Type.usize); |
| 6028 | 5951 | switch (ty.ptrSize(mod)) { |
| 6029 | 5952 | .Slice => { |
| 6030 | 5953 | const len = fg.builder.buildExtractValue(ptr, 1, ""); |
| 6031 | 5954 | const elem_ty = ty.childType(mod); |
| 6032 | 5955 | const abi_size = elem_ty.abiSize(mod); |
| 6033 | 5956 | if (abi_size == 1) return len; |
| 6034 | | const abi_size_llvm_val = llvm_usize_ty.constInt(abi_size, .False); |
| 6035 | | return fg.builder.buildMul(len, abi_size_llvm_val, ""); |
| 5957 | const abi_size_llvm_val = try o.builder.intConst(llvm_usize, abi_size); |
| 5958 | return fg.builder.buildMul(len, abi_size_llvm_val.toLlvm(&o.builder), ""); |
| 6036 | 5959 | }, |
| 6037 | 5960 | .One => { |
| 6038 | 5961 | const array_ty = ty.childType(mod); |
| 6039 | 5962 | const elem_ty = array_ty.childType(mod); |
| 6040 | 5963 | const abi_size = elem_ty.abiSize(mod); |
| 6041 | | return llvm_usize_ty.constInt(array_ty.arrayLen(mod) * abi_size, .False); |
| 5964 | return (try o.builder.intConst(llvm_usize, array_ty.arrayLen(mod) * abi_size)).toLlvm(&o.builder); |
| 6042 | 5965 | }, |
| 6043 | 5966 | .Many, .C => unreachable, |
| 6044 | 5967 | } |
| ... | ... | @@ -6340,10 +6263,10 @@ pub const FuncGen = struct { |
| 6340 | 6263 | if (field_offset == 0) { |
| 6341 | 6264 | return field_ptr; |
| 6342 | 6265 | } |
| 6343 | | const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 6266 | const llvm_usize = try o.lowerType(Type.usize); |
| 6344 | 6267 | |
| 6345 | | const field_ptr_int = self.builder.buildPtrToInt(field_ptr, llvm_usize_ty, ""); |
| 6346 | | const base_ptr_int = self.builder.buildNUWSub(field_ptr_int, llvm_usize_ty.constInt(field_offset, .False), ""); |
| 6268 | const field_ptr_int = self.builder.buildPtrToInt(field_ptr, llvm_usize.toLlvm(&o.builder), ""); |
| 6269 | const base_ptr_int = self.builder.buildNUWSub(field_ptr_int, (try o.builder.intConst(llvm_usize, field_offset)).toLlvm(&o.builder), ""); |
| 6347 | 6270 | return self.builder.buildIntToPtr(base_ptr_int, res_ty, ""); |
| 6348 | 6271 | } |
| 6349 | 6272 | |
| ... | ... | @@ -6919,12 +6842,11 @@ pub const FuncGen = struct { |
| 6919 | 6842 | self.builder.buildLoad(optional_llvm_ty, operand, "") |
| 6920 | 6843 | else |
| 6921 | 6844 | operand; |
| 6922 | | const llvm_i8 = Builder.Type.i8.toLlvm(&o.builder); |
| 6923 | | return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); |
| 6845 | return self.builder.buildICmp(pred, loaded, (try o.builder.intConst(.i8, 0)).toLlvm(&o.builder), ""); |
| 6924 | 6846 | } |
| 6925 | 6847 | |
| 6926 | 6848 | const is_by_ref = operand_is_ptr or isByRef(optional_ty, mod); |
| 6927 | | const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref); |
| 6849 | const non_null_bit = try self.optIsNonNull(optional_llvm_ty, operand, is_by_ref); |
| 6928 | 6850 | if (pred == .EQ) { |
| 6929 | 6851 | return self.builder.buildNot(non_null_bit, ""); |
| 6930 | 6852 | } else { |
| ... | ... | @@ -6949,12 +6871,12 @@ pub const FuncGen = struct { |
| 6949 | 6871 | const zero = err_set_ty.constNull(); |
| 6950 | 6872 | |
| 6951 | 6873 | if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) { |
| 6952 | | const llvm_i1 = Builder.Type.i1.toLlvm(&o.builder); |
| 6953 | | switch (op) { |
| 6954 | | .EQ => return llvm_i1.constInt(1, .False), // 0 == 0 |
| 6955 | | .NE => return llvm_i1.constInt(0, .False), // 0 != 0 |
| 6874 | const val: Builder.Constant = switch (op) { |
| 6875 | .EQ => .true, // 0 == 0 |
| 6876 | .NE => .false, // 0 != 0 |
| 6956 | 6877 | else => unreachable, |
| 6957 | | } |
| 6878 | }; |
| 6879 | return val.toLlvm(&o.builder); |
| 6958 | 6880 | } |
| 6959 | 6881 | |
| 6960 | 6882 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| ... | ... | @@ -7007,7 +6929,7 @@ pub const FuncGen = struct { |
| 7007 | 6929 | const operand = try self.resolveInst(ty_op.operand); |
| 7008 | 6930 | const optional_ty = self.typeOf(ty_op.operand).childType(mod); |
| 7009 | 6931 | const payload_ty = optional_ty.optionalChild(mod); |
| 7010 | | const non_null_bit = Builder.Type.i8.toLlvm(&o.builder).constInt(1, .False); |
| 6932 | const non_null_bit = (try o.builder.intConst(.i8, 1)).toLlvm(&o.builder); |
| 7011 | 6933 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 7012 | 6934 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. |
| 7013 | 6935 | _ = self.builder.buildStore(non_null_bit, operand); |
| ... | ... | @@ -7101,11 +7023,10 @@ pub const FuncGen = struct { |
| 7101 | 7023 | const operand_ty = self.typeOf(ty_op.operand); |
| 7102 | 7024 | const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty; |
| 7103 | 7025 | if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) { |
| 7104 | | const err_llvm_ty = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder); |
| 7105 | 7026 | if (operand_is_ptr) { |
| 7106 | 7027 | return operand; |
| 7107 | 7028 | } else { |
| 7108 | | return err_llvm_ty.constInt(0, .False); |
| 7029 | return (try o.builder.intConst(Builder.Type.err_int, 0)).toLlvm(&o.builder); |
| 7109 | 7030 | } |
| 7110 | 7031 | } |
| 7111 | 7032 | |
| ... | ... | @@ -7193,7 +7114,7 @@ pub const FuncGen = struct { |
| 7193 | 7114 | const mod = o.module; |
| 7194 | 7115 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 7195 | 7116 | const payload_ty = self.typeOf(ty_op.operand); |
| 7196 | | const non_null_bit = Builder.Type.i8.toLlvm(&o.builder).constInt(1, .False); |
| 7117 | const non_null_bit = (try o.builder.intConst(.i8, 1)).toLlvm(&o.builder); |
| 7197 | 7118 | comptime assert(optional_layout_version == 3); |
| 7198 | 7119 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return non_null_bit; |
| 7199 | 7120 | const operand = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -7278,22 +7199,24 @@ pub const FuncGen = struct { |
| 7278 | 7199 | } |
| 7279 | 7200 | |
| 7280 | 7201 | fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7202 | const o = self.dg.object; |
| 7281 | 7203 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 7282 | 7204 | const index = pl_op.payload; |
| 7283 | | const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 7284 | 7205 | const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.size", &.{.i32}); |
| 7285 | | const args: [1]*llvm.Value = .{llvm_u32.constInt(index, .False)}; |
| 7206 | const args: [1]*llvm.Value = .{ |
| 7207 | (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), |
| 7208 | }; |
| 7286 | 7209 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 7287 | 7210 | } |
| 7288 | 7211 | |
| 7289 | 7212 | fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7213 | const o = self.dg.object; |
| 7290 | 7214 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 7291 | 7215 | const index = pl_op.payload; |
| 7292 | 7216 | const operand = try self.resolveInst(pl_op.operand); |
| 7293 | | const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 7294 | 7217 | const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.grow", &.{.i32}); |
| 7295 | 7218 | const args: [2]*llvm.Value = .{ |
| 7296 | | llvm_u32.constInt(index, .False), |
| 7219 | (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), |
| 7297 | 7220 | operand, |
| 7298 | 7221 | }; |
| 7299 | 7222 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| ... | ... | @@ -7571,24 +7494,23 @@ pub const FuncGen = struct { |
| 7571 | 7494 | return self.buildFloatOp(.floor, inst_ty, 1, .{result}); |
| 7572 | 7495 | } |
| 7573 | 7496 | if (scalar_ty.isSignedInt(mod)) { |
| 7574 | | const inst_llvm_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder); |
| 7497 | const inst_llvm_ty = try o.lowerType(inst_ty); |
| 7575 | 7498 | const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1; |
| 7576 | 7499 | const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: { |
| 7577 | 7500 | const vec_len = inst_ty.vectorLen(mod); |
| 7578 | | const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); |
| 7579 | 7501 | |
| 7580 | 7502 | const shifts = try self.gpa.alloc(*llvm.Value, vec_len); |
| 7581 | 7503 | defer self.gpa.free(shifts); |
| 7582 | 7504 | |
| 7583 | | @memset(shifts, scalar_llvm_ty.constInt(scalar_bit_size_minus_one, .False)); |
| 7505 | @memset(shifts, (try o.builder.intConst(try o.lowerType(scalar_ty), scalar_bit_size_minus_one)).toLlvm(&o.builder)); |
| 7584 | 7506 | break :const_vector llvm.constVector(shifts.ptr, vec_len); |
| 7585 | | } else inst_llvm_ty.constInt(scalar_bit_size_minus_one, .False); |
| 7507 | } else (try o.builder.intConst(inst_llvm_ty, scalar_bit_size_minus_one)).toLlvm(&o.builder); |
| 7586 | 7508 | |
| 7587 | 7509 | const div = self.builder.buildSDiv(lhs, rhs, ""); |
| 7588 | 7510 | const rem = self.builder.buildSRem(lhs, rhs, ""); |
| 7589 | 7511 | const div_sign = self.builder.buildXor(lhs, rhs, ""); |
| 7590 | 7512 | const div_sign_mask = self.builder.buildAShr(div_sign, bit_size_minus_one, ""); |
| 7591 | | const zero = inst_llvm_ty.constNull(); |
| 7513 | const zero = inst_llvm_ty.toLlvm(&o.builder).constNull(); |
| 7592 | 7514 | const rem_nonzero = self.builder.buildICmp(.NE, rem, zero, ""); |
| 7593 | 7515 | const correction = self.builder.buildSelect(rem_nonzero, div_sign_mask, zero, ""); |
| 7594 | 7516 | return self.builder.buildNSWAdd(div, correction, ""); |
| ... | ... | @@ -7637,14 +7559,14 @@ pub const FuncGen = struct { |
| 7637 | 7559 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7638 | 7560 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7639 | 7561 | const inst_ty = self.typeOfIndex(inst); |
| 7640 | | const inst_llvm_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder); |
| 7562 | const inst_llvm_ty = try o.lowerType(inst_ty); |
| 7641 | 7563 | const scalar_ty = inst_ty.scalarType(mod); |
| 7642 | 7564 | |
| 7643 | 7565 | if (scalar_ty.isRuntimeFloat()) { |
| 7644 | 7566 | const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs }); |
| 7645 | 7567 | const b = try self.buildFloatOp(.add, inst_ty, 2, .{ a, rhs }); |
| 7646 | 7568 | const c = try self.buildFloatOp(.fmod, inst_ty, 2, .{ b, rhs }); |
| 7647 | | const zero = inst_llvm_ty.constNull(); |
| 7569 | const zero = inst_llvm_ty.toLlvm(&o.builder).constNull(); |
| 7648 | 7570 | const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero }); |
| 7649 | 7571 | return self.builder.buildSelect(ltz, c, a, ""); |
| 7650 | 7572 | } |
| ... | ... | @@ -7652,20 +7574,19 @@ pub const FuncGen = struct { |
| 7652 | 7574 | const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1; |
| 7653 | 7575 | const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: { |
| 7654 | 7576 | const vec_len = inst_ty.vectorLen(mod); |
| 7655 | | const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); |
| 7656 | 7577 | |
| 7657 | 7578 | const shifts = try self.gpa.alloc(*llvm.Value, vec_len); |
| 7658 | 7579 | defer self.gpa.free(shifts); |
| 7659 | 7580 | |
| 7660 | | @memset(shifts, scalar_llvm_ty.constInt(scalar_bit_size_minus_one, .False)); |
| 7581 | @memset(shifts, (try o.builder.intConst(try o.lowerType(scalar_ty), scalar_bit_size_minus_one)).toLlvm(&o.builder)); |
| 7661 | 7582 | break :const_vector llvm.constVector(shifts.ptr, vec_len); |
| 7662 | | } else inst_llvm_ty.constInt(scalar_bit_size_minus_one, .False); |
| 7583 | } else (try o.builder.intConst(inst_llvm_ty, scalar_bit_size_minus_one)).toLlvm(&o.builder); |
| 7663 | 7584 | |
| 7664 | 7585 | const rem = self.builder.buildSRem(lhs, rhs, ""); |
| 7665 | 7586 | const div_sign = self.builder.buildXor(lhs, rhs, ""); |
| 7666 | 7587 | const div_sign_mask = self.builder.buildAShr(div_sign, bit_size_minus_one, ""); |
| 7667 | 7588 | const rhs_masked = self.builder.buildAnd(rhs, div_sign_mask, ""); |
| 7668 | | const zero = inst_llvm_ty.constNull(); |
| 7589 | const zero = inst_llvm_ty.toLlvm(&o.builder).constNull(); |
| 7669 | 7590 | const rem_nonzero = self.builder.buildICmp(.NE, rem, zero, ""); |
| 7670 | 7591 | const correction = self.builder.buildSelect(rem_nonzero, rhs_masked, zero, ""); |
| 7671 | 7592 | return self.builder.buildNSWAdd(rem, correction, ""); |
| ... | ... | @@ -7789,14 +7710,14 @@ pub const FuncGen = struct { |
| 7789 | 7710 | result_vector: *llvm.Value, |
| 7790 | 7711 | vector_len: usize, |
| 7791 | 7712 | ) !*llvm.Value { |
| 7713 | const o = self.dg.object; |
| 7792 | 7714 | const args_len = @as(c_uint, @intCast(args_vectors.len)); |
| 7793 | | const llvm_i32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 7794 | 7715 | assert(args_len <= 3); |
| 7795 | 7716 | |
| 7796 | 7717 | var i: usize = 0; |
| 7797 | 7718 | var result = result_vector; |
| 7798 | 7719 | while (i < vector_len) : (i += 1) { |
| 7799 | | const index_i32 = llvm_i32.constInt(i, .False); |
| 7720 | const index_i32 = (try o.builder.intConst(.i32, i)).toLlvm(&o.builder); |
| 7800 | 7721 | |
| 7801 | 7722 | var args: [3]*llvm.Value = undefined; |
| 7802 | 7723 | for (args_vectors, 0..) |arg_vector, k| { |
| ... | ... | @@ -7882,7 +7803,7 @@ pub const FuncGen = struct { |
| 7882 | 7803 | .i32, |
| 7883 | 7804 | ); |
| 7884 | 7805 | |
| 7885 | | const zero = Builder.Type.i32.toLlvm(&o.builder).constInt(0, .False); |
| 7806 | const zero = (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder); |
| 7886 | 7807 | const int_pred: llvm.IntPredicate = switch (pred) { |
| 7887 | 7808 | .eq => .EQ, |
| 7888 | 7809 | .neq => .NE, |
| ... | ... | @@ -7973,17 +7894,17 @@ pub const FuncGen = struct { |
| 7973 | 7894 | .neg => { |
| 7974 | 7895 | // In this case we can generate a softfloat negation by XORing the |
| 7975 | 7896 | // bits with a constant. |
| 7976 | | const int_llvm_ty = (try o.builder.intType(@intCast(float_bits))).toLlvm(&o.builder); |
| 7977 | | const one = int_llvm_ty.constInt(1, .False); |
| 7978 | | const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False); |
| 7979 | | const sign_mask = one.constShl(shift_amt); |
| 7897 | const int_ty = try o.builder.intType(@intCast(float_bits)); |
| 7898 | const one = (try o.builder.intConst(int_ty, 1)).toLlvm(&o.builder); |
| 7899 | const shift_amt = try o.builder.intConst(int_ty, float_bits - 1); |
| 7900 | const sign_mask = one.constShl(shift_amt.toLlvm(&o.builder)); |
| 7980 | 7901 | const result = if (ty.zigTypeTag(mod) == .Vector) blk: { |
| 7981 | 7902 | const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(mod), sign_mask, ""); |
| 7982 | | const cast_ty = int_llvm_ty.vectorType(ty.vectorLen(mod)); |
| 7983 | | const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty, ""); |
| 7903 | const cast_ty = try o.builder.vectorType(.normal, ty.vectorLen(mod), int_ty); |
| 7904 | const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty.toLlvm(&o.builder), ""); |
| 7984 | 7905 | break :blk self.builder.buildXor(bitcasted_operand, splat_sign_mask, ""); |
| 7985 | 7906 | } else blk: { |
| 7986 | | const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, ""); |
| 7907 | const bitcasted_operand = self.builder.buildBitCast(params[0], int_ty.toLlvm(&o.builder), ""); |
| 7987 | 7908 | break :blk self.builder.buildXor(bitcasted_operand, sign_mask, ""); |
| 7988 | 7909 | }; |
| 7989 | 7910 | return self.builder.buildBitCast(result, llvm_ty.toLlvm(&o.builder), ""); |
| ... | ... | @@ -8191,9 +8112,9 @@ pub const FuncGen = struct { |
| 8191 | 8112 | // poison value." |
| 8192 | 8113 | // However Zig semantics says that saturating shift left can never produce |
| 8193 | 8114 | // undefined; instead it saturates. |
| 8194 | | const lhs_scalar_llvm_ty = (try o.lowerType(lhs_scalar_ty)).toLlvm(&o.builder); |
| 8195 | | const bits = lhs_scalar_llvm_ty.constInt(lhs_bits, .False); |
| 8196 | | const lhs_max = lhs_scalar_llvm_ty.constAllOnes(); |
| 8115 | const lhs_scalar_llvm_ty = try o.lowerType(lhs_scalar_ty); |
| 8116 | const bits = (try o.builder.intConst(lhs_scalar_llvm_ty, lhs_bits)).toLlvm(&o.builder); |
| 8117 | const lhs_max = (try o.builder.intConst(lhs_scalar_llvm_ty, -1)).toLlvm(&o.builder); |
| 8197 | 8118 | if (rhs_ty.zigTypeTag(mod) == .Vector) { |
| 8198 | 8119 | const vec_len = rhs_ty.vectorLen(mod); |
| 8199 | 8120 | const bits_vec = self.builder.buildVectorSplat(vec_len, bits, ""); |
| ... | ... | @@ -8382,17 +8303,19 @@ pub const FuncGen = struct { |
| 8382 | 8303 | } else { |
| 8383 | 8304 | // If the ABI size of the element type is not evenly divisible by size in bits; |
| 8384 | 8305 | // a simple bitcast will not work, and we fall back to extractelement. |
| 8385 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 8386 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 8387 | | const zero = llvm_usize.constNull(); |
| 8306 | const llvm_usize = try o.lowerType(Type.usize); |
| 8307 | const zero = try o.builder.intConst(llvm_usize, 0); |
| 8388 | 8308 | const vector_len = operand_ty.arrayLen(mod); |
| 8389 | 8309 | var i: u64 = 0; |
| 8390 | 8310 | while (i < vector_len) : (i += 1) { |
| 8391 | | const index_usize = llvm_usize.constInt(i, .False); |
| 8392 | | const index_u32 = llvm_u32.constInt(i, .False); |
| 8393 | | const indexes: [2]*llvm.Value = .{ zero, index_usize }; |
| 8311 | const index_usize = try o.builder.intConst(llvm_usize, i); |
| 8312 | const index_u32 = try o.builder.intConst(.i32, i); |
| 8313 | const indexes: [2]*llvm.Value = .{ |
| 8314 | zero.toLlvm(&o.builder), |
| 8315 | index_usize.toLlvm(&o.builder), |
| 8316 | }; |
| 8394 | 8317 | const elem_ptr = self.builder.buildInBoundsGEP(llvm_dest_ty, array_ptr, &indexes, indexes.len, ""); |
| 8395 | | const elem = self.builder.buildExtractElement(operand, index_u32, ""); |
| 8318 | const elem = self.builder.buildExtractElement(operand, index_u32.toLlvm(&o.builder), ""); |
| 8396 | 8319 | _ = self.builder.buildStore(elem, elem_ptr); |
| 8397 | 8320 | } |
| 8398 | 8321 | } |
| ... | ... | @@ -8416,19 +8339,21 @@ pub const FuncGen = struct { |
| 8416 | 8339 | // a simple bitcast will not work, and we fall back to extractelement. |
| 8417 | 8340 | const array_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); |
| 8418 | 8341 | const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 8419 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 8420 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 8421 | | const zero = llvm_usize.constNull(); |
| 8342 | const llvm_usize = try o.lowerType(Type.usize); |
| 8343 | const zero = try o.builder.intConst(llvm_usize, 0); |
| 8422 | 8344 | const vector_len = operand_ty.arrayLen(mod); |
| 8423 | 8345 | var vector = llvm_vector_ty.getUndef(); |
| 8424 | 8346 | var i: u64 = 0; |
| 8425 | 8347 | while (i < vector_len) : (i += 1) { |
| 8426 | | const index_usize = llvm_usize.constInt(i, .False); |
| 8427 | | const index_u32 = llvm_u32.constInt(i, .False); |
| 8428 | | const indexes: [2]*llvm.Value = .{ zero, index_usize }; |
| 8348 | const index_usize = try o.builder.intConst(llvm_usize, i); |
| 8349 | const index_u32 = try o.builder.intConst(.i32, i); |
| 8350 | const indexes: [2]*llvm.Value = .{ |
| 8351 | zero.toLlvm(&o.builder), |
| 8352 | index_usize.toLlvm(&o.builder), |
| 8353 | }; |
| 8429 | 8354 | const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indexes, indexes.len, ""); |
| 8430 | 8355 | const elem = self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); |
| 8431 | | vector = self.builder.buildInsertElement(vector, elem, index_u32, ""); |
| 8356 | vector = self.builder.buildInsertElement(vector, elem, index_u32.toLlvm(&o.builder), ""); |
| 8432 | 8357 | } |
| 8433 | 8358 | |
| 8434 | 8359 | return vector; |
| ... | ... | @@ -8563,14 +8488,13 @@ pub const FuncGen = struct { |
| 8563 | 8488 | // Even if safety is disabled, we still emit a memset to undefined since it conveys |
| 8564 | 8489 | // extra information to LLVM. However, safety makes the difference between using |
| 8565 | 8490 | // 0xaa or actual undefined for the fill byte. |
| 8566 | | const u8_llvm_ty = Builder.Type.i8.toLlvm(&o.builder); |
| 8567 | 8491 | const fill_byte = if (safety) |
| 8568 | | u8_llvm_ty.constInt(0xaa, .False) |
| 8492 | (try o.builder.intConst(.i8, 0xaa)).toLlvm(&o.builder) |
| 8569 | 8493 | else |
| 8570 | | u8_llvm_ty.getUndef(); |
| 8494 | Builder.Type.i8.toLlvm(&o.builder).getUndef(); |
| 8571 | 8495 | const operand_size = operand_ty.abiSize(mod); |
| 8572 | | const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 8573 | | const len = usize_llvm_ty.constInt(operand_size, .False); |
| 8496 | const usize_ty = try o.lowerType(Type.usize); |
| 8497 | const len = (try o.builder.intConst(usize_ty, operand_size)).toLlvm(&o.builder); |
| 8574 | 8498 | const dest_ptr_align = ptr_ty.ptrAlignment(mod); |
| 8575 | 8499 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr(mod)); |
| 8576 | 8500 | if (safety and mod.comp.bin_file.options.valgrind) { |
| ... | ... | @@ -8855,7 +8779,6 @@ pub const FuncGen = struct { |
| 8855 | 8779 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 8856 | 8780 | const elem_ty = self.typeOf(bin_op.rhs); |
| 8857 | 8781 | const dest_ptr_align = ptr_ty.ptrAlignment(mod); |
| 8858 | | const u8_llvm_ty = Builder.Type.i8.toLlvm(&o.builder); |
| 8859 | 8782 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty); |
| 8860 | 8783 | const is_volatile = ptr_ty.isVolatilePtr(mod); |
| 8861 | 8784 | |
| ... | ... | @@ -8873,9 +8796,9 @@ pub const FuncGen = struct { |
| 8873 | 8796 | // extra information to LLVM. However, safety makes the difference between using |
| 8874 | 8797 | // 0xaa or actual undefined for the fill byte. |
| 8875 | 8798 | const fill_byte = if (safety) |
| 8876 | | u8_llvm_ty.constInt(0xaa, .False) |
| 8799 | (try o.builder.intConst(.i8, 0xaa)).toLlvm(&o.builder) |
| 8877 | 8800 | else |
| 8878 | | u8_llvm_ty.getUndef(); |
| 8801 | Builder.Type.i8.toLlvm(&o.builder).getUndef(); |
| 8879 | 8802 | const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8880 | 8803 | if (intrinsic_len0_traps) { |
| 8881 | 8804 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| ... | ... | @@ -8946,10 +8869,10 @@ pub const FuncGen = struct { |
| 8946 | 8869 | const body_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetBody"); |
| 8947 | 8870 | const end_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetEnd"); |
| 8948 | 8871 | |
| 8949 | | const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 8872 | const usize_ty = try o.lowerType(Type.usize); |
| 8950 | 8873 | const len = switch (ptr_ty.ptrSize(mod)) { |
| 8951 | 8874 | .Slice => self.builder.buildExtractValue(dest_slice, 1, ""), |
| 8952 | | .One => llvm_usize_ty.constInt(ptr_ty.childType(mod).arrayLen(mod), .False), |
| 8875 | .One => (try o.builder.intConst(usize_ty, ptr_ty.childType(mod).arrayLen(mod))).toLlvm(&o.builder), |
| 8953 | 8876 | .Many, .C => unreachable, |
| 8954 | 8877 | }; |
| 8955 | 8878 | const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| ... | ... | @@ -8971,7 +8894,7 @@ pub const FuncGen = struct { |
| 8971 | 8894 | it_ptr_alignment, |
| 8972 | 8895 | value, |
| 8973 | 8896 | elem_abi_alignment, |
| 8974 | | llvm_usize_ty.constInt(elem_abi_size, .False), |
| 8897 | (try o.builder.intConst(usize_ty, elem_abi_size)).toLlvm(&o.builder), |
| 8975 | 8898 | is_volatile, |
| 8976 | 8899 | ); |
| 8977 | 8900 | } else { |
| ... | ... | @@ -8979,7 +8902,9 @@ pub const FuncGen = struct { |
| 8979 | 8902 | store_inst.setAlignment(it_ptr_alignment); |
| 8980 | 8903 | store_inst.setVolatile(llvm.Bool.fromBool(is_volatile)); |
| 8981 | 8904 | } |
| 8982 | | const one_gep = [_]*llvm.Value{llvm_usize_ty.constInt(1, .False)}; |
| 8905 | const one_gep = [_]*llvm.Value{ |
| 8906 | (try o.builder.intConst(usize_ty, 1)).toLlvm(&o.builder), |
| 8907 | }; |
| 8983 | 8908 | const next_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, it_ptr, &one_gep, one_gep.len, ""); |
| 8984 | 8909 | _ = self.builder.buildBr(loop_block); |
| 8985 | 8910 | |
| ... | ... | @@ -9194,24 +9119,20 @@ pub const FuncGen = struct { |
| 9194 | 9119 | // If not an even byte-multiple, we need zero-extend + shift-left 1 byte |
| 9195 | 9120 | // The truncated result at the end will be the correct bswap |
| 9196 | 9121 | const scalar_ty = try o.builder.intType(@intCast(bits + 8)); |
| 9197 | | const scalar_llvm_ty = scalar_ty.toLlvm(&o.builder); |
| 9198 | 9122 | if (operand_ty.zigTypeTag(mod) == .Vector) { |
| 9199 | 9123 | const vec_len = operand_ty.vectorLen(mod); |
| 9200 | 9124 | operand_llvm_ty = try o.builder.vectorType(.normal, vec_len, scalar_ty); |
| 9201 | 9125 | |
| 9202 | 9126 | const shifts = try self.gpa.alloc(*llvm.Value, vec_len); |
| 9203 | 9127 | defer self.gpa.free(shifts); |
| 9204 | | |
| 9205 | | for (shifts) |*elem| { |
| 9206 | | elem.* = scalar_llvm_ty.constInt(8, .False); |
| 9207 | | } |
| 9128 | @memset(shifts, (try o.builder.intConst(scalar_ty, 8)).toLlvm(&o.builder)); |
| 9208 | 9129 | const shift_vec = llvm.constVector(shifts.ptr, vec_len); |
| 9209 | 9130 | |
| 9210 | 9131 | const extended = self.builder.buildZExt(operand, operand_llvm_ty.toLlvm(&o.builder), ""); |
| 9211 | 9132 | operand = self.builder.buildShl(extended, shift_vec, ""); |
| 9212 | 9133 | } else { |
| 9213 | | const extended = self.builder.buildZExt(operand, scalar_llvm_ty, ""); |
| 9214 | | operand = self.builder.buildShl(extended, scalar_llvm_ty.constInt(8, .False), ""); |
| 9134 | const extended = self.builder.buildZExt(operand, scalar_ty.toLlvm(&o.builder), ""); |
| 9135 | operand = self.builder.buildShl(extended, (try o.builder.intConst(scalar_ty, 8)).toLlvm(&o.builder), ""); |
| 9215 | 9136 | operand_llvm_ty = scalar_ty; |
| 9216 | 9137 | } |
| 9217 | 9138 | bits = bits + 8; |
| ... | ... | @@ -9263,14 +9184,14 @@ pub const FuncGen = struct { |
| 9263 | 9184 | |
| 9264 | 9185 | self.builder.positionBuilderAtEnd(end_block); |
| 9265 | 9186 | |
| 9266 | | const llvm_type = Builder.Type.i1.toLlvm(&o.builder); |
| 9267 | 9187 | const incoming_values: [2]*llvm.Value = .{ |
| 9268 | | llvm_type.constInt(1, .False), llvm_type.constInt(0, .False), |
| 9188 | Builder.Constant.true.toLlvm(&o.builder), |
| 9189 | Builder.Constant.false.toLlvm(&o.builder), |
| 9269 | 9190 | }; |
| 9270 | 9191 | const incoming_blocks: [2]*llvm.BasicBlock = .{ |
| 9271 | 9192 | valid_block, invalid_block, |
| 9272 | 9193 | }; |
| 9273 | | const phi_node = self.builder.buildPhi(llvm_type, ""); |
| 9194 | const phi_node = self.builder.buildPhi(Builder.Type.i1.toLlvm(&o.builder), ""); |
| 9274 | 9195 | phi_node.addIncoming(&incoming_values, &incoming_blocks, 2); |
| 9275 | 9196 | return phi_node; |
| 9276 | 9197 | } |
| ... | ... | @@ -9346,10 +9267,10 @@ pub const FuncGen = struct { |
| 9346 | 9267 | switch_instr.addCase(this_tag_int_value, named_block); |
| 9347 | 9268 | } |
| 9348 | 9269 | self.builder.positionBuilderAtEnd(named_block); |
| 9349 | | _ = self.builder.buildRet(Builder.Type.i1.toLlvm(&o.builder).constInt(1, .False)); |
| 9270 | _ = self.builder.buildRet(Builder.Constant.true.toLlvm(&o.builder)); |
| 9350 | 9271 | |
| 9351 | 9272 | self.builder.positionBuilderAtEnd(unnamed_block); |
| 9352 | | _ = self.builder.buildRet(Builder.Type.i1.toLlvm(&o.builder).constInt(0, .False)); |
| 9273 | _ = self.builder.buildRet(Builder.Constant.false.toLlvm(&o.builder)); |
| 9353 | 9274 | |
| 9354 | 9275 | try o.builder.llvm_globals.append(self.gpa, fn_val); |
| 9355 | 9276 | _ = try o.builder.addGlobal(llvm_fn_name, global); |
| ... | ... | @@ -9384,7 +9305,7 @@ pub const FuncGen = struct { |
| 9384 | 9305 | const slice_ty = Type.slice_const_u8_sentinel_0; |
| 9385 | 9306 | const ret_ty = try o.lowerType(slice_ty); |
| 9386 | 9307 | const llvm_ret_ty = ret_ty.toLlvm(&o.builder); |
| 9387 | | const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 9308 | const usize_ty = try o.lowerType(Type.usize); |
| 9388 | 9309 | const slice_alignment = slice_ty.abiAlignment(mod); |
| 9389 | 9310 | |
| 9390 | 9311 | const fn_type = try o.builder.fnType(ret_ty, &.{ |
| ... | ... | @@ -9421,9 +9342,9 @@ pub const FuncGen = struct { |
| 9421 | 9342 | const tag_int_value = fn_val.getParam(0); |
| 9422 | 9343 | const switch_instr = self.builder.buildSwitch(tag_int_value, bad_value_block, @as(c_uint, @intCast(enum_type.names.len))); |
| 9423 | 9344 | |
| 9424 | | const array_ptr_indices = [_]*llvm.Value{ |
| 9425 | | usize_llvm_ty.constNull(), usize_llvm_ty.constNull(), |
| 9426 | | }; |
| 9345 | const array_ptr_indices: [2]*llvm.Value = .{ |
| 9346 | (try o.builder.intConst(usize_ty, 0)).toLlvm(&o.builder), |
| 9347 | } ** 2; |
| 9427 | 9348 | |
| 9428 | 9349 | for (enum_type.names, 0..) |name_ip, field_index_usize| { |
| 9429 | 9350 | const field_index = @as(u32, @intCast(field_index_usize)); |
| ... | ... | @@ -9439,7 +9360,7 @@ pub const FuncGen = struct { |
| 9439 | 9360 | |
| 9440 | 9361 | const slice_fields = [_]*llvm.Value{ |
| 9441 | 9362 | str_init_llvm_ty.constInBoundsGEP(str_global, &array_ptr_indices, array_ptr_indices.len), |
| 9442 | | usize_llvm_ty.constInt(name.len, .False), |
| 9363 | (try o.builder.intConst(usize_ty, name.len)).toLlvm(&o.builder), |
| 9443 | 9364 | }; |
| 9444 | 9365 | const slice_init = llvm_ret_ty.constNamedStruct(&slice_fields, slice_fields.len); |
| 9445 | 9366 | const slice_global = o.llvm_module.addGlobal(slice_init.typeOf(), ""); |
| ... | ... | @@ -9555,16 +9476,14 @@ pub const FuncGen = struct { |
| 9555 | 9476 | const values = try self.gpa.alloc(*llvm.Value, mask_len); |
| 9556 | 9477 | defer self.gpa.free(values); |
| 9557 | 9478 | |
| 9558 | | const llvm_i32 = Builder.Type.i32.toLlvm(&o.builder); |
| 9559 | | |
| 9560 | 9479 | for (values, 0..) |*val, i| { |
| 9561 | 9480 | const elem = try mask.elemValue(mod, i); |
| 9562 | 9481 | if (elem.isUndef(mod)) { |
| 9563 | | val.* = llvm_i32.getUndef(); |
| 9482 | val.* = Builder.Type.i32.toLlvm(&o.builder).getUndef(); |
| 9564 | 9483 | } else { |
| 9565 | 9484 | const int = elem.toSignedInt(mod); |
| 9566 | 9485 | const unsigned = if (int >= 0) @as(u32, @intCast(int)) else @as(u32, @intCast(~int + a_len)); |
| 9567 | | val.* = llvm_i32.constInt(unsigned, .False); |
| 9486 | val.* = (try o.builder.intConst(.i32, unsigned)).toLlvm(&o.builder); |
| 9568 | 9487 | } |
| 9569 | 9488 | } |
| 9570 | 9489 | |
| ... | ... | @@ -9592,13 +9511,13 @@ pub const FuncGen = struct { |
| 9592 | 9511 | accum_init: *llvm.Value, |
| 9593 | 9512 | ) !*llvm.Value { |
| 9594 | 9513 | const o = self.dg.object; |
| 9595 | | const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 9596 | | const llvm_vector_len = llvm_usize_ty.constInt(vector_len, .False); |
| 9514 | const usize_ty = try o.lowerType(Type.usize); |
| 9515 | const llvm_vector_len = try o.builder.intConst(usize_ty, vector_len); |
| 9597 | 9516 | const llvm_result_ty = accum_init.typeOf(); |
| 9598 | 9517 | |
| 9599 | 9518 | // Allocate and initialize our mutable variables |
| 9600 | | const i_ptr = try self.buildAlloca(llvm_usize_ty, null); |
| 9601 | | _ = self.builder.buildStore(llvm_usize_ty.constInt(0, .False), i_ptr); |
| 9519 | const i_ptr = try self.buildAlloca(usize_ty.toLlvm(&o.builder), null); |
| 9520 | _ = self.builder.buildStore((try o.builder.intConst(usize_ty, 0)).toLlvm(&o.builder), i_ptr); |
| 9602 | 9521 | const accum_ptr = try self.buildAlloca(llvm_result_ty, null); |
| 9603 | 9522 | _ = self.builder.buildStore(accum_init, accum_ptr); |
| 9604 | 9523 | |
| ... | ... | @@ -9610,8 +9529,8 @@ pub const FuncGen = struct { |
| 9610 | 9529 | self.builder.positionBuilderAtEnd(loop); |
| 9611 | 9530 | |
| 9612 | 9531 | // while (i < vec.len) |
| 9613 | | const i = self.builder.buildLoad(llvm_usize_ty, i_ptr, ""); |
| 9614 | | const cond = self.builder.buildICmp(.ULT, i, llvm_vector_len, ""); |
| 9532 | const i = self.builder.buildLoad(usize_ty.toLlvm(&o.builder), i_ptr, ""); |
| 9533 | const cond = self.builder.buildICmp(.ULT, i, llvm_vector_len.toLlvm(&o.builder), ""); |
| 9615 | 9534 | const loop_then = self.context.appendBasicBlock(self.llvm_func, "ReduceLoopThen"); |
| 9616 | 9535 | |
| 9617 | 9536 | _ = self.builder.buildCondBr(cond, loop_then, loop_exit); |
| ... | ... | @@ -9627,7 +9546,7 @@ pub const FuncGen = struct { |
| 9627 | 9546 | _ = self.builder.buildStore(new_accum, accum_ptr); |
| 9628 | 9547 | |
| 9629 | 9548 | // i += 1 |
| 9630 | | const new_i = self.builder.buildAdd(i, llvm_usize_ty.constInt(1, .False), ""); |
| 9549 | const new_i = self.builder.buildAdd(i, (try o.builder.intConst(usize_ty, 1)).toLlvm(&o.builder), ""); |
| 9631 | 9550 | _ = self.builder.buildStore(new_i, i_ptr); |
| 9632 | 9551 | _ = self.builder.buildBr(loop); |
| 9633 | 9552 | } |
| ... | ... | @@ -9731,13 +9650,11 @@ pub const FuncGen = struct { |
| 9731 | 9650 | |
| 9732 | 9651 | switch (result_ty.zigTypeTag(mod)) { |
| 9733 | 9652 | .Vector => { |
| 9734 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 9735 | | |
| 9736 | 9653 | var vector = llvm_result_ty.getUndef(); |
| 9737 | 9654 | for (elements, 0..) |elem, i| { |
| 9738 | | const index_u32 = llvm_u32.constInt(i, .False); |
| 9655 | const index_u32 = try o.builder.intConst(.i32, i); |
| 9739 | 9656 | const llvm_elem = try self.resolveInst(elem); |
| 9740 | | vector = self.builder.buildInsertElement(vector, llvm_elem, index_u32, ""); |
| 9657 | vector = self.builder.buildInsertElement(vector, llvm_elem, index_u32.toLlvm(&o.builder), ""); |
| 9741 | 9658 | } |
| 9742 | 9659 | return vector; |
| 9743 | 9660 | }, |
| ... | ... | @@ -9746,10 +9663,10 @@ pub const FuncGen = struct { |
| 9746 | 9663 | const struct_obj = mod.typeToStruct(result_ty).?; |
| 9747 | 9664 | assert(struct_obj.haveLayout()); |
| 9748 | 9665 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); |
| 9749 | | const int_llvm_ty = (try o.builder.intType(@intCast(big_bits))).toLlvm(&o.builder); |
| 9666 | const int_ty = try o.builder.intType(@intCast(big_bits)); |
| 9750 | 9667 | const fields = struct_obj.fields.values(); |
| 9751 | 9668 | comptime assert(Type.packed_struct_layout_version == 2); |
| 9752 | | var running_int: *llvm.Value = int_llvm_ty.constNull(); |
| 9669 | var running_int = (try o.builder.intConst(int_ty, 0)).toLlvm(&o.builder); |
| 9753 | 9670 | var running_bits: u16 = 0; |
| 9754 | 9671 | for (elements, 0..) |elem, i| { |
| 9755 | 9672 | const field = fields[i]; |
| ... | ... | @@ -9762,12 +9679,12 @@ pub const FuncGen = struct { |
| 9762 | 9679 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 9763 | 9680 | else |
| 9764 | 9681 | self.builder.buildBitCast(non_int_val, small_int_ty, ""); |
| 9765 | | const shift_rhs = int_llvm_ty.constInt(running_bits, .False); |
| 9682 | const shift_rhs = try o.builder.intConst(int_ty, running_bits); |
| 9766 | 9683 | // If the field is as large as the entire packed struct, this |
| 9767 | 9684 | // zext would go from, e.g. i16 to i16. This is legal with |
| 9768 | 9685 | // constZExtOrBitCast but not legal with constZExt. |
| 9769 | | const extended_int_val = self.builder.buildZExtOrBitCast(small_int_val, int_llvm_ty, ""); |
| 9770 | | const shifted = self.builder.buildShl(extended_int_val, shift_rhs, ""); |
| 9686 | const extended_int_val = self.builder.buildZExtOrBitCast(small_int_val, int_ty.toLlvm(&o.builder), ""); |
| 9687 | const shifted = self.builder.buildShl(extended_int_val, shift_rhs.toLlvm(&o.builder), ""); |
| 9771 | 9688 | running_int = self.builder.buildOr(running_int, shifted, ""); |
| 9772 | 9689 | running_bits += ty_bit_size; |
| 9773 | 9690 | } |
| ... | ... | @@ -9775,18 +9692,20 @@ pub const FuncGen = struct { |
| 9775 | 9692 | } |
| 9776 | 9693 | |
| 9777 | 9694 | if (isByRef(result_ty, mod)) { |
| 9778 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 9779 | 9695 | // TODO in debug builds init to undef so that the padding will be 0xaa |
| 9780 | 9696 | // even if we fully populate the fields. |
| 9781 | 9697 | const alloca_inst = try self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod)); |
| 9782 | 9698 | |
| 9783 | | var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined }; |
| 9699 | var indices: [2]*llvm.Value = .{ |
| 9700 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 9701 | undefined, |
| 9702 | }; |
| 9784 | 9703 | for (elements, 0..) |elem, i| { |
| 9785 | 9704 | if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue; |
| 9786 | 9705 | |
| 9787 | 9706 | const llvm_elem = try self.resolveInst(elem); |
| 9788 | 9707 | const llvm_i = llvmField(result_ty, i, mod).?.index; |
| 9789 | | indices[1] = llvm_u32.constInt(llvm_i, .False); |
| 9708 | indices[1] = (try o.builder.intConst(.i32, llvm_i)).toLlvm(&o.builder); |
| 9790 | 9709 | const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); |
| 9791 | 9710 | const field_ptr_ty = try mod.ptrType(.{ |
| 9792 | 9711 | .child = self.typeOf(elem).toIntern(), |
| ... | ... | @@ -9815,7 +9734,7 @@ pub const FuncGen = struct { |
| 9815 | 9734 | .Array => { |
| 9816 | 9735 | assert(isByRef(result_ty, mod)); |
| 9817 | 9736 | |
| 9818 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 9737 | const usize_ty = try o.lowerType(Type.usize); |
| 9819 | 9738 | const alloca_inst = try self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod)); |
| 9820 | 9739 | |
| 9821 | 9740 | const array_info = result_ty.arrayInfo(mod); |
| ... | ... | @@ -9825,8 +9744,8 @@ pub const FuncGen = struct { |
| 9825 | 9744 | |
| 9826 | 9745 | for (elements, 0..) |elem, i| { |
| 9827 | 9746 | const indices: [2]*llvm.Value = .{ |
| 9828 | | llvm_usize.constNull(), |
| 9829 | | llvm_usize.constInt(@as(c_uint, @intCast(i)), .False), |
| 9747 | (try o.builder.intConst(usize_ty, 0)).toLlvm(&o.builder), |
| 9748 | (try o.builder.intConst(usize_ty, i)).toLlvm(&o.builder), |
| 9830 | 9749 | }; |
| 9831 | 9750 | const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); |
| 9832 | 9751 | const llvm_elem = try self.resolveInst(elem); |
| ... | ... | @@ -9834,8 +9753,8 @@ pub const FuncGen = struct { |
| 9834 | 9753 | } |
| 9835 | 9754 | if (array_info.sentinel) |sent_val| { |
| 9836 | 9755 | const indices: [2]*llvm.Value = .{ |
| 9837 | | llvm_usize.constNull(), |
| 9838 | | llvm_usize.constInt(@as(c_uint, @intCast(array_info.len)), .False), |
| 9756 | (try o.builder.intConst(usize_ty, 0)).toLlvm(&o.builder), |
| 9757 | (try o.builder.intConst(usize_ty, array_info.len)).toLlvm(&o.builder), |
| 9839 | 9758 | }; |
| 9840 | 9759 | const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); |
| 9841 | 9760 | const llvm_elem = try self.resolveValue(.{ |
| ... | ... | @@ -9858,7 +9777,7 @@ pub const FuncGen = struct { |
| 9858 | 9777 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 9859 | 9778 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 9860 | 9779 | const union_ty = self.typeOfIndex(inst); |
| 9861 | | const union_llvm_ty = (try o.lowerType(union_ty)).toLlvm(&o.builder); |
| 9780 | const union_llvm_ty = try o.lowerType(union_ty); |
| 9862 | 9781 | const layout = union_ty.unionGetLayout(mod); |
| 9863 | 9782 | const union_obj = mod.typeToUnion(union_ty).?; |
| 9864 | 9783 | |
| ... | ... | @@ -9889,14 +9808,14 @@ pub const FuncGen = struct { |
| 9889 | 9808 | return null; |
| 9890 | 9809 | } |
| 9891 | 9810 | assert(!isByRef(union_ty, mod)); |
| 9892 | | return union_llvm_ty.constInt(tag_int, .False); |
| 9811 | return (try o.builder.intConst(union_llvm_ty, tag_int)).toLlvm(&o.builder); |
| 9893 | 9812 | } |
| 9894 | 9813 | assert(isByRef(union_ty, mod)); |
| 9895 | 9814 | // The llvm type of the alloca will be the named LLVM union type, and will not |
| 9896 | 9815 | // necessarily match the format that we need, depending on which tag is active. |
| 9897 | 9816 | // We must construct the correct unnamed struct type here, in order to then set |
| 9898 | 9817 | // the fields appropriately. |
| 9899 | | const result_ptr = try self.buildAlloca(union_llvm_ty, layout.abi_align); |
| 9818 | const result_ptr = try self.buildAlloca(union_llvm_ty.toLlvm(&o.builder), layout.abi_align); |
| 9900 | 9819 | const llvm_payload = try self.resolveInst(extra.init); |
| 9901 | 9820 | assert(union_obj.haveFieldTypes()); |
| 9902 | 9821 | const field = union_obj.fields.values()[extra.field_index]; |
| ... | ... | @@ -9936,8 +9855,6 @@ pub const FuncGen = struct { |
| 9936 | 9855 | |
| 9937 | 9856 | // Now we follow the layout as expressed above with GEP instructions to set the |
| 9938 | 9857 | // tag and the payload. |
| 9939 | | const index_type = Builder.Type.i32.toLlvm(&o.builder); |
| 9940 | | |
| 9941 | 9858 | const field_ptr_ty = try mod.ptrType(.{ |
| 9942 | 9859 | .child = field.ty.toIntern(), |
| 9943 | 9860 | .flags = .{ |
| ... | ... | @@ -9946,10 +9863,8 @@ pub const FuncGen = struct { |
| 9946 | 9863 | }); |
| 9947 | 9864 | if (layout.tag_size == 0) { |
| 9948 | 9865 | const indices: [3]*llvm.Value = .{ |
| 9949 | | index_type.constNull(), |
| 9950 | | index_type.constNull(), |
| 9951 | | index_type.constNull(), |
| 9952 | | }; |
| 9866 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 9867 | } ** 3; |
| 9953 | 9868 | const len: c_uint = if (field_size == layout.payload_size) 2 else 3; |
| 9954 | 9869 | const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, result_ptr, &indices, len, ""); |
| 9955 | 9870 | try self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); |
| ... | ... | @@ -9958,9 +9873,9 @@ pub const FuncGen = struct { |
| 9958 | 9873 | |
| 9959 | 9874 | { |
| 9960 | 9875 | const indices: [3]*llvm.Value = .{ |
| 9961 | | index_type.constNull(), |
| 9962 | | index_type.constInt(@intFromBool(layout.tag_align >= layout.payload_align), .False), |
| 9963 | | index_type.constNull(), |
| 9876 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 9877 | (try o.builder.intConst(.i32, @intFromBool(layout.tag_align >= layout.payload_align))).toLlvm(&o.builder), |
| 9878 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 9964 | 9879 | }; |
| 9965 | 9880 | const len: c_uint = if (field_size == layout.payload_size) 2 else 3; |
| 9966 | 9881 | const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, result_ptr, &indices, len, ""); |
| ... | ... | @@ -9968,13 +9883,13 @@ pub const FuncGen = struct { |
| 9968 | 9883 | } |
| 9969 | 9884 | { |
| 9970 | 9885 | const indices: [2]*llvm.Value = .{ |
| 9971 | | index_type.constNull(), |
| 9972 | | index_type.constInt(@intFromBool(layout.tag_align < layout.payload_align), .False), |
| 9886 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 9887 | (try o.builder.intConst(.i32, @intFromBool(layout.tag_align < layout.payload_align))).toLlvm(&o.builder), |
| 9973 | 9888 | }; |
| 9974 | 9889 | const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, result_ptr, &indices, indices.len, ""); |
| 9975 | | const tag_llvm_ty = (try o.lowerType(union_obj.tag_ty)).toLlvm(&o.builder); |
| 9976 | | const llvm_tag = tag_llvm_ty.constInt(tag_int, .False); |
| 9977 | | const store_inst = self.builder.buildStore(llvm_tag, field_ptr); |
| 9890 | const tag_ty = try o.lowerType(union_obj.tag_ty); |
| 9891 | const llvm_tag = try o.builder.intConst(tag_ty, tag_int); |
| 9892 | const store_inst = self.builder.buildStore(llvm_tag.toLlvm(&o.builder), field_ptr); |
| 9978 | 9893 | store_inst.setAlignment(union_obj.tag_ty.abiAlignment(mod)); |
| 9979 | 9894 | } |
| 9980 | 9895 | |
| ... | ... | @@ -10031,12 +9946,11 @@ pub const FuncGen = struct { |
| 10031 | 9946 | |
| 10032 | 9947 | const ptr = try self.resolveInst(prefetch.ptr); |
| 10033 | 9948 | |
| 10034 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 10035 | 9949 | const params = [_]*llvm.Value{ |
| 10036 | 9950 | ptr, |
| 10037 | | llvm_u32.constInt(@intFromEnum(prefetch.rw), .False), |
| 10038 | | llvm_u32.constInt(prefetch.locality, .False), |
| 10039 | | llvm_u32.constInt(@intFromEnum(prefetch.cache), .False), |
| 9951 | (try o.builder.intConst(.i32, @intFromEnum(prefetch.rw))).toLlvm(&o.builder), |
| 9952 | (try o.builder.intConst(.i32, prefetch.locality)).toLlvm(&o.builder), |
| 9953 | (try o.builder.intConst(.i32, @intFromEnum(prefetch.cache))).toLlvm(&o.builder), |
| 10040 | 9954 | }; |
| 10041 | 9955 | _ = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, ""); |
| 10042 | 9956 | return null; |
| ... | ... | @@ -10053,13 +9967,11 @@ pub const FuncGen = struct { |
| 10053 | 9967 | } |
| 10054 | 9968 | |
| 10055 | 9969 | fn amdgcnWorkIntrinsic(self: *FuncGen, dimension: u32, default: u32, comptime basename: []const u8) !?*llvm.Value { |
| 10056 | | const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 10057 | | |
| 10058 | 9970 | const llvm_fn_name = switch (dimension) { |
| 10059 | 9971 | 0 => basename ++ ".x", |
| 10060 | 9972 | 1 => basename ++ ".y", |
| 10061 | 9973 | 2 => basename ++ ".z", |
| 10062 | | else => return llvm_u32.constInt(default, .False), |
| 9974 | else => return (try self.dg.object.builder.intConst(.i32, default)).toLlvm(&self.dg.object.builder), |
| 10063 | 9975 | }; |
| 10064 | 9976 | |
| 10065 | 9977 | const args: [0]*llvm.Value = .{}; |
| ... | ... | @@ -10084,9 +9996,8 @@ pub const FuncGen = struct { |
| 10084 | 9996 | |
| 10085 | 9997 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 10086 | 9998 | const dimension = pl_op.payload; |
| 10087 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 10088 | 9999 | if (dimension >= 3) { |
| 10089 | | return llvm_u32.constInt(1, .False); |
| 10000 | return (try o.builder.intConst(.i32, 1)).toLlvm(&o.builder); |
| 10090 | 10001 | } |
| 10091 | 10002 | |
| 10092 | 10003 | // Fetch the dispatch pointer, which points to this structure: |
| ... | ... | @@ -10099,7 +10010,9 @@ pub const FuncGen = struct { |
| 10099 | 10010 | // Load the work_group_* member from the struct as u16. |
| 10100 | 10011 | // Just treat the dispatch pointer as an array of u16 to keep things simple. |
| 10101 | 10012 | const offset = 2 + dimension; |
| 10102 | | const index = [_]*llvm.Value{llvm_u32.constInt(offset, .False)}; |
| 10013 | const index = [_]*llvm.Value{ |
| 10014 | (try o.builder.intConst(.i32, offset)).toLlvm(&o.builder), |
| 10015 | }; |
| 10103 | 10016 | const llvm_u16 = Builder.Type.i16.toLlvm(&o.builder); |
| 10104 | 10017 | const workgroup_size_ptr = self.builder.buildInBoundsGEP(llvm_u16, dispatch_ptr, &index, index.len, ""); |
| 10105 | 10018 | const workgroup_size = self.builder.buildLoad(llvm_u16, workgroup_size_ptr, ""); |
| ... | ... | @@ -10145,18 +10058,17 @@ pub const FuncGen = struct { |
| 10145 | 10058 | opt_llvm_ty: *llvm.Type, |
| 10146 | 10059 | opt_handle: *llvm.Value, |
| 10147 | 10060 | is_by_ref: bool, |
| 10148 | | ) *llvm.Value { |
| 10149 | | const non_null_llvm_ty = Builder.Type.i8.toLlvm(&self.dg.object.builder); |
| 10061 | ) Allocator.Error!*llvm.Value { |
| 10150 | 10062 | const field = b: { |
| 10151 | 10063 | if (is_by_ref) { |
| 10152 | 10064 | const field_ptr = self.builder.buildStructGEP(opt_llvm_ty, opt_handle, 1, ""); |
| 10153 | | break :b self.builder.buildLoad(non_null_llvm_ty, field_ptr, ""); |
| 10065 | break :b self.builder.buildLoad(Builder.Type.i8.toLlvm(&self.dg.object.builder), field_ptr, ""); |
| 10154 | 10066 | } |
| 10155 | 10067 | break :b self.builder.buildExtractValue(opt_handle, 1, ""); |
| 10156 | 10068 | }; |
| 10157 | 10069 | comptime assert(optional_layout_version == 3); |
| 10158 | 10070 | |
| 10159 | | return self.builder.buildICmp(.NE, field, non_null_llvm_ty.constInt(0, .False), ""); |
| 10071 | return self.builder.buildICmp(.NE, field, (try self.dg.object.builder.intConst(.i8, 0)).toLlvm(&self.dg.object.builder), ""); |
| 10160 | 10072 | } |
| 10161 | 10073 | |
| 10162 | 10074 | /// Assumes the optional is not pointer-like and payload has bits. |
| ... | ... | @@ -10254,9 +10166,9 @@ pub const FuncGen = struct { |
| 10254 | 10166 | const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod); |
| 10255 | 10167 | if (byte_offset == 0) return struct_ptr; |
| 10256 | 10168 | const byte_llvm_ty = Builder.Type.i8.toLlvm(&o.builder); |
| 10257 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 10258 | | const llvm_index = llvm_usize.constInt(byte_offset, .False); |
| 10259 | | const indices: [1]*llvm.Value = .{llvm_index}; |
| 10169 | const usize_ty = try o.lowerType(Type.usize); |
| 10170 | const llvm_index = try o.builder.intConst(usize_ty, byte_offset); |
| 10171 | const indices: [1]*llvm.Value = .{llvm_index.toLlvm(&o.builder)}; |
| 10260 | 10172 | return self.builder.buildInBoundsGEP(byte_llvm_ty, struct_ptr, &indices, indices.len, ""); |
| 10261 | 10173 | }, |
| 10262 | 10174 | else => { |
| ... | ... | @@ -10269,9 +10181,8 @@ pub const FuncGen = struct { |
| 10269 | 10181 | // end of the struct. Treat our struct pointer as an array of two and get |
| 10270 | 10182 | // the index to the element at index `1` to get a pointer to the end of |
| 10271 | 10183 | // the struct. |
| 10272 | | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 10273 | | const llvm_index = llvm_u32.constInt(@intFromBool(struct_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); |
| 10274 | | const indices: [1]*llvm.Value = .{llvm_index}; |
| 10184 | const llvm_index = try o.builder.intConst(.i32, @intFromBool(struct_ty.hasRuntimeBitsIgnoreComptime(mod))); |
| 10185 | const indices: [1]*llvm.Value = .{llvm_index.toLlvm(&o.builder)}; |
| 10275 | 10186 | return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); |
| 10276 | 10187 | } |
| 10277 | 10188 | }, |
| ... | ... | @@ -10311,14 +10222,14 @@ pub const FuncGen = struct { |
| 10311 | 10222 | const pointee_llvm_ty = (try o.lowerType(pointee_type)).toLlvm(&o.builder); |
| 10312 | 10223 | const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod)); |
| 10313 | 10224 | const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align); |
| 10314 | | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 10225 | const usize_ty = try o.lowerType(Type.usize); |
| 10315 | 10226 | const size_bytes = pointee_type.abiSize(mod); |
| 10316 | 10227 | _ = fg.builder.buildMemCpy( |
| 10317 | 10228 | result_ptr, |
| 10318 | 10229 | result_align, |
| 10319 | 10230 | ptr, |
| 10320 | 10231 | ptr_alignment, |
| 10321 | | llvm_usize.constInt(size_bytes, .False), |
| 10232 | (try o.builder.intConst(usize_ty, size_bytes)).toLlvm(&o.builder), |
| 10322 | 10233 | is_volatile, |
| 10323 | 10234 | ); |
| 10324 | 10235 | return result_ptr; |
| ... | ... | @@ -10340,15 +10251,15 @@ pub const FuncGen = struct { |
| 10340 | 10251 | |
| 10341 | 10252 | assert(info.flags.vector_index != .runtime); |
| 10342 | 10253 | if (info.flags.vector_index != .none) { |
| 10343 | | const index_u32 = Builder.Type.i32.toLlvm(&o.builder).constInt(@intFromEnum(info.flags.vector_index), .False); |
| 10344 | | const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 10345 | | const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); |
| 10254 | const index_u32 = try o.builder.intConst(.i32, @intFromEnum(info.flags.vector_index)); |
| 10255 | const vec_elem_ty = try o.lowerType(elem_ty); |
| 10256 | const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); |
| 10346 | 10257 | |
| 10347 | | const loaded_vector = self.builder.buildLoad(vec_ty, ptr, ""); |
| 10258 | const loaded_vector = self.builder.buildLoad(vec_ty.toLlvm(&o.builder), ptr, ""); |
| 10348 | 10259 | loaded_vector.setAlignment(ptr_alignment); |
| 10349 | 10260 | loaded_vector.setVolatile(ptr_volatile); |
| 10350 | 10261 | |
| 10351 | | return self.builder.buildExtractElement(loaded_vector, index_u32, ""); |
| 10262 | return self.builder.buildExtractElement(loaded_vector, index_u32.toLlvm(&o.builder), ""); |
| 10352 | 10263 | } |
| 10353 | 10264 | |
| 10354 | 10265 | if (info.packed_offset.host_size == 0) { |
| ... | ... | @@ -10417,15 +10328,15 @@ pub const FuncGen = struct { |
| 10417 | 10328 | |
| 10418 | 10329 | assert(info.flags.vector_index != .runtime); |
| 10419 | 10330 | if (info.flags.vector_index != .none) { |
| 10420 | | const index_u32 = Builder.Type.i32.toLlvm(&o.builder).constInt(@intFromEnum(info.flags.vector_index), .False); |
| 10421 | | const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 10422 | | const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); |
| 10331 | const index_u32 = try o.builder.intConst(.i32, @intFromEnum(info.flags.vector_index)); |
| 10332 | const vec_elem_ty = try o.lowerType(elem_ty); |
| 10333 | const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); |
| 10423 | 10334 | |
| 10424 | | const loaded_vector = self.builder.buildLoad(vec_ty, ptr, ""); |
| 10335 | const loaded_vector = self.builder.buildLoad(vec_ty.toLlvm(&o.builder), ptr, ""); |
| 10425 | 10336 | loaded_vector.setAlignment(ptr_alignment); |
| 10426 | 10337 | loaded_vector.setVolatile(ptr_volatile); |
| 10427 | 10338 | |
| 10428 | | const modified_vector = self.builder.buildInsertElement(loaded_vector, elem, index_u32, ""); |
| 10339 | const modified_vector = self.builder.buildInsertElement(loaded_vector, elem, index_u32.toLlvm(&o.builder), ""); |
| 10429 | 10340 | |
| 10430 | 10341 | const store_inst = self.builder.buildStore(modified_vector, ptr); |
| 10431 | 10342 | assert(ordering == .NotAtomic); |
| ... | ... | @@ -10481,7 +10392,7 @@ pub const FuncGen = struct { |
| 10481 | 10392 | ptr_alignment, |
| 10482 | 10393 | elem, |
| 10483 | 10394 | elem_ty.abiAlignment(mod), |
| 10484 | | (try o.lowerType(Type.usize)).toLlvm(&o.builder).constInt(size_bytes, .False), |
| 10395 | (try o.builder.intConst(try o.lowerType(Type.usize), size_bytes)).toLlvm(&o.builder), |
| 10485 | 10396 | info.flags.is_volatile, |
| 10486 | 10397 | ); |
| 10487 | 10398 | } |
| ... | ... | @@ -10489,10 +10400,10 @@ pub const FuncGen = struct { |
| 10489 | 10400 | fn valgrindMarkUndef(fg: *FuncGen, ptr: *llvm.Value, len: *llvm.Value) Allocator.Error!void { |
| 10490 | 10401 | const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; |
| 10491 | 10402 | const o = fg.dg.object; |
| 10492 | | const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 10493 | | const zero = usize_llvm_ty.constInt(0, .False); |
| 10494 | | const req = usize_llvm_ty.constInt(VG_USERREQ__MAKE_MEM_UNDEFINED, .False); |
| 10495 | | const ptr_as_usize = fg.builder.buildPtrToInt(ptr, usize_llvm_ty, ""); |
| 10403 | const usize_ty = try o.lowerType(Type.usize); |
| 10404 | const zero = (try o.builder.intConst(usize_ty, 0)).toLlvm(&o.builder); |
| 10405 | const req = (try o.builder.intConst(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED)).toLlvm(&o.builder); |
| 10406 | const ptr_as_usize = fg.builder.buildPtrToInt(ptr, usize_ty.toLlvm(&o.builder), ""); |
| 10496 | 10407 | _ = try valgrindClientRequest(fg, zero, req, ptr_as_usize, len, zero, zero, zero); |
| 10497 | 10408 | } |
| 10498 | 10409 | |
| ... | ... | @@ -10511,21 +10422,20 @@ pub const FuncGen = struct { |
| 10511 | 10422 | const target = mod.getTarget(); |
| 10512 | 10423 | if (!target_util.hasValgrindSupport(target)) return default_value; |
| 10513 | 10424 | |
| 10514 | | const usize_ty = try o.lowerType(Type.usize); |
| 10515 | | const usize_llvm_ty = usize_ty.toLlvm(&o.builder); |
| 10425 | const llvm_usize = try o.lowerType(Type.usize); |
| 10516 | 10426 | const usize_alignment = @as(c_uint, @intCast(Type.usize.abiSize(mod))); |
| 10517 | 10427 | |
| 10518 | | const array_llvm_ty = usize_llvm_ty.arrayType(6); |
| 10428 | const array_llvm_ty = (try o.builder.arrayType(6, llvm_usize)).toLlvm(&o.builder); |
| 10519 | 10429 | const array_ptr = fg.valgrind_client_request_array orelse a: { |
| 10520 | 10430 | const array_ptr = try fg.buildAlloca(array_llvm_ty, usize_alignment); |
| 10521 | 10431 | fg.valgrind_client_request_array = array_ptr; |
| 10522 | 10432 | break :a array_ptr; |
| 10523 | 10433 | }; |
| 10524 | 10434 | const array_elements = [_]*llvm.Value{ request, a1, a2, a3, a4, a5 }; |
| 10525 | | const zero = usize_llvm_ty.constInt(0, .False); |
| 10435 | const zero = (try o.builder.intConst(llvm_usize, 0)).toLlvm(&o.builder); |
| 10526 | 10436 | for (array_elements, 0..) |elem, i| { |
| 10527 | 10437 | const indexes = [_]*llvm.Value{ |
| 10528 | | zero, usize_llvm_ty.constInt(@as(c_uint, @intCast(i)), .False), |
| 10438 | zero, (try o.builder.intConst(llvm_usize, i)).toLlvm(&o.builder), |
| 10529 | 10439 | }; |
| 10530 | 10440 | const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, ""); |
| 10531 | 10441 | const store_inst = fg.builder.buildStore(elem, elem_ptr); |
| ... | ... | @@ -10563,8 +10473,8 @@ pub const FuncGen = struct { |
| 10563 | 10473 | else => unreachable, |
| 10564 | 10474 | }; |
| 10565 | 10475 | |
| 10566 | | const fn_llvm_ty = (try o.builder.fnType(usize_ty, &(.{usize_ty} ** 2), .normal)).toLlvm(&o.builder); |
| 10567 | | const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, ""); |
| 10476 | const fn_llvm_ty = (try o.builder.fnType(llvm_usize, &(.{llvm_usize} ** 2), .normal)).toLlvm(&o.builder); |
| 10477 | const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, llvm_usize.toLlvm(&o.builder), ""); |
| 10568 | 10478 | const args = [_]*llvm.Value{ array_ptr_as_usize, default_value }; |
| 10569 | 10479 | const asm_fn = llvm.getInlineAsm( |
| 10570 | 10480 | fn_llvm_ty, |