Skip to content

Commit c231d94

Browse files
antliljaandrewrk
authored andcommitted
LLVM: Remove deprecated or soon to be deprecated constant expressions
1 parent 3648d7d commit c231d94

File tree

2 files changed

+182
-534
lines changed

2 files changed

+182
-534
lines changed

src/codegen/llvm.zig

+153-50
Original file line numberDiff line numberDiff line change
@@ -3665,6 +3665,124 @@ pub const Object = struct {
36653665
);
36663666
}
36673667

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+
36683786
fn lowerValue(o: *Object, arg_val: InternPool.Index) Error!Builder.Constant {
36693787
const mod = o.module;
36703788
const ip = &mod.intern_pool;
@@ -4022,28 +4140,11 @@ pub const Object = struct {
40224140
const struct_ty = try o.lowerType(ty);
40234141
if (struct_type.layout == .@"packed") {
40244142
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);
40474148
}
40484149
const llvm_len = struct_ty.aggregateLen(&o.builder);
40494150

@@ -4138,12 +4239,10 @@ pub const Object = struct {
41384239
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
41394240
if (container_layout == .@"packed") {
41404241
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);
41474246
}
41484247

41494248
// Sometimes we must make an unnamed struct because LLVM does
@@ -4171,16 +4270,14 @@ pub const Object = struct {
41714270
);
41724271
} else p: {
41734272
assert(layout.tag_size == 0);
4174-
const union_val = try o.lowerValue(un.val);
41754273
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);
41824278
}
41834279

4280+
const union_val = try o.lowerValue(un.val);
41844281
need_unnamed = true;
41854282
break :p union_val;
41864283
};
@@ -4316,12 +4413,11 @@ pub const Object = struct {
43164413
const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global;
43174414

43184415
const llvm_val = try o.builder.convConst(
4319-
.unneeded,
43204416
llvm_global.toConst(),
43214417
try o.builder.ptrType(llvm_addr_space),
43224418
);
43234419

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));
43254421
}
43264422

43274423
fn lowerDeclRefValue(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant {
@@ -4359,12 +4455,11 @@ pub const Object = struct {
43594455
(try o.resolveGlobalDecl(decl_index)).ptrConst(&o.builder).global;
43604456

43614457
const llvm_val = try o.builder.convConst(
4362-
.unneeded,
43634458
llvm_global.toConst(),
43644459
try o.builder.ptrType(toLlvmAddressSpace(decl.@"addrspace", mod.getTarget())),
43654460
);
43664461

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));
43684463
}
43694464

43704465
fn lowerPtrToVoid(o: *Object, ptr_ty: Type) Allocator.Error!Builder.Constant {
@@ -4750,7 +4845,6 @@ pub const FuncGen = struct {
47504845
variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
47514846
variable_index.setAlignment(ty.abiAlignment(mod).toLlvm(), &o.builder);
47524847
return o.builder.convConst(
4753-
.unneeded,
47544848
variable_index.toConst(&o.builder),
47554849
try o.builder.ptrType(toLlvmAddressSpace(.generic, target)),
47564850
);
@@ -10413,9 +10507,9 @@ pub const FuncGen = struct {
1041310507

1041410508
const anded = if (workaround_explicit_mask and payload_llvm_ty != load_llvm_ty) blk: {
1041510509
// 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, "");
1041910513
} else shifted;
1042010514

1042110515
return fg.wip.conv(.unneeded, anded, payload_llvm_ty, "");
@@ -10563,14 +10657,23 @@ pub const FuncGen = struct {
1056310657
else
1056410658
try self.wip.cast(.bitcast, elem, value_bits_type, "");
1056510659

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+
};
1057110675

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, "");
1057410677
const extended_value = try self.wip.cast(.zext, value_bits, containing_int_ty, "");
1057510678
const shifted_value = try self.wip.bin(.shl, extended_value, shift_amt.toValue(), "");
1057610679
const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, "");

0 commit comments

Comments
 (0)