@@ -3665,6 +3665,124 @@ pub const Object = struct {
3665
3665
);
3666
3666
}
3667
3667
3668
+ fn lowerValueToInt(o: *Object, llvm_int_ty: Builder.Type, arg_val: InternPool.Index) Error!Builder.Constant {
3669
+ const mod = o.module;
3670
+ const ip = &mod.intern_pool;
3671
+ const target = mod.getTarget();
3672
+
3673
+ const val = Value.fromInterned(arg_val);
3674
+ const val_key = ip.indexToKey(val.toIntern());
3675
+
3676
+ if (val.isUndefDeep(mod)) return o.builder.undefConst(llvm_int_ty);
3677
+
3678
+ const ty = Type.fromInterned(val_key.typeOf());
3679
+ switch (val_key) {
3680
+ .extern_func => |extern_func| {
3681
+ const fn_decl_index = extern_func.decl;
3682
+ const function_index = try o.resolveLlvmFunction(fn_decl_index);
3683
+ const ptr = function_index.ptrConst(&o.builder).global.toConst();
3684
+ return o.builder.convConst(ptr, llvm_int_ty);
3685
+ },
3686
+ .func => |func| {
3687
+ const fn_decl_index = func.owner_decl;
3688
+ const function_index = try o.resolveLlvmFunction(fn_decl_index);
3689
+ const ptr = function_index.ptrConst(&o.builder).global.toConst();
3690
+ return o.builder.convConst(ptr, llvm_int_ty);
3691
+ },
3692
+ .ptr => return o.builder.convConst(try o.lowerPtr(arg_val, 0), llvm_int_ty),
3693
+ .aggregate => switch (ip.indexToKey(ty.toIntern())) {
3694
+ .struct_type => {
3695
+ const struct_type = ip.loadStructType(ty.toIntern());
3696
+ assert(struct_type.haveLayout(ip));
3697
+ assert(struct_type.layout == .@"packed");
3698
+ comptime assert(Type.packed_struct_layout_version == 2);
3699
+ var running_int = try o.builder.intConst(llvm_int_ty, 0);
3700
+ var running_bits: u16 = 0;
3701
+ for (struct_type.field_types.get(ip), 0..) |field_ty, field_index| {
3702
+ if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;
3703
+
3704
+ const shift_rhs = try o.builder.intConst(llvm_int_ty, running_bits);
3705
+ const field_val = try o.lowerValueToInt(llvm_int_ty, (try val.fieldValue(mod, field_index)).toIntern());
3706
+ const shifted = try o.builder.binConst(.shl, field_val, shift_rhs);
3707
+
3708
+ running_int = try o.builder.binConst(.xor, running_int, shifted);
3709
+
3710
+ const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(mod));
3711
+ running_bits += ty_bit_size;
3712
+ }
3713
+ return running_int;
3714
+ },
3715
+ .vector_type => {},
3716
+ else => unreachable,
3717
+ },
3718
+ .un => |un| {
3719
+ const layout = ty.unionGetLayout(mod);
3720
+ if (layout.payload_size == 0) return o.lowerValue(un.tag);
3721
+
3722
+ const union_obj = mod.typeToUnion(ty).?;
3723
+ const container_layout = union_obj.getLayout(ip);
3724
+
3725
+ assert(container_layout == .@"packed");
3726
+
3727
+ var need_unnamed = false;
3728
+ if (un.tag == .none) {
3729
+ assert(layout.tag_size == 0);
3730
+ const union_val = try o.lowerValueToInt(llvm_int_ty, un.val);
3731
+
3732
+ need_unnamed = true;
3733
+ return union_val;
3734
+ }
3735
+ const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
3736
+ const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
3737
+ if (!field_ty.hasRuntimeBits(mod)) return o.builder.intConst(llvm_int_ty, 0);
3738
+ return o.lowerValueToInt(llvm_int_ty, un.val);
3739
+ },
3740
+ .simple_value => |simple_value| switch (simple_value) {
3741
+ .false, .true => {},
3742
+ else => unreachable,
3743
+ },
3744
+ .int,
3745
+ .float,
3746
+ .enum_tag,
3747
+ => {},
3748
+ else => unreachable,
3749
+ }
3750
+ const bits = ty.bitSize(mod);
3751
+ const bytes: usize = @intCast(std.mem.alignForward(u64, bits, 8) / 8);
3752
+
3753
+ var stack = std.heap.stackFallback(32, o.gpa);
3754
+ const allocator = stack.get();
3755
+
3756
+ const limbs = try allocator.alloc(
3757
+ std.math.big.Limb,
3758
+ std.mem.alignForward(usize, bytes, @sizeOf(std.math.big.Limb)) /
3759
+ @sizeOf(std.math.big.Limb),
3760
+ );
3761
+ defer allocator.free(limbs);
3762
+ @memset(limbs, 0);
3763
+
3764
+ val.writeToPackedMemory(
3765
+ ty,
3766
+ mod,
3767
+ std.mem.sliceAsBytes(limbs)[0..bytes],
3768
+ 0,
3769
+ ) catch unreachable;
3770
+
3771
+ if (builtin.target.cpu.arch.endian() == .little) {
3772
+ if (target.cpu.arch.endian() == .big)
3773
+ std.mem.reverse(u8, std.mem.sliceAsBytes(limbs)[0..bytes]);
3774
+ } else if (target.cpu.arch.endian() == .little) {
3775
+ for (limbs) |*limb| {
3776
+ limb.* = std.mem.nativeToLittle(usize, limb.*);
3777
+ }
3778
+ }
3779
+
3780
+ return o.builder.bigIntConst(llvm_int_ty, .{
3781
+ .limbs = limbs,
3782
+ .positive = true,
3783
+ });
3784
+ }
3785
+
3668
3786
fn lowerValue(o: *Object, arg_val: InternPool.Index) Error!Builder.Constant {
3669
3787
const mod = o.module;
3670
3788
const ip = &mod.intern_pool;
@@ -4022,28 +4140,11 @@ pub const Object = struct {
4022
4140
const struct_ty = try o.lowerType(ty);
4023
4141
if (struct_type.layout == .@"packed") {
4024
4142
comptime assert(Type.packed_struct_layout_version == 2);
4025
- var running_int = try o.builder.intConst(struct_ty, 0);
4026
- var running_bits: u16 = 0;
4027
- for (struct_type.field_types.get(ip), 0..) |field_ty, field_index| {
4028
- if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;
4029
-
4030
- const non_int_val =
4031
- try o.lowerValue((try val.fieldValue(mod, field_index)).toIntern());
4032
- const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(mod));
4033
- const small_int_ty = try o.builder.intType(ty_bit_size);
4034
- const small_int_val = try o.builder.castConst(
4035
- if (Type.fromInterned(field_ty).isPtrAtRuntime(mod)) .ptrtoint else .bitcast,
4036
- non_int_val,
4037
- small_int_ty,
4038
- );
4039
- const shift_rhs = try o.builder.intConst(struct_ty, running_bits);
4040
- const extended_int_val =
4041
- try o.builder.convConst(.unsigned, small_int_val, struct_ty);
4042
- const shifted = try o.builder.binConst(.shl, extended_int_val, shift_rhs);
4043
- running_int = try o.builder.binConst(.@"or", running_int, shifted);
4044
- running_bits += ty_bit_size;
4045
- }
4046
- return running_int;
4143
+
4144
+ const bits = ty.bitSize(mod);
4145
+ const llvm_int_ty = try o.builder.intType(@intCast(bits));
4146
+
4147
+ return o.lowerValueToInt(llvm_int_ty, arg_val);
4047
4148
}
4048
4149
const llvm_len = struct_ty.aggregateLen(&o.builder);
4049
4150
@@ -4138,12 +4239,10 @@ pub const Object = struct {
4138
4239
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
4139
4240
if (container_layout == .@"packed") {
4140
4241
if (!field_ty.hasRuntimeBits(mod)) return o.builder.intConst(union_ty, 0);
4141
- const small_int_val = try o.builder.castConst(
4142
- if (field_ty.isPtrAtRuntime(mod)) .ptrtoint else .bitcast,
4143
- try o.lowerValue(un.val),
4144
- try o.builder.intType(@intCast(field_ty.bitSize(mod))),
4145
- );
4146
- return o.builder.convConst(.unsigned, small_int_val, union_ty);
4242
+ const bits = ty.bitSize(mod);
4243
+ const llvm_int_ty = try o.builder.intType(@intCast(bits));
4244
+
4245
+ return o.lowerValueToInt(llvm_int_ty, arg_val);
4147
4246
}
4148
4247
4149
4248
// Sometimes we must make an unnamed struct because LLVM does
@@ -4171,16 +4270,14 @@ pub const Object = struct {
4171
4270
);
4172
4271
} else p: {
4173
4272
assert(layout.tag_size == 0);
4174
- const union_val = try o.lowerValue(un.val);
4175
4273
if (container_layout == .@"packed") {
4176
- const bitcast_val = try o.builder.castConst(
4177
- .bitcast,
4178
- union_val,
4179
- try o.builder.intType(@intCast(ty.bitSize(mod))),
4180
- );
4181
- return o.builder.convConst(.unsigned, bitcast_val, union_ty);
4274
+ const bits = ty.bitSize(mod);
4275
+ const llvm_int_ty = try o.builder.intType(@intCast(bits));
4276
+
4277
+ return o.lowerValueToInt(llvm_int_ty, arg_val);
4182
4278
}
4183
4279
4280
+ const union_val = try o.lowerValue(un.val);
4184
4281
need_unnamed = true;
4185
4282
break :p union_val;
4186
4283
};
@@ -4316,12 +4413,11 @@ pub const Object = struct {
4316
4413
const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global;
4317
4414
4318
4415
const llvm_val = try o.builder.convConst(
4319
- .unneeded,
4320
4416
llvm_global.toConst(),
4321
4417
try o.builder.ptrType(llvm_addr_space),
4322
4418
);
4323
4419
4324
- return o.builder.convConst(.unneeded, llvm_val, try o.lowerType(ptr_ty));
4420
+ return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty));
4325
4421
}
4326
4422
4327
4423
fn lowerDeclRefValue(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant {
@@ -4359,12 +4455,11 @@ pub const Object = struct {
4359
4455
(try o.resolveGlobalDecl(decl_index)).ptrConst(&o.builder).global;
4360
4456
4361
4457
const llvm_val = try o.builder.convConst(
4362
- .unneeded,
4363
4458
llvm_global.toConst(),
4364
4459
try o.builder.ptrType(toLlvmAddressSpace(decl.@"addrspace", mod.getTarget())),
4365
4460
);
4366
4461
4367
- return o.builder.convConst(.unneeded, llvm_val, try o.lowerType(ptr_ty));
4462
+ return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty));
4368
4463
}
4369
4464
4370
4465
fn lowerPtrToVoid(o: *Object, ptr_ty: Type) Allocator.Error!Builder.Constant {
@@ -4750,7 +4845,6 @@ pub const FuncGen = struct {
4750
4845
variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4751
4846
variable_index.setAlignment(ty.abiAlignment(mod).toLlvm(), &o.builder);
4752
4847
return o.builder.convConst(
4753
- .unneeded,
4754
4848
variable_index.toConst(&o.builder),
4755
4849
try o.builder.ptrType(toLlvmAddressSpace(.generic, target)),
4756
4850
);
@@ -10413,9 +10507,9 @@ pub const FuncGen = struct {
10413
10507
10414
10508
const anded = if (workaround_explicit_mask and payload_llvm_ty != load_llvm_ty) blk: {
10415
10509
// this is rendundant with llvm.trunc. But without it, llvm17 emits invalid code for powerpc.
10416
- var mask_val = try o.builder.intConst (payload_llvm_ty, -1);
10417
- mask_val = try o.builder.castConst (.zext, mask_val, load_llvm_ty);
10418
- break :blk try fg.wip.bin(.@"and", shifted, mask_val.toValue() , "");
10510
+ const mask_val = try o.builder.intValue (payload_llvm_ty, -1);
10511
+ const zext_mask_val = try fg.wip.cast (.zext, mask_val, load_llvm_ty, "" );
10512
+ break :blk try fg.wip.bin(.@"and", shifted, zext_mask_val , "");
10419
10513
} else shifted;
10420
10514
10421
10515
return fg.wip.conv(.unneeded, anded, payload_llvm_ty, "");
@@ -10563,14 +10657,23 @@ pub const FuncGen = struct {
10563
10657
else
10564
10658
try self.wip.cast(.bitcast, elem, value_bits_type, "");
10565
10659
10566
- var mask_val = try o.builder.intConst(value_bits_type, -1);
10567
- mask_val = try o.builder.castConst(.zext, mask_val, containing_int_ty);
10568
- mask_val = try o.builder.binConst(.shl, mask_val, shift_amt);
10569
- mask_val =
10570
- try o.builder.binConst(.xor, mask_val, try o.builder.intConst(containing_int_ty, -1));
10660
+ const mask_val = blk: {
10661
+ const zext = try self.wip.cast(
10662
+ .zext,
10663
+ try o.builder.intValue(value_bits_type, -1),
10664
+ containing_int_ty,
10665
+ "",
10666
+ );
10667
+ const shl = try self.wip.bin(.shl, zext, shift_amt.toValue(), "");
10668
+ break :blk try self.wip.bin(
10669
+ .xor,
10670
+ shl,
10671
+ try o.builder.intValue(containing_int_ty, -1),
10672
+ "",
10673
+ );
10674
+ };
10571
10675
10572
- const anded_containing_int =
10573
- try self.wip.bin(.@"and", containing_int, mask_val.toValue(), "");
10676
+ const anded_containing_int = try self.wip.bin(.@"and", containing_int, mask_val, "");
10574
10677
const extended_value = try self.wip.cast(.zext, value_bits, containing_int_ty, "");
10575
10678
const shifted_value = try self.wip.bin(.shl, extended_value, shift_amt.toValue(), "");
10576
10679
const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, "");
0 commit comments