mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
LLVM: Remove deprecated or soon to be deprecated constant expressions
This commit is contained in:
parent
3648d7df19
commit
c231d94960
2 changed files with 181 additions and 533 deletions
|
|
@ -3665,6 +3665,124 @@ pub const Object = struct {
|
|||
);
|
||||
}
|
||||
|
||||
fn lowerValueToInt(o: *Object, llvm_int_ty: Builder.Type, arg_val: InternPool.Index) Error!Builder.Constant {
|
||||
const mod = o.module;
|
||||
const ip = &mod.intern_pool;
|
||||
const target = mod.getTarget();
|
||||
|
||||
const val = Value.fromInterned(arg_val);
|
||||
const val_key = ip.indexToKey(val.toIntern());
|
||||
|
||||
if (val.isUndefDeep(mod)) return o.builder.undefConst(llvm_int_ty);
|
||||
|
||||
const ty = Type.fromInterned(val_key.typeOf());
|
||||
switch (val_key) {
|
||||
.extern_func => |extern_func| {
|
||||
const fn_decl_index = extern_func.decl;
|
||||
const function_index = try o.resolveLlvmFunction(fn_decl_index);
|
||||
const ptr = function_index.ptrConst(&o.builder).global.toConst();
|
||||
return o.builder.convConst(ptr, llvm_int_ty);
|
||||
},
|
||||
.func => |func| {
|
||||
const fn_decl_index = func.owner_decl;
|
||||
const function_index = try o.resolveLlvmFunction(fn_decl_index);
|
||||
const ptr = function_index.ptrConst(&o.builder).global.toConst();
|
||||
return o.builder.convConst(ptr, llvm_int_ty);
|
||||
},
|
||||
.ptr => return o.builder.convConst(try o.lowerPtr(arg_val, 0), llvm_int_ty),
|
||||
.aggregate => switch (ip.indexToKey(ty.toIntern())) {
|
||||
.struct_type => {
|
||||
const struct_type = ip.loadStructType(ty.toIntern());
|
||||
assert(struct_type.haveLayout(ip));
|
||||
assert(struct_type.layout == .@"packed");
|
||||
comptime assert(Type.packed_struct_layout_version == 2);
|
||||
var running_int = try o.builder.intConst(llvm_int_ty, 0);
|
||||
var running_bits: u16 = 0;
|
||||
for (struct_type.field_types.get(ip), 0..) |field_ty, field_index| {
|
||||
if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||
|
||||
const shift_rhs = try o.builder.intConst(llvm_int_ty, running_bits);
|
||||
const field_val = try o.lowerValueToInt(llvm_int_ty, (try val.fieldValue(mod, field_index)).toIntern());
|
||||
const shifted = try o.builder.binConst(.shl, field_val, shift_rhs);
|
||||
|
||||
running_int = try o.builder.binConst(.xor, running_int, shifted);
|
||||
|
||||
const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(mod));
|
||||
running_bits += ty_bit_size;
|
||||
}
|
||||
return running_int;
|
||||
},
|
||||
.vector_type => {},
|
||||
else => unreachable,
|
||||
},
|
||||
.un => |un| {
|
||||
const layout = ty.unionGetLayout(mod);
|
||||
if (layout.payload_size == 0) return o.lowerValue(un.tag);
|
||||
|
||||
const union_obj = mod.typeToUnion(ty).?;
|
||||
const container_layout = union_obj.getLayout(ip);
|
||||
|
||||
assert(container_layout == .@"packed");
|
||||
|
||||
var need_unnamed = false;
|
||||
if (un.tag == .none) {
|
||||
assert(layout.tag_size == 0);
|
||||
const union_val = try o.lowerValueToInt(llvm_int_ty, un.val);
|
||||
|
||||
need_unnamed = true;
|
||||
return union_val;
|
||||
}
|
||||
const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
|
||||
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
|
||||
if (!field_ty.hasRuntimeBits(mod)) return o.builder.intConst(llvm_int_ty, 0);
|
||||
return o.lowerValueToInt(llvm_int_ty, un.val);
|
||||
},
|
||||
.simple_value => |simple_value| switch (simple_value) {
|
||||
.false, .true => {},
|
||||
else => unreachable,
|
||||
},
|
||||
.int,
|
||||
.float,
|
||||
.enum_tag,
|
||||
=> {},
|
||||
else => unreachable,
|
||||
}
|
||||
const bits = ty.bitSize(mod);
|
||||
const bytes: usize = @intCast(std.mem.alignForward(u64, bits, 8) / 8);
|
||||
|
||||
var stack = std.heap.stackFallback(32, o.gpa);
|
||||
const allocator = stack.get();
|
||||
|
||||
const limbs = try allocator.alloc(
|
||||
std.math.big.Limb,
|
||||
std.mem.alignForward(usize, bytes, @sizeOf(std.math.big.Limb)) /
|
||||
@sizeOf(std.math.big.Limb),
|
||||
);
|
||||
defer allocator.free(limbs);
|
||||
@memset(limbs, 0);
|
||||
|
||||
val.writeToPackedMemory(
|
||||
ty,
|
||||
mod,
|
||||
std.mem.sliceAsBytes(limbs)[0..bytes],
|
||||
0,
|
||||
) catch unreachable;
|
||||
|
||||
if (builtin.target.cpu.arch.endian() == .little) {
|
||||
if (target.cpu.arch.endian() == .big)
|
||||
std.mem.reverse(u8, std.mem.sliceAsBytes(limbs)[0..bytes]);
|
||||
} else if (target.cpu.arch.endian() == .little) {
|
||||
for (limbs) |*limb| {
|
||||
limb.* = std.mem.nativeToLittle(usize, limb.*);
|
||||
}
|
||||
}
|
||||
|
||||
return o.builder.bigIntConst(llvm_int_ty, .{
|
||||
.limbs = limbs,
|
||||
.positive = true,
|
||||
});
|
||||
}
|
||||
|
||||
fn lowerValue(o: *Object, arg_val: InternPool.Index) Error!Builder.Constant {
|
||||
const mod = o.module;
|
||||
const ip = &mod.intern_pool;
|
||||
|
|
@ -4022,28 +4140,11 @@ pub const Object = struct {
|
|||
const struct_ty = try o.lowerType(ty);
|
||||
if (struct_type.layout == .@"packed") {
|
||||
comptime assert(Type.packed_struct_layout_version == 2);
|
||||
var running_int = try o.builder.intConst(struct_ty, 0);
|
||||
var running_bits: u16 = 0;
|
||||
for (struct_type.field_types.get(ip), 0..) |field_ty, field_index| {
|
||||
if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;
|
||||
|
||||
const non_int_val =
|
||||
try o.lowerValue((try val.fieldValue(mod, field_index)).toIntern());
|
||||
const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(mod));
|
||||
const small_int_ty = try o.builder.intType(ty_bit_size);
|
||||
const small_int_val = try o.builder.castConst(
|
||||
if (Type.fromInterned(field_ty).isPtrAtRuntime(mod)) .ptrtoint else .bitcast,
|
||||
non_int_val,
|
||||
small_int_ty,
|
||||
);
|
||||
const shift_rhs = try o.builder.intConst(struct_ty, running_bits);
|
||||
const extended_int_val =
|
||||
try o.builder.convConst(.unsigned, small_int_val, struct_ty);
|
||||
const shifted = try o.builder.binConst(.shl, extended_int_val, shift_rhs);
|
||||
running_int = try o.builder.binConst(.@"or", running_int, shifted);
|
||||
running_bits += ty_bit_size;
|
||||
}
|
||||
return running_int;
|
||||
const bits = ty.bitSize(mod);
|
||||
const llvm_int_ty = try o.builder.intType(@intCast(bits));
|
||||
|
||||
return o.lowerValueToInt(llvm_int_ty, arg_val);
|
||||
}
|
||||
const llvm_len = struct_ty.aggregateLen(&o.builder);
|
||||
|
||||
|
|
@ -4138,12 +4239,10 @@ pub const Object = struct {
|
|||
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
|
||||
if (container_layout == .@"packed") {
|
||||
if (!field_ty.hasRuntimeBits(mod)) return o.builder.intConst(union_ty, 0);
|
||||
const small_int_val = try o.builder.castConst(
|
||||
if (field_ty.isPtrAtRuntime(mod)) .ptrtoint else .bitcast,
|
||||
try o.lowerValue(un.val),
|
||||
try o.builder.intType(@intCast(field_ty.bitSize(mod))),
|
||||
);
|
||||
return o.builder.convConst(.unsigned, small_int_val, union_ty);
|
||||
const bits = ty.bitSize(mod);
|
||||
const llvm_int_ty = try o.builder.intType(@intCast(bits));
|
||||
|
||||
return o.lowerValueToInt(llvm_int_ty, arg_val);
|
||||
}
|
||||
|
||||
// Sometimes we must make an unnamed struct because LLVM does
|
||||
|
|
@ -4171,16 +4270,14 @@ pub const Object = struct {
|
|||
);
|
||||
} else p: {
|
||||
assert(layout.tag_size == 0);
|
||||
const union_val = try o.lowerValue(un.val);
|
||||
if (container_layout == .@"packed") {
|
||||
const bitcast_val = try o.builder.castConst(
|
||||
.bitcast,
|
||||
union_val,
|
||||
try o.builder.intType(@intCast(ty.bitSize(mod))),
|
||||
);
|
||||
return o.builder.convConst(.unsigned, bitcast_val, union_ty);
|
||||
const bits = ty.bitSize(mod);
|
||||
const llvm_int_ty = try o.builder.intType(@intCast(bits));
|
||||
|
||||
return o.lowerValueToInt(llvm_int_ty, arg_val);
|
||||
}
|
||||
|
||||
const union_val = try o.lowerValue(un.val);
|
||||
need_unnamed = true;
|
||||
break :p union_val;
|
||||
};
|
||||
|
|
@ -4316,12 +4413,11 @@ pub const Object = struct {
|
|||
const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global;
|
||||
|
||||
const llvm_val = try o.builder.convConst(
|
||||
.unneeded,
|
||||
llvm_global.toConst(),
|
||||
try o.builder.ptrType(llvm_addr_space),
|
||||
);
|
||||
|
||||
return o.builder.convConst(.unneeded, llvm_val, try o.lowerType(ptr_ty));
|
||||
return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty));
|
||||
}
|
||||
|
||||
fn lowerDeclRefValue(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant {
|
||||
|
|
@ -4359,12 +4455,11 @@ pub const Object = struct {
|
|||
(try o.resolveGlobalDecl(decl_index)).ptrConst(&o.builder).global;
|
||||
|
||||
const llvm_val = try o.builder.convConst(
|
||||
.unneeded,
|
||||
llvm_global.toConst(),
|
||||
try o.builder.ptrType(toLlvmAddressSpace(decl.@"addrspace", mod.getTarget())),
|
||||
);
|
||||
|
||||
return o.builder.convConst(.unneeded, llvm_val, try o.lowerType(ptr_ty));
|
||||
return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty));
|
||||
}
|
||||
|
||||
fn lowerPtrToVoid(o: *Object, ptr_ty: Type) Allocator.Error!Builder.Constant {
|
||||
|
|
@ -4750,7 +4845,6 @@ pub const FuncGen = struct {
|
|||
variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
|
||||
variable_index.setAlignment(ty.abiAlignment(mod).toLlvm(), &o.builder);
|
||||
return o.builder.convConst(
|
||||
.unneeded,
|
||||
variable_index.toConst(&o.builder),
|
||||
try o.builder.ptrType(toLlvmAddressSpace(.generic, target)),
|
||||
);
|
||||
|
|
@ -10413,9 +10507,9 @@ pub const FuncGen = struct {
|
|||
|
||||
const anded = if (workaround_explicit_mask and payload_llvm_ty != load_llvm_ty) blk: {
|
||||
// this is rendundant with llvm.trunc. But without it, llvm17 emits invalid code for powerpc.
|
||||
var mask_val = try o.builder.intConst(payload_llvm_ty, -1);
|
||||
mask_val = try o.builder.castConst(.zext, mask_val, load_llvm_ty);
|
||||
break :blk try fg.wip.bin(.@"and", shifted, mask_val.toValue(), "");
|
||||
const mask_val = try o.builder.intValue(payload_llvm_ty, -1);
|
||||
const zext_mask_val = try fg.wip.cast(.zext, mask_val, load_llvm_ty, "");
|
||||
break :blk try fg.wip.bin(.@"and", shifted, zext_mask_val, "");
|
||||
} else shifted;
|
||||
|
||||
return fg.wip.conv(.unneeded, anded, payload_llvm_ty, "");
|
||||
|
|
@ -10563,14 +10657,23 @@ pub const FuncGen = struct {
|
|||
else
|
||||
try self.wip.cast(.bitcast, elem, value_bits_type, "");
|
||||
|
||||
var mask_val = try o.builder.intConst(value_bits_type, -1);
|
||||
mask_val = try o.builder.castConst(.zext, mask_val, containing_int_ty);
|
||||
mask_val = try o.builder.binConst(.shl, mask_val, shift_amt);
|
||||
mask_val =
|
||||
try o.builder.binConst(.xor, mask_val, try o.builder.intConst(containing_int_ty, -1));
|
||||
const mask_val = blk: {
|
||||
const zext = try self.wip.cast(
|
||||
.zext,
|
||||
try o.builder.intValue(value_bits_type, -1),
|
||||
containing_int_ty,
|
||||
"",
|
||||
);
|
||||
const shl = try self.wip.bin(.shl, zext, shift_amt.toValue(), "");
|
||||
break :blk try self.wip.bin(
|
||||
.xor,
|
||||
shl,
|
||||
try o.builder.intValue(containing_int_ty, -1),
|
||||
"",
|
||||
);
|
||||
};
|
||||
|
||||
const anded_containing_int =
|
||||
try self.wip.bin(.@"and", containing_int, mask_val.toValue(), "");
|
||||
const anded_containing_int = try self.wip.bin(.@"and", containing_int, mask_val, "");
|
||||
const extended_value = try self.wip.cast(.zext, value_bits, containing_int_ty, "");
|
||||
const shifted_value = try self.wip.bin(.shl, extended_value, shift_amt.toValue(), "");
|
||||
const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, "");
|
||||
|
|
|
|||
|
|
@ -5694,7 +5694,7 @@ pub const WipFunction = struct {
|
|||
) Allocator.Error!Value {
|
||||
const val_ty = val.typeOfWip(self);
|
||||
if (val_ty == ty) return val;
|
||||
return self.cast(self.builder.convTag(Instruction.Tag, signedness, val_ty, ty), val, ty, name);
|
||||
return self.cast(self.builder.convTag(signedness, val_ty, ty), val, ty, name);
|
||||
}
|
||||
|
||||
pub fn cast(
|
||||
|
|
@ -6891,39 +6891,19 @@ pub const Constant = enum(u32) {
|
|||
dso_local_equivalent,
|
||||
no_cfi,
|
||||
trunc,
|
||||
zext,
|
||||
sext,
|
||||
fptrunc,
|
||||
fpext,
|
||||
fptoui,
|
||||
fptosi,
|
||||
uitofp,
|
||||
sitofp,
|
||||
ptrtoint,
|
||||
inttoptr,
|
||||
bitcast,
|
||||
addrspacecast,
|
||||
getelementptr,
|
||||
@"getelementptr inbounds",
|
||||
icmp,
|
||||
fcmp,
|
||||
extractelement,
|
||||
insertelement,
|
||||
shufflevector,
|
||||
add,
|
||||
@"add nsw",
|
||||
@"add nuw",
|
||||
sub,
|
||||
@"sub nsw",
|
||||
@"sub nuw",
|
||||
mul,
|
||||
@"mul nsw",
|
||||
@"mul nuw",
|
||||
shl,
|
||||
lshr,
|
||||
ashr,
|
||||
@"and",
|
||||
@"or",
|
||||
xor,
|
||||
@"asm",
|
||||
@"asm sideeffect",
|
||||
|
|
@ -6952,15 +6932,7 @@ pub const Constant = enum(u32) {
|
|||
.@"sub nsw",
|
||||
.@"sub nuw",
|
||||
=> .sub,
|
||||
.mul,
|
||||
.@"mul nsw",
|
||||
.@"mul nuw",
|
||||
=> .mul,
|
||||
.shl => .shl,
|
||||
.lshr => .lshr,
|
||||
.ashr => .ashr,
|
||||
.@"and" => .@"and",
|
||||
.@"or" => .@"or",
|
||||
.xor => .xor,
|
||||
else => unreachable,
|
||||
};
|
||||
|
|
@ -6969,14 +6941,6 @@ pub const Constant = enum(u32) {
|
|||
pub fn toCastOpcode(self: Tag) CastOpcode {
|
||||
return switch (self) {
|
||||
.trunc => .trunc,
|
||||
.zext => .zext,
|
||||
.sext => .sext,
|
||||
.fptoui => .fptoui,
|
||||
.fptosi => .fptosi,
|
||||
.uitofp => .uitofp,
|
||||
.sitofp => .sitofp,
|
||||
.fptrunc => .fptrunc,
|
||||
.fpext => .fpext,
|
||||
.ptrtoint => .ptrtoint,
|
||||
.inttoptr => .inttoptr,
|
||||
.bitcast => .bitcast,
|
||||
|
|
@ -7051,29 +7015,6 @@ pub const Constant = enum(u32) {
|
|||
pub const Info = packed struct(u32) { indices_len: u16, inrange: InRangeIndex };
|
||||
};
|
||||
|
||||
pub const Compare = extern struct {
|
||||
cond: u32,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
};
|
||||
|
||||
pub const ExtractElement = extern struct {
|
||||
val: Constant,
|
||||
index: Constant,
|
||||
};
|
||||
|
||||
pub const InsertElement = extern struct {
|
||||
val: Constant,
|
||||
elem: Constant,
|
||||
index: Constant,
|
||||
};
|
||||
|
||||
pub const ShuffleVector = extern struct {
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
mask: Constant,
|
||||
};
|
||||
|
||||
pub const Binary = extern struct {
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
|
|
@ -7149,14 +7090,6 @@ pub const Constant = enum(u32) {
|
|||
=> builder.ptrTypeAssumeCapacity(@as(Function.Index, @enumFromInt(item.data))
|
||||
.ptrConst(builder).global.ptrConst(builder).addr_space),
|
||||
.trunc,
|
||||
.zext,
|
||||
.sext,
|
||||
.fptrunc,
|
||||
.fpext,
|
||||
.fptoui,
|
||||
.fptosi,
|
||||
.uitofp,
|
||||
.sitofp,
|
||||
.ptrtoint,
|
||||
.inttoptr,
|
||||
.bitcast,
|
||||
|
|
@ -7176,35 +7109,13 @@ pub const Constant = enum(u32) {
|
|||
};
|
||||
return base_ty;
|
||||
},
|
||||
.icmp,
|
||||
.fcmp,
|
||||
=> builder.constantExtraData(Compare, item.data).lhs.typeOf(builder)
|
||||
.changeScalarAssumeCapacity(.i1, builder),
|
||||
.extractelement => builder.constantExtraData(ExtractElement, item.data)
|
||||
.val.typeOf(builder).childType(builder),
|
||||
.insertelement => builder.constantExtraData(InsertElement, item.data)
|
||||
.val.typeOf(builder),
|
||||
.shufflevector => {
|
||||
const extra = builder.constantExtraData(ShuffleVector, item.data);
|
||||
return extra.lhs.typeOf(builder).changeLengthAssumeCapacity(
|
||||
extra.mask.typeOf(builder).vectorLen(builder),
|
||||
builder,
|
||||
);
|
||||
},
|
||||
.add,
|
||||
.@"add nsw",
|
||||
.@"add nuw",
|
||||
.sub,
|
||||
.@"sub nsw",
|
||||
.@"sub nuw",
|
||||
.mul,
|
||||
.@"mul nsw",
|
||||
.@"mul nuw",
|
||||
.shl,
|
||||
.lshr,
|
||||
.ashr,
|
||||
.@"and",
|
||||
.@"or",
|
||||
.xor,
|
||||
=> builder.constantExtraData(Binary, item.data).lhs.typeOf(builder),
|
||||
.@"asm",
|
||||
|
|
@ -7516,14 +7427,6 @@ pub const Constant = enum(u32) {
|
|||
});
|
||||
},
|
||||
.trunc,
|
||||
.zext,
|
||||
.sext,
|
||||
.fptrunc,
|
||||
.fpext,
|
||||
.fptoui,
|
||||
.fptosi,
|
||||
.uitofp,
|
||||
.sitofp,
|
||||
.ptrtoint,
|
||||
.inttoptr,
|
||||
.bitcast,
|
||||
|
|
@ -7550,61 +7453,13 @@ pub const Constant = enum(u32) {
|
|||
for (indices) |index| try writer.print(", {%}", .{index.fmt(data.builder)});
|
||||
try writer.writeByte(')');
|
||||
},
|
||||
inline .icmp,
|
||||
.fcmp,
|
||||
=> |tag| {
|
||||
const extra = data.builder.constantExtraData(Compare, item.data);
|
||||
try writer.print("{s} {s} ({%}, {%})", .{
|
||||
@tagName(tag),
|
||||
@tagName(@as(switch (tag) {
|
||||
.icmp => IntegerCondition,
|
||||
.fcmp => FloatCondition,
|
||||
else => unreachable,
|
||||
}, @enumFromInt(extra.cond))),
|
||||
extra.lhs.fmt(data.builder),
|
||||
extra.rhs.fmt(data.builder),
|
||||
});
|
||||
},
|
||||
.extractelement => |tag| {
|
||||
const extra = data.builder.constantExtraData(ExtractElement, item.data);
|
||||
try writer.print("{s} ({%}, {%})", .{
|
||||
@tagName(tag),
|
||||
extra.val.fmt(data.builder),
|
||||
extra.index.fmt(data.builder),
|
||||
});
|
||||
},
|
||||
.insertelement => |tag| {
|
||||
const extra = data.builder.constantExtraData(InsertElement, item.data);
|
||||
try writer.print("{s} ({%}, {%}, {%})", .{
|
||||
@tagName(tag),
|
||||
extra.val.fmt(data.builder),
|
||||
extra.elem.fmt(data.builder),
|
||||
extra.index.fmt(data.builder),
|
||||
});
|
||||
},
|
||||
.shufflevector => |tag| {
|
||||
const extra = data.builder.constantExtraData(ShuffleVector, item.data);
|
||||
try writer.print("{s} ({%}, {%}, {%})", .{
|
||||
@tagName(tag),
|
||||
extra.lhs.fmt(data.builder),
|
||||
extra.rhs.fmt(data.builder),
|
||||
extra.mask.fmt(data.builder),
|
||||
});
|
||||
},
|
||||
.add,
|
||||
.@"add nsw",
|
||||
.@"add nuw",
|
||||
.sub,
|
||||
.@"sub nsw",
|
||||
.@"sub nuw",
|
||||
.mul,
|
||||
.@"mul nsw",
|
||||
.@"mul nuw",
|
||||
.shl,
|
||||
.lshr,
|
||||
.ashr,
|
||||
.@"and",
|
||||
.@"or",
|
||||
.xor,
|
||||
=> |tag| {
|
||||
const extra = data.builder.constantExtraData(Binary, item.data);
|
||||
|
|
@ -9278,21 +9133,19 @@ pub fn noCfiValue(self: *Builder, function: Function.Index) Allocator.Error!Valu
|
|||
|
||||
pub fn convConst(
|
||||
self: *Builder,
|
||||
signedness: Constant.Cast.Signedness,
|
||||
val: Constant,
|
||||
ty: Type,
|
||||
) Allocator.Error!Constant {
|
||||
try self.ensureUnusedConstantCapacity(1, Constant.Cast, 0);
|
||||
return self.convConstAssumeCapacity(signedness, val, ty);
|
||||
return self.convConstAssumeCapacity(val, ty);
|
||||
}
|
||||
|
||||
pub fn convValue(
|
||||
self: *Builder,
|
||||
signedness: Constant.Cast.Signedness,
|
||||
val: Constant,
|
||||
ty: Type,
|
||||
) Allocator.Error!Value {
|
||||
return (try self.convConst(signedness, val, ty)).toValue();
|
||||
return (try self.convConst(val, ty)).toValue();
|
||||
}
|
||||
|
||||
pub fn castConst(self: *Builder, tag: Constant.Tag, val: Constant, ty: Type) Allocator.Error!Constant {
|
||||
|
|
@ -9328,92 +9181,6 @@ pub fn gepValue(
|
|||
return (try self.gepConst(kind, ty, base, inrange, indices)).toValue();
|
||||
}
|
||||
|
||||
pub fn icmpConst(
|
||||
self: *Builder,
|
||||
cond: IntegerCondition,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
) Allocator.Error!Constant {
|
||||
try self.ensureUnusedConstantCapacity(1, Constant.Compare, 0);
|
||||
return self.icmpConstAssumeCapacity(cond, lhs, rhs);
|
||||
}
|
||||
|
||||
pub fn icmpValue(
|
||||
self: *Builder,
|
||||
cond: IntegerCondition,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
) Allocator.Error!Value {
|
||||
return (try self.icmpConst(cond, lhs, rhs)).toValue();
|
||||
}
|
||||
|
||||
pub fn fcmpConst(
|
||||
self: *Builder,
|
||||
cond: FloatCondition,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
) Allocator.Error!Constant {
|
||||
try self.ensureUnusedConstantCapacity(1, Constant.Compare, 0);
|
||||
return self.icmpConstAssumeCapacity(cond, lhs, rhs);
|
||||
}
|
||||
|
||||
pub fn fcmpValue(
|
||||
self: *Builder,
|
||||
cond: FloatCondition,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
) Allocator.Error!Value {
|
||||
return (try self.fcmpConst(cond, lhs, rhs)).toValue();
|
||||
}
|
||||
|
||||
pub fn extractElementConst(self: *Builder, val: Constant, index: Constant) Allocator.Error!Constant {
|
||||
try self.ensureUnusedConstantCapacity(1, Constant.ExtractElement, 0);
|
||||
return self.extractElementConstAssumeCapacity(val, index);
|
||||
}
|
||||
|
||||
pub fn extractElementValue(self: *Builder, val: Constant, index: Constant) Allocator.Error!Value {
|
||||
return (try self.extractElementConst(val, index)).toValue();
|
||||
}
|
||||
|
||||
pub fn insertElementConst(
|
||||
self: *Builder,
|
||||
val: Constant,
|
||||
elem: Constant,
|
||||
index: Constant,
|
||||
) Allocator.Error!Constant {
|
||||
try self.ensureUnusedConstantCapacity(1, Constant.InsertElement, 0);
|
||||
return self.insertElementConstAssumeCapacity(val, elem, index);
|
||||
}
|
||||
|
||||
pub fn insertElementValue(
|
||||
self: *Builder,
|
||||
val: Constant,
|
||||
elem: Constant,
|
||||
index: Constant,
|
||||
) Allocator.Error!Value {
|
||||
return (try self.insertElementConst(val, elem, index)).toValue();
|
||||
}
|
||||
|
||||
pub fn shuffleVectorConst(
|
||||
self: *Builder,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
mask: Constant,
|
||||
) Allocator.Error!Constant {
|
||||
try self.ensureUnusedTypeCapacity(1, Type.Array, 0);
|
||||
try self.ensureUnusedConstantCapacity(1, Constant.ShuffleVector, 0);
|
||||
return self.shuffleVectorConstAssumeCapacity(lhs, rhs, mask);
|
||||
}
|
||||
|
||||
pub fn shuffleVectorValue(
|
||||
self: *Builder,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
mask: Constant,
|
||||
) Allocator.Error!Value {
|
||||
return (try self.shuffleVectorConst(lhs, rhs, mask)).toValue();
|
||||
}
|
||||
|
||||
pub fn binConst(
|
||||
self: *Builder,
|
||||
tag: Constant.Tag,
|
||||
|
|
@ -11390,11 +11157,10 @@ fn noCfiConstAssumeCapacity(self: *Builder, function: Function.Index) Constant {
|
|||
|
||||
fn convTag(
|
||||
self: *Builder,
|
||||
comptime Tag: type,
|
||||
signedness: Constant.Cast.Signedness,
|
||||
val_ty: Type,
|
||||
ty: Type,
|
||||
) Tag {
|
||||
) Function.Instruction.Tag {
|
||||
assert(val_ty != ty);
|
||||
return switch (val_ty.scalarTag(self)) {
|
||||
.simple => switch (ty.scalarTag(self)) {
|
||||
|
|
@ -11437,15 +11203,38 @@ fn convTag(
|
|||
};
|
||||
}
|
||||
|
||||
fn convConstTag(
|
||||
self: *Builder,
|
||||
val_ty: Type,
|
||||
ty: Type,
|
||||
) Constant.Tag {
|
||||
assert(val_ty != ty);
|
||||
return switch (val_ty.scalarTag(self)) {
|
||||
.integer => switch (ty.scalarTag(self)) {
|
||||
.integer => switch (std.math.order(val_ty.scalarBits(self), ty.scalarBits(self))) {
|
||||
.gt => .trunc,
|
||||
else => unreachable,
|
||||
},
|
||||
.pointer => .inttoptr,
|
||||
else => unreachable,
|
||||
},
|
||||
.pointer => switch (ty.scalarTag(self)) {
|
||||
.integer => .ptrtoint,
|
||||
.pointer => .addrspacecast,
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
fn convConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
signedness: Constant.Cast.Signedness,
|
||||
val: Constant,
|
||||
ty: Type,
|
||||
) Constant {
|
||||
const val_ty = val.typeOf(self);
|
||||
if (val_ty == ty) return val;
|
||||
return self.castConstAssumeCapacity(self.convTag(Constant.Tag, signedness, val_ty, ty), val, ty);
|
||||
return self.castConstAssumeCapacity(self.convConstTag(val_ty, ty), val, ty);
|
||||
}
|
||||
|
||||
fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty: Type) Constant {
|
||||
|
|
@ -11570,179 +11359,6 @@ fn gepConstAssumeCapacity(
|
|||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn icmpConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
cond: IntegerCondition,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
) Constant {
|
||||
const Adapter = struct {
|
||||
builder: *const Builder,
|
||||
pub fn hash(_: @This(), key: Constant.Compare) u32 {
|
||||
return @truncate(std.hash.Wyhash.hash(
|
||||
std.hash.uint32(@intFromEnum(Constant.tag.icmp)),
|
||||
std.mem.asBytes(&key),
|
||||
));
|
||||
}
|
||||
pub fn eql(ctx: @This(), lhs_key: Constant.Compare, _: void, rhs_index: usize) bool {
|
||||
if (ctx.builder.constant_items.items(.tag)[rhs_index] != .icmp) return false;
|
||||
const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
|
||||
const rhs_extra = ctx.builder.constantExtraData(Constant.Compare, rhs_data);
|
||||
return std.meta.eql(lhs_key, rhs_extra);
|
||||
}
|
||||
};
|
||||
const data = Constant.Compare{ .cond = @intFromEnum(cond), .lhs = lhs, .rhs = rhs };
|
||||
const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
|
||||
if (!gop.found_existing) {
|
||||
gop.key_ptr.* = {};
|
||||
gop.value_ptr.* = {};
|
||||
self.constant_items.appendAssumeCapacity(.{
|
||||
.tag = .icmp,
|
||||
.data = self.addConstantExtraAssumeCapacity(data),
|
||||
});
|
||||
}
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn fcmpConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
cond: FloatCondition,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
) Constant {
|
||||
const Adapter = struct {
|
||||
builder: *const Builder,
|
||||
pub fn hash(_: @This(), key: Constant.Compare) u32 {
|
||||
return @truncate(std.hash.Wyhash.hash(
|
||||
std.hash.uint32(@intFromEnum(Constant.tag.fcmp)),
|
||||
std.mem.asBytes(&key),
|
||||
));
|
||||
}
|
||||
pub fn eql(ctx: @This(), lhs_key: Constant.Compare, _: void, rhs_index: usize) bool {
|
||||
if (ctx.builder.constant_items.items(.tag)[rhs_index] != .fcmp) return false;
|
||||
const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
|
||||
const rhs_extra = ctx.builder.constantExtraData(Constant.Compare, rhs_data);
|
||||
return std.meta.eql(lhs_key, rhs_extra);
|
||||
}
|
||||
};
|
||||
const data = Constant.Compare{ .cond = @intFromEnum(cond), .lhs = lhs, .rhs = rhs };
|
||||
const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
|
||||
if (!gop.found_existing) {
|
||||
gop.key_ptr.* = {};
|
||||
gop.value_ptr.* = {};
|
||||
self.constant_items.appendAssumeCapacity(.{
|
||||
.tag = .fcmp,
|
||||
.data = self.addConstantExtraAssumeCapacity(data),
|
||||
});
|
||||
}
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn extractElementConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
val: Constant,
|
||||
index: Constant,
|
||||
) Constant {
|
||||
const Adapter = struct {
|
||||
builder: *const Builder,
|
||||
pub fn hash(_: @This(), key: Constant.ExtractElement) u32 {
|
||||
return @truncate(std.hash.Wyhash.hash(
|
||||
comptime std.hash.uint32(@intFromEnum(Constant.Tag.extractelement)),
|
||||
std.mem.asBytes(&key),
|
||||
));
|
||||
}
|
||||
pub fn eql(ctx: @This(), lhs_key: Constant.ExtractElement, _: void, rhs_index: usize) bool {
|
||||
if (ctx.builder.constant_items.items(.tag)[rhs_index] != .extractelement) return false;
|
||||
const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
|
||||
const rhs_extra = ctx.builder.constantExtraData(Constant.ExtractElement, rhs_data);
|
||||
return std.meta.eql(lhs_key, rhs_extra);
|
||||
}
|
||||
};
|
||||
const data = Constant.ExtractElement{ .val = val, .index = index };
|
||||
const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
|
||||
if (!gop.found_existing) {
|
||||
gop.key_ptr.* = {};
|
||||
gop.value_ptr.* = {};
|
||||
self.constant_items.appendAssumeCapacity(.{
|
||||
.tag = .extractelement,
|
||||
.data = self.addConstantExtraAssumeCapacity(data),
|
||||
});
|
||||
}
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn insertElementConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
val: Constant,
|
||||
elem: Constant,
|
||||
index: Constant,
|
||||
) Constant {
|
||||
const Adapter = struct {
|
||||
builder: *const Builder,
|
||||
pub fn hash(_: @This(), key: Constant.InsertElement) u32 {
|
||||
return @truncate(std.hash.Wyhash.hash(
|
||||
comptime std.hash.uint32(@intFromEnum(Constant.Tag.insertelement)),
|
||||
std.mem.asBytes(&key),
|
||||
));
|
||||
}
|
||||
pub fn eql(ctx: @This(), lhs_key: Constant.InsertElement, _: void, rhs_index: usize) bool {
|
||||
if (ctx.builder.constant_items.items(.tag)[rhs_index] != .insertelement) return false;
|
||||
const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
|
||||
const rhs_extra = ctx.builder.constantExtraData(Constant.InsertElement, rhs_data);
|
||||
return std.meta.eql(lhs_key, rhs_extra);
|
||||
}
|
||||
};
|
||||
const data = Constant.InsertElement{ .val = val, .elem = elem, .index = index };
|
||||
const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
|
||||
if (!gop.found_existing) {
|
||||
gop.key_ptr.* = {};
|
||||
gop.value_ptr.* = {};
|
||||
self.constant_items.appendAssumeCapacity(.{
|
||||
.tag = .insertelement,
|
||||
.data = self.addConstantExtraAssumeCapacity(data),
|
||||
});
|
||||
}
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn shuffleVectorConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
mask: Constant,
|
||||
) Constant {
|
||||
assert(lhs.typeOf(self).isVector(self.builder));
|
||||
assert(lhs.typeOf(self) == rhs.typeOf(self));
|
||||
assert(mask.typeOf(self).scalarType(self).isInteger(self));
|
||||
_ = lhs.typeOf(self).changeLengthAssumeCapacity(mask.typeOf(self).vectorLen(self), self);
|
||||
const Adapter = struct {
|
||||
builder: *const Builder,
|
||||
pub fn hash(_: @This(), key: Constant.ShuffleVector) u32 {
|
||||
return @truncate(std.hash.Wyhash.hash(
|
||||
comptime std.hash.uint32(@intFromEnum(Constant.Tag.shufflevector)),
|
||||
std.mem.asBytes(&key),
|
||||
));
|
||||
}
|
||||
pub fn eql(ctx: @This(), lhs_key: Constant.ShuffleVector, _: void, rhs_index: usize) bool {
|
||||
if (ctx.builder.constant_items.items(.tag)[rhs_index] != .shufflevector) return false;
|
||||
const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
|
||||
const rhs_extra = ctx.builder.constantExtraData(Constant.ShuffleVector, rhs_data);
|
||||
return std.meta.eql(lhs_key, rhs_extra);
|
||||
}
|
||||
};
|
||||
const data = Constant.ShuffleVector{ .lhs = lhs, .rhs = rhs, .mask = mask };
|
||||
const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
|
||||
if (!gop.found_existing) {
|
||||
gop.key_ptr.* = {};
|
||||
gop.value_ptr.* = {};
|
||||
self.constant_items.appendAssumeCapacity(.{
|
||||
.tag = .shufflevector,
|
||||
.data = self.addConstantExtraAssumeCapacity(data),
|
||||
});
|
||||
}
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn binConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
tag: Constant.Tag,
|
||||
|
|
@ -11756,14 +11372,7 @@ fn binConstAssumeCapacity(
|
|||
.sub,
|
||||
.@"sub nsw",
|
||||
.@"sub nuw",
|
||||
.mul,
|
||||
.@"mul nsw",
|
||||
.@"mul nuw",
|
||||
.shl,
|
||||
.lshr,
|
||||
.ashr,
|
||||
.@"and",
|
||||
.@"or",
|
||||
.xor,
|
||||
=> {},
|
||||
else => unreachable,
|
||||
|
|
@ -13938,16 +13547,8 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
|
|||
.bitcast,
|
||||
.inttoptr,
|
||||
.ptrtoint,
|
||||
.fptosi,
|
||||
.fptoui,
|
||||
.sitofp,
|
||||
.uitofp,
|
||||
.addrspacecast,
|
||||
.fptrunc,
|
||||
.trunc,
|
||||
.fpext,
|
||||
.sext,
|
||||
.zext,
|
||||
=> |tag| {
|
||||
const extra = self.constantExtraData(Constant.Cast, data);
|
||||
try constants_block.writeAbbrevAdapted(Constants.Cast{
|
||||
|
|
@ -13962,14 +13563,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
|
|||
.sub,
|
||||
.@"sub nsw",
|
||||
.@"sub nuw",
|
||||
.mul,
|
||||
.@"mul nsw",
|
||||
.@"mul nuw",
|
||||
.shl,
|
||||
.lshr,
|
||||
.ashr,
|
||||
.@"and",
|
||||
.@"or",
|
||||
.xor,
|
||||
=> |tag| {
|
||||
const extra = self.constantExtraData(Constant.Binary, data);
|
||||
|
|
@ -13979,55 +13573,6 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
|
|||
.rhs = extra.rhs,
|
||||
}, constant_adapter);
|
||||
},
|
||||
.icmp,
|
||||
.fcmp,
|
||||
=> {
|
||||
const extra = self.constantExtraData(Constant.Compare, data);
|
||||
try constants_block.writeAbbrevAdapted(Constants.Cmp{
|
||||
.ty = extra.lhs.typeOf(self),
|
||||
.lhs = extra.lhs,
|
||||
.rhs = extra.rhs,
|
||||
.pred = extra.cond,
|
||||
}, constant_adapter);
|
||||
},
|
||||
.extractelement => {
|
||||
const extra = self.constantExtraData(Constant.ExtractElement, data);
|
||||
try constants_block.writeAbbrevAdapted(Constants.ExtractElement{
|
||||
.val_type = extra.val.typeOf(self),
|
||||
.val = extra.val,
|
||||
.index_type = extra.index.typeOf(self),
|
||||
.index = extra.index,
|
||||
}, constant_adapter);
|
||||
},
|
||||
.insertelement => {
|
||||
const extra = self.constantExtraData(Constant.InsertElement, data);
|
||||
try constants_block.writeAbbrevAdapted(Constants.InsertElement{
|
||||
.val = extra.val,
|
||||
.elem = extra.elem,
|
||||
.index_type = extra.index.typeOf(self),
|
||||
.index = extra.index,
|
||||
}, constant_adapter);
|
||||
},
|
||||
.shufflevector => {
|
||||
const extra = self.constantExtraData(Constant.ShuffleVector, data);
|
||||
const ty = constant.typeOf(self);
|
||||
const lhs_type = extra.lhs.typeOf(self);
|
||||
// Check if instruction is widening, truncating or not
|
||||
if (ty == lhs_type) {
|
||||
try constants_block.writeAbbrevAdapted(Constants.ShuffleVector{
|
||||
.lhs = extra.lhs,
|
||||
.rhs = extra.rhs,
|
||||
.mask = extra.mask,
|
||||
}, constant_adapter);
|
||||
} else {
|
||||
try constants_block.writeAbbrevAdapted(Constants.ShuffleVectorEx{
|
||||
.ty = ty,
|
||||
.lhs = extra.lhs,
|
||||
.rhs = extra.rhs,
|
||||
.mask = extra.mask,
|
||||
}, constant_adapter);
|
||||
}
|
||||
},
|
||||
.getelementptr,
|
||||
.@"getelementptr inbounds",
|
||||
=> |tag| {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue