authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-08 23:13:06-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-19 23:38:40-04:00
log2cb52235b91f7e4bf5a4ebf77a5008adfc30c8b9
tree07495729dae15f20cd1cdf00cc37a3c8dbbb07ea
parent65fd401c063ed5214fd6d38b04278571df24f962

llvm: convert all calls to `constInt`


3 files changed, 834 insertions(+), 454 deletions(-)

src/codegen/llvm.zig+273-363
......@@ -611,7 +611,7 @@ pub const Object = struct {
611611 };
612612 errdefer builder.llvm_context.dispose();
613613
614 initializeLLVMTarget(options.target.cpu.arch);
614 builder.initializeLLVMTarget(options.target.cpu.arch);
615615
616616 builder.llvm_module = llvm.Module.createWithName(options.root_name.ptr, builder.llvm_context);
617617 errdefer builder.llvm_module.dispose();
......@@ -832,7 +832,7 @@ pub const Object = struct {
832832
833833 const slice_fields = [_]*llvm.Value{
834834 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),
836836 };
837837 llvm_error.* = llvm_slice_ty.constNamedStruct(&slice_fields, slice_fields.len);
838838 }
......@@ -874,8 +874,8 @@ pub const Object = struct {
874874 // }
875875
876876 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), "");
879879 _ = builder.buildRet(is_lt);
880880 }
881881
......@@ -3474,10 +3474,8 @@ pub const Object = struct {
34743474 .@"unreachable",
34753475 .generic_poison,
34763476 => 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),
34813479 },
34823480 .variable,
34833481 .enum_literal,
......@@ -3503,9 +3501,9 @@ pub const Object = struct {
35033501 return lowerBigInt(o, tv.ty, bigint);
35043502 },
35053503 .err => |err| {
3506 const llvm_ty = Builder.Type.err_int.toLlvm(&o.builder);
35073504 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);
35093507 },
35103508 .error_union => |error_union| {
35113509 const err_tv: TypedValue = switch (error_union.val) {
......@@ -3556,79 +3554,33 @@ pub const Object = struct {
35563554 return o.context.constStruct(&fields_buf, llvm_field_count, .False);
35573555 }
35583556 },
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)),
36323584 .ptr => |ptr| {
36333585 const ptr_tv: TypedValue = switch (ptr.len) {
36343586 .none => tv,
......@@ -3660,11 +3612,7 @@ pub const Object = struct {
36603612 comptime assert(optional_layout_version == 3);
36613613 const payload_ty = tv.ty.optionalChild(mod);
36623614
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);
36683616 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
36693617 return non_null_bit;
36703618 }
......@@ -3761,10 +3709,9 @@ pub const Object = struct {
37613709 const elem_ty = vector_type.child.toType();
37623710 const llvm_elems = try gpa.alloc(*llvm.Value, vector_type.len);
37633711 defer gpa.free(llvm_elems);
3764 const llvm_i8 = Builder.Type.i8.toLlvm(&o.builder);
37653712 for (llvm_elems, 0..) |*llvm_elem, i| {
37663713 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),
37683715 .elems => |elems| try o.lowerValue(.{
37693716 .ty = elem_ty,
37703717 .val = elems[i].toValue(),
......@@ -3802,10 +3749,10 @@ pub const Object = struct {
38023749
38033750 const padding_len = offset - prev_offset;
38043751 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);
38063753 // TODO make this and all other padding elsewhere in debug
38073754 // builds be 0xaa not undef.
3808 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3755 llvm_fields.appendAssumeCapacity(llvm_array_ty.toLlvm(&o.builder).getUndef());
38093756 }
38103757
38113758 const field_llvm_val = try o.lowerValue(.{
......@@ -3824,8 +3771,8 @@ pub const Object = struct {
38243771 offset = std.mem.alignForward(u64, offset, big_align);
38253772 const padding_len = offset - prev_offset;
38263773 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());
38293776 }
38303777 }
38313778
......@@ -3850,10 +3797,10 @@ pub const Object = struct {
38503797 if (struct_obj.layout == .Packed) {
38513798 assert(struct_obj.haveLayout());
38523799 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));
38543801 const fields = struct_obj.fields.values();
38553802 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);
38573804 var running_bits: u16 = 0;
38583805 for (fields, 0..) |field, i| {
38593806 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
......@@ -3868,11 +3815,11 @@ pub const Object = struct {
38683815 non_int_val.constPtrToInt(small_int_ty)
38693816 else
38703817 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);
38723819 // If the field is as large as the entire packed struct, this
38733820 // zext would go from, e.g. i16 to i16. This is legal with
38743821 // 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));
38763823 const shifted = extended_int_val.constShl(shift_rhs);
38773824 running_int = running_int.constOr(shifted);
38783825 running_bits += ty_bit_size;
......@@ -3899,10 +3846,10 @@ pub const Object = struct {
38993846
39003847 const padding_len = offset - prev_offset;
39013848 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);
39033850 // TODO make this and all other padding elsewhere in debug
39043851 // builds be 0xaa not undef.
3905 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3852 llvm_fields.appendAssumeCapacity(llvm_array_ty.toLlvm(&o.builder).getUndef());
39063853 }
39073854
39083855 const field_llvm_val = try o.lowerValue(.{
......@@ -3921,8 +3868,8 @@ pub const Object = struct {
39213868 offset = std.mem.alignForward(u64, offset, big_align);
39223869 const padding_len = offset - prev_offset;
39233870 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());
39263873 }
39273874 }
39283875
......@@ -3985,7 +3932,7 @@ pub const Object = struct {
39853932 const payload = p: {
39863933 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {
39873934 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();
39893936 }
39903937 const field = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val });
39913938 need_unnamed = need_unnamed or o.isUnnamedType(field_ty, field);
......@@ -3995,7 +3942,7 @@ pub const Object = struct {
39953942 }
39963943 const padding_len = @as(c_uint, @intCast(layout.payload_size - field_size));
39973944 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(),
39993946 };
40003947 break :p o.context.constStruct(&fields, fields.len, .True);
40013948 };
......@@ -4020,7 +3967,7 @@ pub const Object = struct {
40203967 fields = .{ payload, llvm_tag_value, undefined };
40213968 }
40223969 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();
40243971 fields_len = 3;
40253972 }
40263973 if (need_unnamed) {
......@@ -4048,27 +3995,8 @@ pub const Object = struct {
40483995 }
40493996
40503997 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);
40724000 }
40734001
40744002 const ParentPtr = struct {
......@@ -4106,10 +4034,9 @@ pub const Object = struct {
41064034 }
41074035
41084036 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);
41104037 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),
41134040 };
41144041 const eu_llvm_ty = (try o.lowerType(eu_ty)).toLlvm(&o.builder);
41154042 return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
......@@ -4127,11 +4054,9 @@ pub const Object = struct {
41274054 return parent_llvm_ptr;
41284055 }
41294056
4130 const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder);
41314057 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;
41354060 const opt_llvm_ty = (try o.lowerType(opt_ty)).toLlvm(&o.builder);
41364061 return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
41374062 },
......@@ -4139,9 +4064,8 @@ pub const Object = struct {
41394064 .elem => |elem_ptr| {
41404065 const parent_llvm_ptr = try o.lowerParentPtr(elem_ptr.base.toValue(), true);
41414066
4142 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
41434067 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),
41454069 };
41464070 const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod);
41474071 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
......@@ -4152,7 +4076,6 @@ pub const Object = struct {
41524076 const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
41534077
41544078 const field_index = @as(u32, @intCast(field_ptr.index));
4155 const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder);
41564079 switch (parent_ty.zigTypeTag(mod)) {
41574080 .Union => {
41584081 if (parent_ty.containerLayout(mod) == .Packed) {
......@@ -4170,8 +4093,8 @@ pub const Object = struct {
41704093 else
41714094 @intFromBool(layout.tag_align >= layout.payload_align);
41724095 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),
41754098 };
41764099 const parent_llvm_ty = (try o.lowerType(parent_ty)).toLlvm(&o.builder);
41774100 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
......@@ -4179,8 +4102,8 @@ pub const Object = struct {
41794102 .Struct => {
41804103 if (parent_ty.containerLayout(mod) == .Packed) {
41814104 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));
41844107 // count bits of fields before this one
41854108 const prev_bits = b: {
41864109 var b: usize = 0;
......@@ -4190,7 +4113,7 @@ pub const Object = struct {
41904113 }
41914114 break :b b;
41924115 };
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);
41944117 const field_addr = base_addr.constAdd(byte_offset);
41954118 const final_llvm_ty = o.context.pointerType(0);
41964119 return field_addr.constIntToPtr(final_llvm_ty);
......@@ -4199,21 +4122,22 @@ pub const Object = struct {
41994122 const parent_llvm_ty = (try o.lowerType(parent_ty)).toLlvm(&o.builder);
42004123 if (llvmField(parent_ty, field_index, mod)) |llvm_field| {
42014124 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),
42044127 };
42054128 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
42064129 } 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 };
42094133 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
42104134 }
42114135 },
42124136 .Pointer => {
42134137 assert(parent_ty.isSlice(mod));
42144138 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),
42174141 };
42184142 const parent_llvm_ty = (try o.lowerType(parent_ty)).toLlvm(&o.builder);
42194143 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
......@@ -4284,10 +4208,10 @@ pub const Object = struct {
42844208 // The value cannot be undefined, because we use the `nonnull` annotation
42854209 // for non-optional pointers. We also need to respect the alignment, even though
42864210 // 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);
42884212 const llvm_ptr_ty = (try o.lowerType(ptr_ty)).toLlvm(&o.builder);
42894213 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);
42914215 }
42924216 // Note that these 0xaa values are appropriate even in release-optimized builds
42934217 // because we need a well-defined value that is not null, and LLVM does not
......@@ -4295,13 +4219,13 @@ pub const Object = struct {
42954219 // instruction is followed by a `wrap_optional`, it will return this value
42964220 // verbatim, and the result should test as non-null.
42974221 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,
43024226 else => unreachable,
4303 };
4304 return int.constIntToPtr(llvm_ptr_ty);
4227 }));
4228 return int.toLlvm(&o.builder).constIntToPtr(llvm_ptr_ty);
43054229 }
43064230
43074231 fn addAttr(o: *Object, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void {
......@@ -5118,11 +5042,11 @@ pub const FuncGen = struct {
51185042 llvm_arg = store_inst;
51195043 }
51205044
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);
51235047
51245048 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, "");
51265050 load_inst.setAlignment(alignment);
51275051 try llvm_args.append(load_inst);
51285052 },
......@@ -5138,9 +5062,9 @@ pub const FuncGen = struct {
51385062 llvm_arg = store_inst;
51395063 }
51405064
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)));
51425066 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, "");
51445068 load_inst.setAlignment(alignment);
51455069 try llvm_args.append(load_inst);
51465070 },
......@@ -5279,7 +5203,7 @@ pub const FuncGen = struct {
52795203 });
52805204 const null_opt_addr_global = try o.getNullOptAddr();
52815205 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);
52835207 // example:
52845208 // call fastcc void @test2.panic(
52855209 // ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr
......@@ -5289,7 +5213,7 @@ pub const FuncGen = struct {
52895213 // )
52905214 const args = [4]*llvm.Value{
52915215 msg_ptr,
5292 llvm_usize.constInt(msg_len, .False),
5216 (try o.builder.intConst(llvm_usize, msg_len)).toLlvm(&o.builder),
52935217 fg.context.pointerType(0).constNull(),
52945218 null_opt_addr_global,
52955219 };
......@@ -5327,8 +5251,8 @@ pub const FuncGen = struct {
53275251 // Functions with an empty error set are emitted with an error code
53285252 // return type and return zero so they can be function pointers coerced
53295253 // 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));
53325256 } else {
53335257 _ = self.builder.buildRetVoid();
53345258 }
......@@ -5375,8 +5299,8 @@ pub const FuncGen = struct {
53755299 // Functions with an empty error set are emitted with an error code
53765300 // return type and return zero so they can be function pointers coerced
53775301 // 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));
53805304 } else {
53815305 _ = self.builder.buildRetVoid();
53825306 }
......@@ -5531,22 +5455,22 @@ pub const FuncGen = struct {
55315455 // of optionals that are not pointers.
55325456 const is_by_ref = isByRef(scalar_ty, mod);
55335457 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), "");
55405464 const lhs_rhs_ored = self.builder.buildOr(lhs_shifted, rhs_non_null_i2, "");
55415465 const both_null_block = self.context.appendBasicBlock(self.llvm_func, "BothNull");
55425466 const mixed_block = self.context.appendBasicBlock(self.llvm_func, "Mixed");
55435467 const both_pl_block = self.context.appendBasicBlock(self.llvm_func, "BothNonNull");
55445468 const end_block = self.context.appendBasicBlock(self.llvm_func, "End");
55455469 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);
55505474
55515475 self.builder.positionBuilderAtEnd(both_null_block);
55525476 _ = self.builder.buildBr(end_block);
......@@ -5567,9 +5491,8 @@ pub const FuncGen = struct {
55675491 mixed_block,
55685492 both_pl_block_end,
55695493 };
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);
55735496 const incoming_values: [3]*llvm.Value = .{
55745497 switch (op) {
55755498 .eq => llvm_i1_1,
......@@ -5584,7 +5507,7 @@ pub const FuncGen = struct {
55845507 payload_cmp,
55855508 };
55865509
5587 const phi_node = self.builder.buildPhi(llvm_i1, "");
5510 const phi_node = self.builder.buildPhi(Builder.Type.i1.toLlvm(&o.builder), "");
55885511 comptime assert(incoming_values.len == incoming_blocks.len);
55895512 phi_node.addIncoming(
55905513 &incoming_values,
......@@ -5882,8 +5805,8 @@ pub const FuncGen = struct {
58825805 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
58835806 const operand_ty = self.typeOf(ty_op.operand);
58845807 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);
58875810 const slice_llvm_ty = (try o.lowerType(self.typeOfIndex(inst))).toLlvm(&o.builder);
58885811 const operand = try self.resolveInst(ty_op.operand);
58895812 if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
......@@ -5891,8 +5814,8 @@ pub const FuncGen = struct {
58915814 return self.builder.buildInsertValue(partial, len, 1, "");
58925815 }
58935816 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;
58965819 const array_llvm_ty = (try o.lowerType(array_ty)).toLlvm(&o.builder);
58975820 const ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indices, indices.len, "");
58985821 const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, "");
......@@ -6024,21 +5947,21 @@ pub const FuncGen = struct {
60245947 fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: *llvm.Value, ty: Type) Allocator.Error!*llvm.Value {
60255948 const o = fg.dg.object;
60265949 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);
60285951 switch (ty.ptrSize(mod)) {
60295952 .Slice => {
60305953 const len = fg.builder.buildExtractValue(ptr, 1, "");
60315954 const elem_ty = ty.childType(mod);
60325955 const abi_size = elem_ty.abiSize(mod);
60335956 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), "");
60365959 },
60375960 .One => {
60385961 const array_ty = ty.childType(mod);
60395962 const elem_ty = array_ty.childType(mod);
60405963 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);
60425965 },
60435966 .Many, .C => unreachable,
60445967 }
......@@ -6340,10 +6263,10 @@ pub const FuncGen = struct {
63406263 if (field_offset == 0) {
63416264 return field_ptr;
63426265 }
6343 const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
6266 const llvm_usize = try o.lowerType(Type.usize);
63446267
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), "");
63476270 return self.builder.buildIntToPtr(base_ptr_int, res_ty, "");
63486271 }
63496272
......@@ -6919,12 +6842,11 @@ pub const FuncGen = struct {
69196842 self.builder.buildLoad(optional_llvm_ty, operand, "")
69206843 else
69216844 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), "");
69246846 }
69256847
69266848 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);
69286850 if (pred == .EQ) {
69296851 return self.builder.buildNot(non_null_bit, "");
69306852 } else {
......@@ -6949,12 +6871,12 @@ pub const FuncGen = struct {
69496871 const zero = err_set_ty.constNull();
69506872
69516873 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
69566877 else => unreachable,
6957 }
6878 };
6879 return val.toLlvm(&o.builder);
69586880 }
69596881
69606882 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
......@@ -7007,7 +6929,7 @@ pub const FuncGen = struct {
70076929 const operand = try self.resolveInst(ty_op.operand);
70086930 const optional_ty = self.typeOf(ty_op.operand).childType(mod);
70096931 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);
70116933 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
70126934 // We have a pointer to a i8. We need to set it to 1 and then return the same pointer.
70136935 _ = self.builder.buildStore(non_null_bit, operand);
......@@ -7101,11 +7023,10 @@ pub const FuncGen = struct {
71017023 const operand_ty = self.typeOf(ty_op.operand);
71027024 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
71037025 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
7104 const err_llvm_ty = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder);
71057026 if (operand_is_ptr) {
71067027 return operand;
71077028 } else {
7108 return err_llvm_ty.constInt(0, .False);
7029 return (try o.builder.intConst(Builder.Type.err_int, 0)).toLlvm(&o.builder);
71097030 }
71107031 }
71117032
......@@ -7193,7 +7114,7 @@ pub const FuncGen = struct {
71937114 const mod = o.module;
71947115 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
71957116 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);
71977118 comptime assert(optional_layout_version == 3);
71987119 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return non_null_bit;
71997120 const operand = try self.resolveInst(ty_op.operand);
......@@ -7278,22 +7199,24 @@ pub const FuncGen = struct {
72787199 }
72797200
72807201 fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7202 const o = self.dg.object;
72817203 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
72827204 const index = pl_op.payload;
7283 const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder);
72847205 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 };
72867209 return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, "");
72877210 }
72887211
72897212 fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7213 const o = self.dg.object;
72907214 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
72917215 const index = pl_op.payload;
72927216 const operand = try self.resolveInst(pl_op.operand);
7293 const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder);
72947217 const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.grow", &.{.i32});
72957218 const args: [2]*llvm.Value = .{
7296 llvm_u32.constInt(index, .False),
7219 (try o.builder.intConst(.i32, index)).toLlvm(&o.builder),
72977220 operand,
72987221 };
72997222 return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, "");
......@@ -7571,24 +7494,23 @@ pub const FuncGen = struct {
75717494 return self.buildFloatOp(.floor, inst_ty, 1, .{result});
75727495 }
75737496 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);
75757498 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
75767499 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
75777500 const vec_len = inst_ty.vectorLen(mod);
7578 const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
75797501
75807502 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
75817503 defer self.gpa.free(shifts);
75827504
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));
75847506 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);
75867508
75877509 const div = self.builder.buildSDiv(lhs, rhs, "");
75887510 const rem = self.builder.buildSRem(lhs, rhs, "");
75897511 const div_sign = self.builder.buildXor(lhs, rhs, "");
75907512 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();
75927514 const rem_nonzero = self.builder.buildICmp(.NE, rem, zero, "");
75937515 const correction = self.builder.buildSelect(rem_nonzero, div_sign_mask, zero, "");
75947516 return self.builder.buildNSWAdd(div, correction, "");
......@@ -7637,14 +7559,14 @@ pub const FuncGen = struct {
76377559 const lhs = try self.resolveInst(bin_op.lhs);
76387560 const rhs = try self.resolveInst(bin_op.rhs);
76397561 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);
76417563 const scalar_ty = inst_ty.scalarType(mod);
76427564
76437565 if (scalar_ty.isRuntimeFloat()) {
76447566 const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });
76457567 const b = try self.buildFloatOp(.add, inst_ty, 2, .{ a, rhs });
76467568 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();
76487570 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero });
76497571 return self.builder.buildSelect(ltz, c, a, "");
76507572 }
......@@ -7652,20 +7574,19 @@ pub const FuncGen = struct {
76527574 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
76537575 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
76547576 const vec_len = inst_ty.vectorLen(mod);
7655 const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder);
76567577
76577578 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
76587579 defer self.gpa.free(shifts);
76597580
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));
76617582 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);
76637584
76647585 const rem = self.builder.buildSRem(lhs, rhs, "");
76657586 const div_sign = self.builder.buildXor(lhs, rhs, "");
76667587 const div_sign_mask = self.builder.buildAShr(div_sign, bit_size_minus_one, "");
76677588 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();
76697590 const rem_nonzero = self.builder.buildICmp(.NE, rem, zero, "");
76707591 const correction = self.builder.buildSelect(rem_nonzero, rhs_masked, zero, "");
76717592 return self.builder.buildNSWAdd(rem, correction, "");
......@@ -7789,14 +7710,14 @@ pub const FuncGen = struct {
77897710 result_vector: *llvm.Value,
77907711 vector_len: usize,
77917712 ) !*llvm.Value {
7713 const o = self.dg.object;
77927714 const args_len = @as(c_uint, @intCast(args_vectors.len));
7793 const llvm_i32 = Builder.Type.i32.toLlvm(&self.dg.object.builder);
77947715 assert(args_len <= 3);
77957716
77967717 var i: usize = 0;
77977718 var result = result_vector;
77987719 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);
78007721
78017722 var args: [3]*llvm.Value = undefined;
78027723 for (args_vectors, 0..) |arg_vector, k| {
......@@ -7882,7 +7803,7 @@ pub const FuncGen = struct {
78827803 .i32,
78837804 );
78847805
7885 const zero = Builder.Type.i32.toLlvm(&o.builder).constInt(0, .False);
7806 const zero = (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder);
78867807 const int_pred: llvm.IntPredicate = switch (pred) {
78877808 .eq => .EQ,
78887809 .neq => .NE,
......@@ -7973,17 +7894,17 @@ pub const FuncGen = struct {
79737894 .neg => {
79747895 // In this case we can generate a softfloat negation by XORing the
79757896 // 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));
79807901 const result = if (ty.zigTypeTag(mod) == .Vector) blk: {
79817902 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), "");
79847905 break :blk self.builder.buildXor(bitcasted_operand, splat_sign_mask, "");
79857906 } 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), "");
79877908 break :blk self.builder.buildXor(bitcasted_operand, sign_mask, "");
79887909 };
79897910 return self.builder.buildBitCast(result, llvm_ty.toLlvm(&o.builder), "");
......@@ -8191,9 +8112,9 @@ pub const FuncGen = struct {
81918112 // poison value."
81928113 // However Zig semantics says that saturating shift left can never produce
81938114 // 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);
81978118 if (rhs_ty.zigTypeTag(mod) == .Vector) {
81988119 const vec_len = rhs_ty.vectorLen(mod);
81998120 const bits_vec = self.builder.buildVectorSplat(vec_len, bits, "");
......@@ -8382,17 +8303,19 @@ pub const FuncGen = struct {
83828303 } else {
83838304 // If the ABI size of the element type is not evenly divisible by size in bits;
83848305 // 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);
83888308 const vector_len = operand_ty.arrayLen(mod);
83898309 var i: u64 = 0;
83908310 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 };
83948317 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), "");
83968319 _ = self.builder.buildStore(elem, elem_ptr);
83978320 }
83988321 }
......@@ -8416,19 +8339,21 @@ pub const FuncGen = struct {
84168339 // a simple bitcast will not work, and we fall back to extractelement.
84178340 const array_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder);
84188341 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);
84228344 const vector_len = operand_ty.arrayLen(mod);
84238345 var vector = llvm_vector_ty.getUndef();
84248346 var i: u64 = 0;
84258347 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 };
84298354 const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indexes, indexes.len, "");
84308355 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), "");
84328357 }
84338358
84348359 return vector;
......@@ -8563,14 +8488,13 @@ pub const FuncGen = struct {
85638488 // Even if safety is disabled, we still emit a memset to undefined since it conveys
85648489 // extra information to LLVM. However, safety makes the difference between using
85658490 // 0xaa or actual undefined for the fill byte.
8566 const u8_llvm_ty = Builder.Type.i8.toLlvm(&o.builder);
85678491 const fill_byte = if (safety)
8568 u8_llvm_ty.constInt(0xaa, .False)
8492 (try o.builder.intConst(.i8, 0xaa)).toLlvm(&o.builder)
85698493 else
8570 u8_llvm_ty.getUndef();
8494 Builder.Type.i8.toLlvm(&o.builder).getUndef();
85718495 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);
85748498 const dest_ptr_align = ptr_ty.ptrAlignment(mod);
85758499 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr(mod));
85768500 if (safety and mod.comp.bin_file.options.valgrind) {
......@@ -8855,7 +8779,6 @@ pub const FuncGen = struct {
88558779 const ptr_ty = self.typeOf(bin_op.lhs);
88568780 const elem_ty = self.typeOf(bin_op.rhs);
88578781 const dest_ptr_align = ptr_ty.ptrAlignment(mod);
8858 const u8_llvm_ty = Builder.Type.i8.toLlvm(&o.builder);
88598782 const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty);
88608783 const is_volatile = ptr_ty.isVolatilePtr(mod);
88618784
......@@ -8873,9 +8796,9 @@ pub const FuncGen = struct {
88738796 // extra information to LLVM. However, safety makes the difference between using
88748797 // 0xaa or actual undefined for the fill byte.
88758798 const fill_byte = if (safety)
8876 u8_llvm_ty.constInt(0xaa, .False)
8799 (try o.builder.intConst(.i8, 0xaa)).toLlvm(&o.builder)
88778800 else
8878 u8_llvm_ty.getUndef();
8801 Builder.Type.i8.toLlvm(&o.builder).getUndef();
88798802 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
88808803 if (intrinsic_len0_traps) {
88818804 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile);
......@@ -8946,10 +8869,10 @@ pub const FuncGen = struct {
89468869 const body_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetBody");
89478870 const end_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetEnd");
89488871
8949 const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
8872 const usize_ty = try o.lowerType(Type.usize);
89508873 const len = switch (ptr_ty.ptrSize(mod)) {
89518874 .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),
89538876 .Many, .C => unreachable,
89548877 };
89558878 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
......@@ -8971,7 +8894,7 @@ pub const FuncGen = struct {
89718894 it_ptr_alignment,
89728895 value,
89738896 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),
89758898 is_volatile,
89768899 );
89778900 } else {
......@@ -8979,7 +8902,9 @@ pub const FuncGen = struct {
89798902 store_inst.setAlignment(it_ptr_alignment);
89808903 store_inst.setVolatile(llvm.Bool.fromBool(is_volatile));
89818904 }
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 };
89838908 const next_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, it_ptr, &one_gep, one_gep.len, "");
89848909 _ = self.builder.buildBr(loop_block);
89858910
......@@ -9194,24 +9119,20 @@ pub const FuncGen = struct {
91949119 // If not an even byte-multiple, we need zero-extend + shift-left 1 byte
91959120 // The truncated result at the end will be the correct bswap
91969121 const scalar_ty = try o.builder.intType(@intCast(bits + 8));
9197 const scalar_llvm_ty = scalar_ty.toLlvm(&o.builder);
91989122 if (operand_ty.zigTypeTag(mod) == .Vector) {
91999123 const vec_len = operand_ty.vectorLen(mod);
92009124 operand_llvm_ty = try o.builder.vectorType(.normal, vec_len, scalar_ty);
92019125
92029126 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
92039127 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));
92089129 const shift_vec = llvm.constVector(shifts.ptr, vec_len);
92099130
92109131 const extended = self.builder.buildZExt(operand, operand_llvm_ty.toLlvm(&o.builder), "");
92119132 operand = self.builder.buildShl(extended, shift_vec, "");
92129133 } 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), "");
92159136 operand_llvm_ty = scalar_ty;
92169137 }
92179138 bits = bits + 8;
......@@ -9263,14 +9184,14 @@ pub const FuncGen = struct {
92639184
92649185 self.builder.positionBuilderAtEnd(end_block);
92659186
9266 const llvm_type = Builder.Type.i1.toLlvm(&o.builder);
92679187 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),
92699190 };
92709191 const incoming_blocks: [2]*llvm.BasicBlock = .{
92719192 valid_block, invalid_block,
92729193 };
9273 const phi_node = self.builder.buildPhi(llvm_type, "");
9194 const phi_node = self.builder.buildPhi(Builder.Type.i1.toLlvm(&o.builder), "");
92749195 phi_node.addIncoming(&incoming_values, &incoming_blocks, 2);
92759196 return phi_node;
92769197 }
......@@ -9346,10 +9267,10 @@ pub const FuncGen = struct {
93469267 switch_instr.addCase(this_tag_int_value, named_block);
93479268 }
93489269 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));
93509271
93519272 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));
93539274
93549275 try o.builder.llvm_globals.append(self.gpa, fn_val);
93559276 _ = try o.builder.addGlobal(llvm_fn_name, global);
......@@ -9384,7 +9305,7 @@ pub const FuncGen = struct {
93849305 const slice_ty = Type.slice_const_u8_sentinel_0;
93859306 const ret_ty = try o.lowerType(slice_ty);
93869307 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);
93889309 const slice_alignment = slice_ty.abiAlignment(mod);
93899310
93909311 const fn_type = try o.builder.fnType(ret_ty, &.{
......@@ -9421,9 +9342,9 @@ pub const FuncGen = struct {
94219342 const tag_int_value = fn_val.getParam(0);
94229343 const switch_instr = self.builder.buildSwitch(tag_int_value, bad_value_block, @as(c_uint, @intCast(enum_type.names.len)));
94239344
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;
94279348
94289349 for (enum_type.names, 0..) |name_ip, field_index_usize| {
94299350 const field_index = @as(u32, @intCast(field_index_usize));
......@@ -9439,7 +9360,7 @@ pub const FuncGen = struct {
94399360
94409361 const slice_fields = [_]*llvm.Value{
94419362 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),
94439364 };
94449365 const slice_init = llvm_ret_ty.constNamedStruct(&slice_fields, slice_fields.len);
94459366 const slice_global = o.llvm_module.addGlobal(slice_init.typeOf(), "");
......@@ -9555,16 +9476,14 @@ pub const FuncGen = struct {
95559476 const values = try self.gpa.alloc(*llvm.Value, mask_len);
95569477 defer self.gpa.free(values);
95579478
9558 const llvm_i32 = Builder.Type.i32.toLlvm(&o.builder);
9559
95609479 for (values, 0..) |*val, i| {
95619480 const elem = try mask.elemValue(mod, i);
95629481 if (elem.isUndef(mod)) {
9563 val.* = llvm_i32.getUndef();
9482 val.* = Builder.Type.i32.toLlvm(&o.builder).getUndef();
95649483 } else {
95659484 const int = elem.toSignedInt(mod);
95669485 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);
95689487 }
95699488 }
95709489
......@@ -9592,13 +9511,13 @@ pub const FuncGen = struct {
95929511 accum_init: *llvm.Value,
95939512 ) !*llvm.Value {
95949513 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);
95979516 const llvm_result_ty = accum_init.typeOf();
95989517
95999518 // 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);
96029521 const accum_ptr = try self.buildAlloca(llvm_result_ty, null);
96039522 _ = self.builder.buildStore(accum_init, accum_ptr);
96049523
......@@ -9610,8 +9529,8 @@ pub const FuncGen = struct {
96109529 self.builder.positionBuilderAtEnd(loop);
96119530
96129531 // 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), "");
96159534 const loop_then = self.context.appendBasicBlock(self.llvm_func, "ReduceLoopThen");
96169535
96179536 _ = self.builder.buildCondBr(cond, loop_then, loop_exit);
......@@ -9627,7 +9546,7 @@ pub const FuncGen = struct {
96279546 _ = self.builder.buildStore(new_accum, accum_ptr);
96289547
96299548 // 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), "");
96319550 _ = self.builder.buildStore(new_i, i_ptr);
96329551 _ = self.builder.buildBr(loop);
96339552 }
......@@ -9731,13 +9650,11 @@ pub const FuncGen = struct {
97319650
97329651 switch (result_ty.zigTypeTag(mod)) {
97339652 .Vector => {
9734 const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder);
9735
97369653 var vector = llvm_result_ty.getUndef();
97379654 for (elements, 0..) |elem, i| {
9738 const index_u32 = llvm_u32.constInt(i, .False);
9655 const index_u32 = try o.builder.intConst(.i32, i);
97399656 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), "");
97419658 }
97429659 return vector;
97439660 },
......@@ -9746,10 +9663,10 @@ pub const FuncGen = struct {
97469663 const struct_obj = mod.typeToStruct(result_ty).?;
97479664 assert(struct_obj.haveLayout());
97489665 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));
97509667 const fields = struct_obj.fields.values();
97519668 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);
97539670 var running_bits: u16 = 0;
97549671 for (elements, 0..) |elem, i| {
97559672 const field = fields[i];
......@@ -9762,12 +9679,12 @@ pub const FuncGen = struct {
97629679 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
97639680 else
97649681 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);
97669683 // If the field is as large as the entire packed struct, this
97679684 // zext would go from, e.g. i16 to i16. This is legal with
97689685 // 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), "");
97719688 running_int = self.builder.buildOr(running_int, shifted, "");
97729689 running_bits += ty_bit_size;
97739690 }
......@@ -9775,18 +9692,20 @@ pub const FuncGen = struct {
97759692 }
97769693
97779694 if (isByRef(result_ty, mod)) {
9778 const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder);
97799695 // TODO in debug builds init to undef so that the padding will be 0xaa
97809696 // even if we fully populate the fields.
97819697 const alloca_inst = try self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod));
97829698
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 };
97849703 for (elements, 0..) |elem, i| {
97859704 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
97869705
97879706 const llvm_elem = try self.resolveInst(elem);
97889707 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);
97909709 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
97919710 const field_ptr_ty = try mod.ptrType(.{
97929711 .child = self.typeOf(elem).toIntern(),
......@@ -9815,7 +9734,7 @@ pub const FuncGen = struct {
98159734 .Array => {
98169735 assert(isByRef(result_ty, mod));
98179736
9818 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
9737 const usize_ty = try o.lowerType(Type.usize);
98199738 const alloca_inst = try self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod));
98209739
98219740 const array_info = result_ty.arrayInfo(mod);
......@@ -9825,8 +9744,8 @@ pub const FuncGen = struct {
98259744
98269745 for (elements, 0..) |elem, i| {
98279746 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),
98309749 };
98319750 const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
98329751 const llvm_elem = try self.resolveInst(elem);
......@@ -9834,8 +9753,8 @@ pub const FuncGen = struct {
98349753 }
98359754 if (array_info.sentinel) |sent_val| {
98369755 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),
98399758 };
98409759 const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
98419760 const llvm_elem = try self.resolveValue(.{
......@@ -9858,7 +9777,7 @@ pub const FuncGen = struct {
98589777 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
98599778 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
98609779 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);
98629781 const layout = union_ty.unionGetLayout(mod);
98639782 const union_obj = mod.typeToUnion(union_ty).?;
98649783
......@@ -9889,14 +9808,14 @@ pub const FuncGen = struct {
98899808 return null;
98909809 }
98919810 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);
98939812 }
98949813 assert(isByRef(union_ty, mod));
98959814 // The llvm type of the alloca will be the named LLVM union type, and will not
98969815 // necessarily match the format that we need, depending on which tag is active.
98979816 // We must construct the correct unnamed struct type here, in order to then set
98989817 // 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);
99009819 const llvm_payload = try self.resolveInst(extra.init);
99019820 assert(union_obj.haveFieldTypes());
99029821 const field = union_obj.fields.values()[extra.field_index];
......@@ -9936,8 +9855,6 @@ pub const FuncGen = struct {
99369855
99379856 // Now we follow the layout as expressed above with GEP instructions to set the
99389857 // tag and the payload.
9939 const index_type = Builder.Type.i32.toLlvm(&o.builder);
9940
99419858 const field_ptr_ty = try mod.ptrType(.{
99429859 .child = field.ty.toIntern(),
99439860 .flags = .{
......@@ -9946,10 +9863,8 @@ pub const FuncGen = struct {
99469863 });
99479864 if (layout.tag_size == 0) {
99489865 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;
99539868 const len: c_uint = if (field_size == layout.payload_size) 2 else 3;
99549869 const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, result_ptr, &indices, len, "");
99559870 try self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic);
......@@ -9958,9 +9873,9 @@ pub const FuncGen = struct {
99589873
99599874 {
99609875 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),
99649879 };
99659880 const len: c_uint = if (field_size == layout.payload_size) 2 else 3;
99669881 const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, result_ptr, &indices, len, "");
......@@ -9968,13 +9883,13 @@ pub const FuncGen = struct {
99689883 }
99699884 {
99709885 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),
99739888 };
99749889 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);
99789893 store_inst.setAlignment(union_obj.tag_ty.abiAlignment(mod));
99799894 }
99809895
......@@ -10031,12 +9946,11 @@ pub const FuncGen = struct {
100319946
100329947 const ptr = try self.resolveInst(prefetch.ptr);
100339948
10034 const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder);
100359949 const params = [_]*llvm.Value{
100369950 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),
100409954 };
100419955 _ = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");
100429956 return null;
......@@ -10053,13 +9967,11 @@ pub const FuncGen = struct {
100539967 }
100549968
100559969 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
100589970 const llvm_fn_name = switch (dimension) {
100599971 0 => basename ++ ".x",
100609972 1 => basename ++ ".y",
100619973 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),
100639975 };
100649976
100659977 const args: [0]*llvm.Value = .{};
......@@ -10084,9 +9996,8 @@ pub const FuncGen = struct {
100849996
100859997 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
100869998 const dimension = pl_op.payload;
10087 const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder);
100889999 if (dimension >= 3) {
10089 return llvm_u32.constInt(1, .False);
10000 return (try o.builder.intConst(.i32, 1)).toLlvm(&o.builder);
1009010001 }
1009110002
1009210003 // Fetch the dispatch pointer, which points to this structure:
......@@ -10099,7 +10010,9 @@ pub const FuncGen = struct {
1009910010 // Load the work_group_* member from the struct as u16.
1010010011 // Just treat the dispatch pointer as an array of u16 to keep things simple.
1010110012 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 };
1010310016 const llvm_u16 = Builder.Type.i16.toLlvm(&o.builder);
1010410017 const workgroup_size_ptr = self.builder.buildInBoundsGEP(llvm_u16, dispatch_ptr, &index, index.len, "");
1010510018 const workgroup_size = self.builder.buildLoad(llvm_u16, workgroup_size_ptr, "");
......@@ -10145,18 +10058,17 @@ pub const FuncGen = struct {
1014510058 opt_llvm_ty: *llvm.Type,
1014610059 opt_handle: *llvm.Value,
1014710060 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 {
1015010062 const field = b: {
1015110063 if (is_by_ref) {
1015210064 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, "");
1015410066 }
1015510067 break :b self.builder.buildExtractValue(opt_handle, 1, "");
1015610068 };
1015710069 comptime assert(optional_layout_version == 3);
1015810070
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), "");
1016010072 }
1016110073
1016210074 /// Assumes the optional is not pointer-like and payload has bits.
......@@ -10254,9 +10166,9 @@ pub const FuncGen = struct {
1025410166 const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod);
1025510167 if (byte_offset == 0) return struct_ptr;
1025610168 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)};
1026010172 return self.builder.buildInBoundsGEP(byte_llvm_ty, struct_ptr, &indices, indices.len, "");
1026110173 },
1026210174 else => {
......@@ -10269,9 +10181,8 @@ pub const FuncGen = struct {
1026910181 // end of the struct. Treat our struct pointer as an array of two and get
1027010182 // the index to the element at index `1` to get a pointer to the end of
1027110183 // 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)};
1027510186 return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, "");
1027610187 }
1027710188 },
......@@ -10311,14 +10222,14 @@ pub const FuncGen = struct {
1031110222 const pointee_llvm_ty = (try o.lowerType(pointee_type)).toLlvm(&o.builder);
1031210223 const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod));
1031310224 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);
1031510226 const size_bytes = pointee_type.abiSize(mod);
1031610227 _ = fg.builder.buildMemCpy(
1031710228 result_ptr,
1031810229 result_align,
1031910230 ptr,
1032010231 ptr_alignment,
10321 llvm_usize.constInt(size_bytes, .False),
10232 (try o.builder.intConst(usize_ty, size_bytes)).toLlvm(&o.builder),
1032210233 is_volatile,
1032310234 );
1032410235 return result_ptr;
......@@ -10340,15 +10251,15 @@ pub const FuncGen = struct {
1034010251
1034110252 assert(info.flags.vector_index != .runtime);
1034210253 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);
1034610257
10347 const loaded_vector = self.builder.buildLoad(vec_ty, ptr, "");
10258 const loaded_vector = self.builder.buildLoad(vec_ty.toLlvm(&o.builder), ptr, "");
1034810259 loaded_vector.setAlignment(ptr_alignment);
1034910260 loaded_vector.setVolatile(ptr_volatile);
1035010261
10351 return self.builder.buildExtractElement(loaded_vector, index_u32, "");
10262 return self.builder.buildExtractElement(loaded_vector, index_u32.toLlvm(&o.builder), "");
1035210263 }
1035310264
1035410265 if (info.packed_offset.host_size == 0) {
......@@ -10417,15 +10328,15 @@ pub const FuncGen = struct {
1041710328
1041810329 assert(info.flags.vector_index != .runtime);
1041910330 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);
1042310334
10424 const loaded_vector = self.builder.buildLoad(vec_ty, ptr, "");
10335 const loaded_vector = self.builder.buildLoad(vec_ty.toLlvm(&o.builder), ptr, "");
1042510336 loaded_vector.setAlignment(ptr_alignment);
1042610337 loaded_vector.setVolatile(ptr_volatile);
1042710338
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), "");
1042910340
1043010341 const store_inst = self.builder.buildStore(modified_vector, ptr);
1043110342 assert(ordering == .NotAtomic);
......@@ -10481,7 +10392,7 @@ pub const FuncGen = struct {
1048110392 ptr_alignment,
1048210393 elem,
1048310394 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),
1048510396 info.flags.is_volatile,
1048610397 );
1048710398 }
......@@ -10489,10 +10400,10 @@ pub const FuncGen = struct {
1048910400 fn valgrindMarkUndef(fg: *FuncGen, ptr: *llvm.Value, len: *llvm.Value) Allocator.Error!void {
1049010401 const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
1049110402 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), "");
1049610407 _ = try valgrindClientRequest(fg, zero, req, ptr_as_usize, len, zero, zero, zero);
1049710408 }
1049810409
......@@ -10511,21 +10422,20 @@ pub const FuncGen = struct {
1051110422 const target = mod.getTarget();
1051210423 if (!target_util.hasValgrindSupport(target)) return default_value;
1051310424
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);
1051610426 const usize_alignment = @as(c_uint, @intCast(Type.usize.abiSize(mod)));
1051710427
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);
1051910429 const array_ptr = fg.valgrind_client_request_array orelse a: {
1052010430 const array_ptr = try fg.buildAlloca(array_llvm_ty, usize_alignment);
1052110431 fg.valgrind_client_request_array = array_ptr;
1052210432 break :a array_ptr;
1052310433 };
1052410434 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);
1052610436 for (array_elements, 0..) |elem, i| {
1052710437 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),
1052910439 };
1053010440 const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, "");
1053110441 const store_inst = fg.builder.buildStore(elem, elem_ptr);
......@@ -10563,8 +10473,8 @@ pub const FuncGen = struct {
1056310473 else => unreachable,
1056410474 };
1056510475
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), "");
1056810478 const args = [_]*llvm.Value{ array_ptr_as_usize, default_value };
1056910479 const asm_fn = llvm.getInlineAsm(
1057010480 fn_llvm_ty,
src/codegen/llvm/Builder.zig+555-91
......@@ -6,6 +6,7 @@ llvm_module: *llvm.Module,
66di_builder: ?*llvm.DIBuilder = null,
77llvm_types: std.ArrayListUnmanaged(*llvm.Type) = .{},
88llvm_globals: std.ArrayListUnmanaged(*llvm.Value) = .{},
9llvm_constants: std.ArrayListUnmanaged(*llvm.Value) = .{},
910
1011source_filename: String = .none,
1112data_layout: String = .none,
......@@ -29,6 +30,11 @@ aliases: std.ArrayListUnmanaged(Alias) = .{},
2930objects: std.ArrayListUnmanaged(Object) = .{},
3031functions: std.ArrayListUnmanaged(Function) = .{},
3132
33constant_map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
34constant_items: std.MultiArrayList(Constant.Item) = .{},
35constant_extra: std.ArrayListUnmanaged(u32) = .{},
36constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb) = .{},
37
3238pub const String = enum(u32) {
3339 none = std.math.maxInt(u31),
3440 empty,
......@@ -612,10 +618,6 @@ pub const Global = struct {
612618 builder.llvm_globals.items[index].setValueName2(slice.ptr, slice.len);
613619 }
614620 };
615
616 fn deinit(self: *Global, _: Allocator) void {
617 self.* = undefined;
618 }
619621};
620622
621623pub const Alias = struct {
......@@ -642,7 +644,7 @@ pub const Object = struct {
642644 global: Global.Index,
643645 thread_local: ThreadLocal = .default,
644646 mutability: enum { global, constant } = .global,
645 init: void = {},
647 init: Constant = .no_init,
646648
647649 pub const Index = enum(u32) {
648650 _,
......@@ -664,10 +666,8 @@ pub const Object = struct {
664666pub const Function = struct {
665667 global: Global.Index,
666668 body: ?void = null,
667
668 fn deinit(self: *Function, _: Allocator) void {
669 self.* = undefined;
670 }
669 instructions: std.ArrayListUnmanaged(Instruction) = .{},
670 blocks: std.ArrayListUnmanaged(Block) = .{},
671671
672672 pub const Index = enum(u32) {
673673 _,
......@@ -684,6 +684,130 @@ pub const Function = struct {
684684 return self.ptrConst(builder).global.toLlvm(builder);
685685 }
686686 };
687
688 pub const Instruction = struct {
689 tag: Tag,
690
691 pub const Tag = enum {
692 arg,
693 block,
694 };
695
696 pub const Index = enum(u31) { _ };
697 };
698
699 pub const Block = struct {
700 body: std.ArrayListUnmanaged(Instruction.Index) = .{},
701
702 pub const Index = enum(u31) { _ };
703 };
704
705 pub fn deinit(self: *Function, gpa: Allocator) void {
706 self.instructions.deinit(gpa);
707 self.blocks.deinit(gpa);
708 self.* = undefined;
709 }
710};
711
712pub const Constant = enum(u32) {
713 false,
714 true,
715 none,
716 no_init = 1 << 31,
717 _,
718
719 const first_global: Constant = @enumFromInt(1 << 30);
720
721 pub const Tag = enum(u6) {
722 integer_positive,
723 integer_negative,
724 null,
725 none,
726 structure,
727 array,
728 vector,
729 zeroinitializer,
730 global,
731 undef,
732 poison,
733 blockaddress,
734 dso_local_equivalent,
735 no_cfi,
736 trunc,
737 zext,
738 sext,
739 fptrunc,
740 fpext,
741 fptoui,
742 fptosi,
743 uitofp,
744 sitofp,
745 ptrtoint,
746 inttoptr,
747 bitcast,
748 addrspacecast,
749 getelementptr,
750 icmp,
751 fcmp,
752 extractelement,
753 insertelement,
754 shufflevector,
755 add,
756 sub,
757 mul,
758 shl,
759 lshr,
760 ashr,
761 @"and",
762 @"or",
763 xor,
764 };
765
766 pub const Item = struct {
767 tag: Tag,
768 data: u32,
769 };
770
771 pub const Integer = packed struct(u64) {
772 type: Type,
773 limbs_len: u32,
774
775 pub const limbs = @divExact(@bitSizeOf(Integer), @bitSizeOf(std.math.big.Limb));
776 };
777
778 pub fn unwrap(self: Constant) union(enum) {
779 constant: u30,
780 global: Global.Index,
781 } {
782 return if (@intFromEnum(self) < @intFromEnum(first_global))
783 .{ .constant = @intCast(@intFromEnum(self)) }
784 else
785 .{ .global = @enumFromInt(@intFromEnum(self) - @intFromEnum(first_global)) };
786 }
787
788 pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value {
789 assert(builder.useLibLlvm());
790 return switch (self.unwrap()) {
791 .constant => |constant| builder.llvm_constants.items[constant],
792 .global => |global| global.toLlvm(builder),
793 };
794 }
795};
796
797pub const Value = enum(u32) {
798 _,
799
800 const first_constant: Value = @enumFromInt(1 << 31);
801
802 pub fn unwrap(self: Value) union(enum) {
803 instruction: Function.Instruction.Index,
804 constant: Constant,
805 } {
806 return if (@intFromEnum(self) < @intFromEnum(first_constant))
807 .{ .instruction = @intFromEnum(self) }
808 else
809 .{ .constant = @enumFromInt(@intFromEnum(self) - @intFromEnum(first_constant)) };
810 }
687811};
688812
689813pub fn init(self: *Builder) Allocator.Error!void {
......@@ -711,11 +835,15 @@ pub fn init(self: *Builder) Allocator.Error!void {
711835 inline for (.{0}) |addr_space|
712836 assert(self.ptrTypeAssumeCapacity(@enumFromInt(addr_space)) == .ptr);
713837 }
838
839 assert(try self.intConst(.i1, 0) == .false);
840 assert(try self.intConst(.i1, 1) == .true);
714841}
715842
716843pub fn deinit(self: *Builder) void {
717844 self.llvm_types.deinit(self.gpa);
718845 self.llvm_globals.deinit(self.gpa);
846 self.llvm_constants.deinit(self.gpa);
719847
720848 self.string_map.deinit(self.gpa);
721849 self.string_bytes.deinit(self.gpa);
......@@ -731,11 +859,210 @@ pub fn deinit(self: *Builder) void {
731859 self.next_unique_global_id.deinit(self.gpa);
732860 self.aliases.deinit(self.gpa);
733861 self.objects.deinit(self.gpa);
862 for (self.functions.items) |*function| function.deinit(self.gpa);
734863 self.functions.deinit(self.gpa);
735864
865 self.constant_map.deinit(self.gpa);
866 self.constant_items.deinit(self.gpa);
867 self.constant_extra.deinit(self.gpa);
868 self.constant_limbs.deinit(self.gpa);
869
736870 self.* = undefined;
737871}
738872
873pub fn initializeLLVMTarget(self: *const Builder, arch: std.Target.Cpu.Arch) void {
874 if (!self.useLibLlvm()) return;
875 switch (arch) {
876 .aarch64, .aarch64_be, .aarch64_32 => {
877 llvm.LLVMInitializeAArch64Target();
878 llvm.LLVMInitializeAArch64TargetInfo();
879 llvm.LLVMInitializeAArch64TargetMC();
880 llvm.LLVMInitializeAArch64AsmPrinter();
881 llvm.LLVMInitializeAArch64AsmParser();
882 },
883 .amdgcn => {
884 llvm.LLVMInitializeAMDGPUTarget();
885 llvm.LLVMInitializeAMDGPUTargetInfo();
886 llvm.LLVMInitializeAMDGPUTargetMC();
887 llvm.LLVMInitializeAMDGPUAsmPrinter();
888 llvm.LLVMInitializeAMDGPUAsmParser();
889 },
890 .thumb, .thumbeb, .arm, .armeb => {
891 llvm.LLVMInitializeARMTarget();
892 llvm.LLVMInitializeARMTargetInfo();
893 llvm.LLVMInitializeARMTargetMC();
894 llvm.LLVMInitializeARMAsmPrinter();
895 llvm.LLVMInitializeARMAsmParser();
896 },
897 .avr => {
898 llvm.LLVMInitializeAVRTarget();
899 llvm.LLVMInitializeAVRTargetInfo();
900 llvm.LLVMInitializeAVRTargetMC();
901 llvm.LLVMInitializeAVRAsmPrinter();
902 llvm.LLVMInitializeAVRAsmParser();
903 },
904 .bpfel, .bpfeb => {
905 llvm.LLVMInitializeBPFTarget();
906 llvm.LLVMInitializeBPFTargetInfo();
907 llvm.LLVMInitializeBPFTargetMC();
908 llvm.LLVMInitializeBPFAsmPrinter();
909 llvm.LLVMInitializeBPFAsmParser();
910 },
911 .hexagon => {
912 llvm.LLVMInitializeHexagonTarget();
913 llvm.LLVMInitializeHexagonTargetInfo();
914 llvm.LLVMInitializeHexagonTargetMC();
915 llvm.LLVMInitializeHexagonAsmPrinter();
916 llvm.LLVMInitializeHexagonAsmParser();
917 },
918 .lanai => {
919 llvm.LLVMInitializeLanaiTarget();
920 llvm.LLVMInitializeLanaiTargetInfo();
921 llvm.LLVMInitializeLanaiTargetMC();
922 llvm.LLVMInitializeLanaiAsmPrinter();
923 llvm.LLVMInitializeLanaiAsmParser();
924 },
925 .mips, .mipsel, .mips64, .mips64el => {
926 llvm.LLVMInitializeMipsTarget();
927 llvm.LLVMInitializeMipsTargetInfo();
928 llvm.LLVMInitializeMipsTargetMC();
929 llvm.LLVMInitializeMipsAsmPrinter();
930 llvm.LLVMInitializeMipsAsmParser();
931 },
932 .msp430 => {
933 llvm.LLVMInitializeMSP430Target();
934 llvm.LLVMInitializeMSP430TargetInfo();
935 llvm.LLVMInitializeMSP430TargetMC();
936 llvm.LLVMInitializeMSP430AsmPrinter();
937 llvm.LLVMInitializeMSP430AsmParser();
938 },
939 .nvptx, .nvptx64 => {
940 llvm.LLVMInitializeNVPTXTarget();
941 llvm.LLVMInitializeNVPTXTargetInfo();
942 llvm.LLVMInitializeNVPTXTargetMC();
943 llvm.LLVMInitializeNVPTXAsmPrinter();
944 // There is no LLVMInitializeNVPTXAsmParser function available.
945 },
946 .powerpc, .powerpcle, .powerpc64, .powerpc64le => {
947 llvm.LLVMInitializePowerPCTarget();
948 llvm.LLVMInitializePowerPCTargetInfo();
949 llvm.LLVMInitializePowerPCTargetMC();
950 llvm.LLVMInitializePowerPCAsmPrinter();
951 llvm.LLVMInitializePowerPCAsmParser();
952 },
953 .riscv32, .riscv64 => {
954 llvm.LLVMInitializeRISCVTarget();
955 llvm.LLVMInitializeRISCVTargetInfo();
956 llvm.LLVMInitializeRISCVTargetMC();
957 llvm.LLVMInitializeRISCVAsmPrinter();
958 llvm.LLVMInitializeRISCVAsmParser();
959 },
960 .sparc, .sparc64, .sparcel => {
961 llvm.LLVMInitializeSparcTarget();
962 llvm.LLVMInitializeSparcTargetInfo();
963 llvm.LLVMInitializeSparcTargetMC();
964 llvm.LLVMInitializeSparcAsmPrinter();
965 llvm.LLVMInitializeSparcAsmParser();
966 },
967 .s390x => {
968 llvm.LLVMInitializeSystemZTarget();
969 llvm.LLVMInitializeSystemZTargetInfo();
970 llvm.LLVMInitializeSystemZTargetMC();
971 llvm.LLVMInitializeSystemZAsmPrinter();
972 llvm.LLVMInitializeSystemZAsmParser();
973 },
974 .wasm32, .wasm64 => {
975 llvm.LLVMInitializeWebAssemblyTarget();
976 llvm.LLVMInitializeWebAssemblyTargetInfo();
977 llvm.LLVMInitializeWebAssemblyTargetMC();
978 llvm.LLVMInitializeWebAssemblyAsmPrinter();
979 llvm.LLVMInitializeWebAssemblyAsmParser();
980 },
981 .x86, .x86_64 => {
982 llvm.LLVMInitializeX86Target();
983 llvm.LLVMInitializeX86TargetInfo();
984 llvm.LLVMInitializeX86TargetMC();
985 llvm.LLVMInitializeX86AsmPrinter();
986 llvm.LLVMInitializeX86AsmParser();
987 },
988 .xtensa => {
989 if (build_options.llvm_has_xtensa) {
990 llvm.LLVMInitializeXtensaTarget();
991 llvm.LLVMInitializeXtensaTargetInfo();
992 llvm.LLVMInitializeXtensaTargetMC();
993 llvm.LLVMInitializeXtensaAsmPrinter();
994 llvm.LLVMInitializeXtensaAsmParser();
995 }
996 },
997 .xcore => {
998 llvm.LLVMInitializeXCoreTarget();
999 llvm.LLVMInitializeXCoreTargetInfo();
1000 llvm.LLVMInitializeXCoreTargetMC();
1001 llvm.LLVMInitializeXCoreAsmPrinter();
1002 // There is no LLVMInitializeXCoreAsmParser function.
1003 },
1004 .m68k => {
1005 if (build_options.llvm_has_m68k) {
1006 llvm.LLVMInitializeM68kTarget();
1007 llvm.LLVMInitializeM68kTargetInfo();
1008 llvm.LLVMInitializeM68kTargetMC();
1009 llvm.LLVMInitializeM68kAsmPrinter();
1010 llvm.LLVMInitializeM68kAsmParser();
1011 }
1012 },
1013 .csky => {
1014 if (build_options.llvm_has_csky) {
1015 llvm.LLVMInitializeCSKYTarget();
1016 llvm.LLVMInitializeCSKYTargetInfo();
1017 llvm.LLVMInitializeCSKYTargetMC();
1018 // There is no LLVMInitializeCSKYAsmPrinter function.
1019 llvm.LLVMInitializeCSKYAsmParser();
1020 }
1021 },
1022 .ve => {
1023 llvm.LLVMInitializeVETarget();
1024 llvm.LLVMInitializeVETargetInfo();
1025 llvm.LLVMInitializeVETargetMC();
1026 llvm.LLVMInitializeVEAsmPrinter();
1027 llvm.LLVMInitializeVEAsmParser();
1028 },
1029 .arc => {
1030 if (build_options.llvm_has_arc) {
1031 llvm.LLVMInitializeARCTarget();
1032 llvm.LLVMInitializeARCTargetInfo();
1033 llvm.LLVMInitializeARCTargetMC();
1034 llvm.LLVMInitializeARCAsmPrinter();
1035 // There is no LLVMInitializeARCAsmParser function.
1036 }
1037 },
1038
1039 // LLVM backends that have no initialization functions.
1040 .tce,
1041 .tcele,
1042 .r600,
1043 .le32,
1044 .le64,
1045 .amdil,
1046 .amdil64,
1047 .hsail,
1048 .hsail64,
1049 .shave,
1050 .spir,
1051 .spir64,
1052 .kalimba,
1053 .renderscript32,
1054 .renderscript64,
1055 .dxil,
1056 .loongarch32,
1057 .loongarch64,
1058 => {},
1059
1060 .spu_2 => unreachable, // LLVM does not support this backend
1061 .spirv32 => unreachable, // LLVM does not support this backend
1062 .spirv64 => unreachable, // LLVM does not support this backend
1063 }
1064}
1065
7391066pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String {
7401067 try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len + 1);
7411068 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
......@@ -899,6 +1226,112 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index {
8991226 return @enumFromInt(self.globals.getIndex(name) orelse return null);
9001227}
9011228
1229pub fn intConst(self: *Builder, ty: Type, value: anytype) Allocator.Error!Constant {
1230 var limbs: [
1231 switch (@typeInfo(@TypeOf(value))) {
1232 .Int => |info| std.math.big.int.calcTwosCompLimbCount(info.bits),
1233 .ComptimeInt => std.math.big.int.calcLimbLen(value),
1234 else => @compileError("intConst expected an integral value, got " ++
1235 @typeName(@TypeOf(value))),
1236 }
1237 ]std.math.big.Limb = undefined;
1238 return self.bigIntConst(ty, std.math.big.int.Mutable.init(&limbs, value).toConst());
1239}
1240
1241pub fn bigIntConst(self: *Builder, ty: Type, value: std.math.big.int.Const) Allocator.Error!Constant {
1242 try self.constant_map.ensureUnusedCapacity(self.gpa, 1);
1243 try self.constant_items.ensureUnusedCapacity(self.gpa, 1);
1244 try self.constant_limbs.ensureUnusedCapacity(self.gpa, Constant.Integer.limbs + value.limbs.len);
1245 if (self.useLibLlvm()) try self.llvm_constants.ensureUnusedCapacity(self.gpa, 1);
1246 return self.bigIntConstAssumeCapacity(ty, value);
1247}
1248
1249pub fn dump(self: *Builder, writer: anytype) @TypeOf(writer).Error!void {
1250 if (self.source_filename != .none) try writer.print(
1251 \\; ModuleID = '{s}'
1252 \\source_filename = {"}
1253 \\
1254 , .{ self.source_filename.toSlice(self).?, self.source_filename.fmt(self) });
1255 if (self.data_layout != .none) try writer.print(
1256 \\target datalayout = {"}
1257 \\
1258 , .{self.data_layout.fmt(self)});
1259 if (self.target_triple != .none) try writer.print(
1260 \\target triple = {"}
1261 \\
1262 , .{self.target_triple.fmt(self)});
1263 try writer.writeByte('\n');
1264 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(
1265 \\%{} = type {}
1266 \\
1267 , .{ id.fmt(self), ty.fmt(self) });
1268 try writer.writeByte('\n');
1269 for (self.objects.items) |object| {
1270 const global = self.globals.entries.get(@intFromEnum(object.global));
1271 try writer.print(
1272 \\@{} ={}{}{}{}{}{}{}{} {s} {%}{,}
1273 \\
1274 , .{
1275 global.key.fmt(self),
1276 global.value.linkage,
1277 global.value.preemption,
1278 global.value.visibility,
1279 global.value.dll_storage_class,
1280 object.thread_local,
1281 global.value.unnamed_addr,
1282 global.value.addr_space,
1283 global.value.externally_initialized,
1284 @tagName(object.mutability),
1285 global.value.type.fmt(self),
1286 global.value.alignment,
1287 });
1288 }
1289 try writer.writeByte('\n');
1290 for (self.functions.items) |function| {
1291 const global = self.globals.entries.get(@intFromEnum(function.global));
1292 const item = self.type_items.items[@intFromEnum(global.value.type)];
1293 const extra = self.typeExtraDataTrail(Type.Function, item.data);
1294 const params: []const Type =
1295 @ptrCast(self.type_extra.items[extra.end..][0..extra.data.params_len]);
1296 try writer.print(
1297 \\{s} {}{}{}{}{} @{}(
1298 , .{
1299 if (function.body) |_| "define" else "declare",
1300 global.value.linkage,
1301 global.value.preemption,
1302 global.value.visibility,
1303 global.value.dll_storage_class,
1304 extra.data.ret.fmt(self),
1305 global.key.fmt(self),
1306 });
1307 for (params, 0..) |param, index| {
1308 if (index > 0) try writer.writeAll(", ");
1309 try writer.print("{%} %{d}", .{ param.fmt(self), index });
1310 }
1311 switch (item.tag) {
1312 .function => {},
1313 .vararg_function => {
1314 if (params.len > 0) try writer.writeAll(", ");
1315 try writer.writeAll("...");
1316 },
1317 else => unreachable,
1318 }
1319 try writer.print(") {}{}", .{
1320 global.value.unnamed_addr,
1321 global.value.alignment,
1322 });
1323 if (function.body) |_| try writer.print(
1324 \\{{
1325 \\ ret {%}
1326 \\}}
1327 \\
1328 , .{
1329 extra.data.ret.fmt(self),
1330 });
1331 try writer.writeByte('\n');
1332 }
1333}
1334
9021335fn ensureUnusedCapacityGlobal(self: *Builder, name: String) Allocator.Error!void {
9031336 if (self.useLibLlvm()) try self.llvm_globals.ensureUnusedCapacity(self.gpa, 1);
9041337 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
......@@ -1002,6 +1435,7 @@ fn fnTypeAssumeCapacity(
10021435}
10031436
10041437fn intTypeAssumeCapacity(self: *Builder, bits: u24) Type {
1438 assert(bits > 0);
10051439 const result = self.typeNoExtraAssumeCapacity(.{ .tag = .integer, .data = bits });
10061440 if (self.useLibLlvm() and result.new)
10071441 self.llvm_types.appendAssumeCapacity(self.llvm_context.intType(bits));
......@@ -1162,10 +1596,16 @@ fn structTypeAssumeCapacity(
11621596 });
11631597 self.type_extra.appendSliceAssumeCapacity(@ptrCast(fields));
11641598 if (self.useLibLlvm()) {
1165 const llvm_fields = try self.gpa.alloc(*llvm.Type, fields.len);
1166 defer self.gpa.free(llvm_fields);
1599 const ExpectedContents = [32]*llvm.Type;
1600 var stack align(@alignOf(ExpectedContents)) =
1601 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
1602 const allocator = stack.get();
1603
1604 const llvm_fields = try allocator.alloc(*llvm.Type, fields.len);
1605 defer allocator.free(llvm_fields);
11671606 for (llvm_fields, fields) |*llvm_field, field|
11681607 llvm_field.* = self.llvm_types.items[@intFromEnum(field)];
1608
11691609 self.llvm_types.appendAssumeCapacity(self.llvm_context.structType(
11701610 llvm_fields.ptr,
11711611 @intCast(llvm_fields.len),
......@@ -1277,90 +1717,114 @@ fn isValidIdentifier(id: []const u8) bool {
12771717 return true;
12781718}
12791719
1280pub fn dump(self: *Builder, writer: anytype) @TypeOf(writer).Error!void {
1281 if (self.source_filename != .none) try writer.print(
1282 \\; ModuleID = '{s}'
1283 \\source_filename = {"}
1284 \\
1285 , .{ self.source_filename.toSlice(self).?, self.source_filename.fmt(self) });
1286 if (self.data_layout != .none) try writer.print(
1287 \\target datalayout = {"}
1288 \\
1289 , .{self.data_layout.fmt(self)});
1290 if (self.target_triple != .none) try writer.print(
1291 \\target triple = {"}
1292 \\
1293 , .{self.target_triple.fmt(self)});
1294 try writer.writeByte('\n');
1295 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(
1296 \\%{} = type {}
1297 \\
1298 , .{ id.fmt(self), ty.fmt(self) });
1299 try writer.writeByte('\n');
1300 for (self.objects.items) |object| {
1301 const global = self.globals.entries.get(@intFromEnum(object.global));
1302 try writer.print(
1303 \\@{} ={}{}{}{}{}{}{}{} {s} {%}{,}
1304 \\
1305 , .{
1306 global.key.fmt(self),
1307 global.value.linkage,
1308 global.value.preemption,
1309 global.value.visibility,
1310 global.value.dll_storage_class,
1311 object.thread_local,
1312 global.value.unnamed_addr,
1313 global.value.addr_space,
1314 global.value.externally_initialized,
1315 @tagName(object.mutability),
1316 global.value.type.fmt(self),
1317 global.value.alignment,
1318 });
1319 }
1320 try writer.writeByte('\n');
1321 for (self.functions.items) |function| {
1322 const global = self.globals.entries.get(@intFromEnum(function.global));
1323 const item = self.type_items.items[@intFromEnum(global.value.type)];
1324 const extra = self.typeExtraDataTrail(Type.Function, item.data);
1325 const params: []const Type =
1326 @ptrCast(self.type_extra.items[extra.end..][0..extra.data.params_len]);
1327 try writer.print(
1328 \\{s} {}{}{}{}{} @{}(
1329 , .{
1330 if (function.body) |_| "define" else "declare",
1331 global.value.linkage,
1332 global.value.preemption,
1333 global.value.visibility,
1334 global.value.dll_storage_class,
1335 extra.data.ret.fmt(self),
1336 global.key.fmt(self),
1337 });
1338 for (params, 0..) |param, index| {
1339 if (index > 0) try writer.writeAll(", ");
1340 try writer.print("{%} %{d}", .{ param.fmt(self), index });
1720fn bigIntConstAssumeCapacity(
1721 self: *Builder,
1722 ty: Type,
1723 value: std.math.big.int.Const,
1724) if (build_options.have_llvm) Allocator.Error!Constant else Constant {
1725 const type_item = self.type_items.items[@intFromEnum(ty)];
1726 assert(type_item.tag == .integer);
1727 const bits = type_item.data;
1728
1729 const ExpectedContents = extern struct {
1730 limbs: [64 / @sizeOf(std.math.big.Limb)]std.math.big.Limb,
1731 llvm_limbs: if (build_options.have_llvm) [64 / @sizeOf(u64)]u64 else void,
1732 };
1733 var stack align(@alignOf(ExpectedContents)) =
1734 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
1735 const allocator = stack.get();
1736
1737 var limbs: []std.math.big.Limb = &.{};
1738 defer allocator.free(limbs);
1739 const canonical_value = if (value.fitsInTwosComp(.signed, bits)) value else canon: {
1740 assert(value.fitsInTwosComp(.unsigned, bits));
1741 limbs = try allocator.alloc(std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(bits));
1742 var temp_value = std.math.big.int.Mutable.init(limbs, 0);
1743 temp_value.truncate(value, .signed, bits);
1744 break :canon temp_value.toConst();
1745 };
1746 assert(canonical_value.fitsInTwosComp(.signed, bits));
1747
1748 const ExtraPtr = *align(@alignOf(std.math.big.Limb)) Constant.Integer;
1749 const Key = struct { tag: Constant.Tag, type: Type, limbs: []const std.math.big.Limb };
1750 const tag: Constant.Tag = switch (canonical_value.positive) {
1751 true => .integer_positive,
1752 false => .integer_negative,
1753 };
1754 const Adapter = struct {
1755 builder: *const Builder,
1756 pub fn hash(_: @This(), key: Key) u32 {
1757 var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag)));
1758 hasher.update(std.mem.asBytes(&key.type));
1759 hasher.update(std.mem.sliceAsBytes(key.limbs));
1760 return @truncate(hasher.final());
13411761 }
1342 switch (item.tag) {
1343 .function => {},
1344 .vararg_function => {
1345 if (params.len > 0) try writer.writeAll(", ");
1346 try writer.writeAll("...");
1347 },
1348 else => unreachable,
1762 pub fn eql(ctx: @This(), lhs: Key, _: void, rhs_index: usize) bool {
1763 if (lhs.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false;
1764 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
1765 const rhs_extra: ExtraPtr = @ptrCast(
1766 ctx.builder.constant_limbs.items[rhs_data..][0..Constant.Integer.limbs],
1767 );
1768 const rhs_limbs = ctx.builder.constant_limbs
1769 .items[rhs_data + Constant.Integer.limbs ..][0..rhs_extra.limbs_len];
1770 return lhs.type == rhs_extra.type and std.mem.eql(std.math.big.Limb, lhs.limbs, rhs_limbs);
13491771 }
1350 try writer.print(") {}{}", .{
1351 global.value.unnamed_addr,
1352 global.value.alignment,
1353 });
1354 if (function.body) |_| try writer.print(
1355 \\{{
1356 \\ ret {%}
1357 \\}}
1358 \\
1359 , .{
1360 extra.data.ret.fmt(self),
1772 };
1773
1774 const data = Key{ .tag = tag, .type = ty, .limbs = canonical_value.limbs };
1775 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
1776 if (!gop.found_existing) {
1777 gop.key_ptr.* = {};
1778 gop.value_ptr.* = {};
1779 self.constant_items.appendAssumeCapacity(.{
1780 .tag = tag,
1781 .data = @intCast(self.constant_limbs.items.len),
13611782 });
1362 try writer.writeByte('\n');
1783 const extra: ExtraPtr = @ptrCast(
1784 self.constant_limbs.addManyAsArrayAssumeCapacity(Constant.Integer.limbs),
1785 );
1786 extra.* = .{ .type = ty, .limbs_len = @intCast(canonical_value.limbs.len) };
1787 self.constant_limbs.appendSliceAssumeCapacity(canonical_value.limbs);
1788 if (self.useLibLlvm()) {
1789 const llvm_type = ty.toLlvm(self);
1790 if (canonical_value.to(c_longlong)) |small| {
1791 self.llvm_constants.appendAssumeCapacity(llvm_type.constInt(@bitCast(small), .True));
1792 } else |_| if (canonical_value.to(c_ulonglong)) |small| {
1793 self.llvm_constants.appendAssumeCapacity(llvm_type.constInt(small, .False));
1794 } else |_| {
1795 const llvm_limbs = try allocator.alloc(u64, std.math.divCeil(
1796 usize,
1797 canonical_value.bitCountTwosComp(),
1798 @bitSizeOf(u64),
1799 ) catch unreachable);
1800 defer allocator.free(llvm_limbs);
1801 var limb_index: usize = 0;
1802 var borrow: std.math.big.Limb = 0;
1803 for (llvm_limbs) |*result_limb| {
1804 var llvm_limb: u64 = 0;
1805 inline for (0..Constant.Integer.limbs) |shift| {
1806 const limb = if (limb_index < canonical_value.limbs.len)
1807 canonical_value.limbs[limb_index]
1808 else
1809 0;
1810 limb_index += 1;
1811 llvm_limb |= @as(u64, limb) << shift * @bitSizeOf(std.math.big.Limb);
1812 }
1813 if (!canonical_value.positive) {
1814 const overflow = @subWithOverflow(borrow, llvm_limb);
1815 llvm_limb = overflow[0];
1816 borrow -%= overflow[1];
1817 assert(borrow == 0 or borrow == std.math.maxInt(u64));
1818 }
1819 result_limb.* = llvm_limb;
1820 }
1821 self.llvm_constants.appendAssumeCapacity(
1822 llvm_type.constIntOfArbitraryPrecision(@intCast(llvm_limbs.len), llvm_limbs.ptr),
1823 );
1824 }
1825 }
13631826 }
1827 return @enumFromInt(gop.index);
13641828}
13651829
13661830inline fn useLibLlvm(self: *const Builder) bool {
src/codegen/llvm/bindings.zig+6
......@@ -280,6 +280,9 @@ pub const Value = opaque {
280280
281281 pub const attachMetaData = ZigLLVMAttachMetaData;
282282 extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void;
283
284 pub const dump = LLVMDumpValue;
285 extern fn LLVMDumpValue(Val: *Value) void;
283286};
284287
285288pub const Type = opaque {
......@@ -353,6 +356,9 @@ pub const Type = opaque {
353356 ConstantIndices: [*]const *Value,
354357 NumIndices: c_uint,
355358 ) *Value;
359
360 pub const dump = LLVMDumpType;
361 extern fn LLVMDumpType(Ty: *Type) void;
356362};
357363
358364pub const Module = opaque {