llvm: cleanup management and implement more const functions
This commit is contained in:
@@ -533,15 +533,6 @@ const DataLayoutBuilder = struct {
|
||||
}
|
||||
};
|
||||
|
||||
/// TODO can this be done with simpler logic / different API binding?
|
||||
fn deleteLlvmGlobal(llvm_global: *llvm.Value) void {
|
||||
if (llvm_global.globalGetValueType().getTypeKind() == .Function) {
|
||||
llvm_global.deleteFunction();
|
||||
return;
|
||||
}
|
||||
return llvm_global.deleteGlobal();
|
||||
}
|
||||
|
||||
pub const Object = struct {
|
||||
gpa: Allocator,
|
||||
builder: Builder,
|
||||
@@ -818,7 +809,7 @@ pub const Object = struct {
|
||||
.init = str_init,
|
||||
};
|
||||
try o.builder.llvm.globals.append(o.gpa, str_global);
|
||||
const str_global_index = try o.builder.addGlobal(.none, global);
|
||||
const str_global_index = try o.builder.addGlobal(.empty, global);
|
||||
try o.builder.variables.append(o.gpa, variable);
|
||||
|
||||
llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
|
||||
@@ -848,7 +839,7 @@ pub const Object = struct {
|
||||
.init = error_name_table_init,
|
||||
};
|
||||
try o.builder.llvm.globals.append(o.gpa, error_name_table_global);
|
||||
_ = try o.builder.addGlobal(.none, global);
|
||||
_ = try o.builder.addGlobal(.empty, global);
|
||||
try o.builder.variables.append(o.gpa, variable);
|
||||
|
||||
const error_name_table_ptr = error_name_table_global;
|
||||
@@ -904,35 +895,27 @@ pub const Object = struct {
|
||||
// This map has externs with incorrect symbol names.
|
||||
for (object.extern_collisions.keys()) |decl_index| {
|
||||
const global = object.decl_map.get(decl_index) orelse continue;
|
||||
const llvm_global = global.toLlvm(&object.builder);
|
||||
// Same logic as below but for externs instead of exports.
|
||||
const decl_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue;
|
||||
const other_global = object.builder.getGlobal(decl_name) orelse continue;
|
||||
const other_llvm_global = other_global.toLlvm(&object.builder);
|
||||
if (other_llvm_global == llvm_global) continue;
|
||||
if (other_global.eql(global, &object.builder)) continue;
|
||||
|
||||
llvm_global.replaceAllUsesWith(other_llvm_global);
|
||||
deleteLlvmGlobal(llvm_global);
|
||||
object.builder.llvm.globals.items[@intFromEnum(global)] = other_llvm_global;
|
||||
try global.replace(other_global, &object.builder);
|
||||
}
|
||||
object.extern_collisions.clearRetainingCapacity();
|
||||
|
||||
for (mod.decl_exports.keys(), mod.decl_exports.values()) |decl_index, export_list| {
|
||||
const global = object.decl_map.get(decl_index) orelse continue;
|
||||
const llvm_global = global.toLlvm(&object.builder);
|
||||
for (export_list.items) |exp| {
|
||||
// Detect if the LLVM global has already been created as an extern. In such
|
||||
// case, we need to replace all uses of it with this exported global.
|
||||
const exp_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue;
|
||||
|
||||
const other_global = object.builder.getGlobal(exp_name) orelse continue;
|
||||
const other_llvm_global = other_global.toLlvm(&object.builder);
|
||||
if (other_llvm_global == llvm_global) continue;
|
||||
if (other_global.eql(global, &object.builder)) continue;
|
||||
|
||||
other_llvm_global.replaceAllUsesWith(llvm_global);
|
||||
try global.takeName(&object.builder, other_global);
|
||||
deleteLlvmGlobal(other_llvm_global);
|
||||
object.builder.llvm.globals.items[@intFromEnum(other_global)] = llvm_global;
|
||||
try global.takeName(other_global, &object.builder);
|
||||
try other_global.replace(global, &object.builder);
|
||||
// Problem: now we need to replace in the decl_map that
|
||||
// the extern decl index points to this new global. However we don't
|
||||
// know the decl index.
|
||||
@@ -1519,7 +1502,7 @@ pub const Object = struct {
|
||||
}
|
||||
}
|
||||
|
||||
try global.rename(&self.builder, decl_name);
|
||||
try global.rename(decl_name, &self.builder);
|
||||
global.ptr(&self.builder).unnamed_addr = .default;
|
||||
llvm_global.setUnnamedAddr(.False);
|
||||
global.ptr(&self.builder).linkage = .external;
|
||||
@@ -1558,7 +1541,7 @@ pub const Object = struct {
|
||||
global.ptr(&self.builder).updateAttributes();
|
||||
} else if (exports.len != 0) {
|
||||
const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exports[0].opts.name));
|
||||
try global.rename(&self.builder, exp_name);
|
||||
try global.rename(exp_name, &self.builder);
|
||||
global.ptr(&self.builder).unnamed_addr = .default;
|
||||
llvm_global.setUnnamedAddr(.False);
|
||||
if (mod.wantDllExports()) {
|
||||
@@ -1641,7 +1624,7 @@ pub const Object = struct {
|
||||
}
|
||||
} else {
|
||||
const fqn = try self.builder.string(mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)));
|
||||
try global.rename(&self.builder, fqn);
|
||||
try global.rename(fqn, &self.builder);
|
||||
global.ptr(&self.builder).linkage = .internal;
|
||||
llvm_global.setLinkage(.Internal);
|
||||
if (mod.wantDllExports()) {
|
||||
@@ -2738,7 +2721,7 @@ pub const Object = struct {
|
||||
.init = llvm_init,
|
||||
};
|
||||
try o.builder.llvm.globals.append(o.gpa, llvm_global);
|
||||
_ = try o.builder.addGlobal(.none, global);
|
||||
_ = try o.builder.addGlobal(.empty, global);
|
||||
try o.builder.variables.append(o.gpa, variable);
|
||||
|
||||
const addrspace_casted_global = if (llvm_wanted_addrspace != llvm_actual_addrspace)
|
||||
@@ -4473,8 +4456,8 @@ pub const DeclGen = struct {
|
||||
_ = try o.resolveLlvmFunction(extern_func.decl);
|
||||
} else {
|
||||
const target = mod.getTarget();
|
||||
const object = try o.resolveGlobalDecl(decl_index);
|
||||
const global = object.ptrConst(&o.builder).global;
|
||||
const variable = try o.resolveGlobalDecl(decl_index);
|
||||
const global = variable.ptrConst(&o.builder).global;
|
||||
var llvm_global = global.toLlvm(&o.builder);
|
||||
global.ptr(&o.builder).alignment = Builder.Alignment.fromByteUnits(decl.getAlignment(mod));
|
||||
llvm_global.setAlignment(decl.getAlignment(mod));
|
||||
@@ -4483,18 +4466,18 @@ pub const DeclGen = struct {
|
||||
llvm_global.setSection(section);
|
||||
}
|
||||
assert(decl.has_tv);
|
||||
const init_val = if (decl.val.getVariable(mod)) |decl_var| init_val: {
|
||||
object.ptr(&o.builder).mutability = .global;
|
||||
break :init_val decl_var.init;
|
||||
} else init_val: {
|
||||
object.ptr(&o.builder).mutability = .constant;
|
||||
const init_val = if (decl.val.getVariable(mod)) |decl_var| decl_var.init else init_val: {
|
||||
variable.ptr(&o.builder).mutability = .constant;
|
||||
llvm_global.setGlobalConstant(.True);
|
||||
break :init_val decl.val.toIntern();
|
||||
};
|
||||
if (init_val != .none) {
|
||||
const llvm_init = try o.lowerValue(init_val);
|
||||
const llvm_init_ty = llvm_init.typeOf(&o.builder);
|
||||
global.ptr(&o.builder).type = llvm_init_ty;
|
||||
variable.ptr(&o.builder).mutability = .global;
|
||||
variable.ptr(&o.builder).init = llvm_init;
|
||||
if (llvm_global.globalGetValueType() == llvm_init.typeOf(&o.builder).toLlvm(&o.builder)) {
|
||||
object.ptr(&o.builder).init = llvm_init;
|
||||
llvm_global.setInitializer(llvm_init.toLlvm(&o.builder));
|
||||
} else {
|
||||
// LLVM does not allow us to change the type of globals. So we must
|
||||
@@ -4512,7 +4495,7 @@ pub const DeclGen = struct {
|
||||
// Related: https://github.com/ziglang/zig/issues/13265
|
||||
const llvm_global_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
|
||||
const new_global = o.llvm_module.addGlobalInAddressSpace(
|
||||
llvm_init.typeOf(&o.builder).toLlvm(&o.builder),
|
||||
llvm_init_ty.toLlvm(&o.builder),
|
||||
"",
|
||||
@intFromEnum(llvm_global_addrspace),
|
||||
);
|
||||
@@ -4525,7 +4508,7 @@ pub const DeclGen = struct {
|
||||
// TODO: How should this work then the address space of a global changed?
|
||||
llvm_global.replaceAllUsesWith(new_global);
|
||||
new_global.takeName(llvm_global);
|
||||
o.builder.llvm.globals.items[@intFromEnum(object.ptrConst(&o.builder).global)] =
|
||||
o.builder.llvm.globals.items[@intFromEnum(variable.ptrConst(&o.builder).global)] =
|
||||
new_global;
|
||||
llvm_global.deleteGlobal();
|
||||
llvm_global = new_global;
|
||||
@@ -4672,7 +4655,7 @@ pub const FuncGen = struct {
|
||||
.init = llvm_val,
|
||||
};
|
||||
try o.builder.llvm.globals.append(o.gpa, llvm_global);
|
||||
_ = try o.builder.addGlobal(.none, global);
|
||||
_ = try o.builder.addGlobal(.empty, global);
|
||||
try o.builder.variables.append(o.gpa, variable);
|
||||
|
||||
const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)
|
||||
@@ -9312,6 +9295,7 @@ pub const FuncGen = struct {
|
||||
};
|
||||
var function = Builder.Function{
|
||||
.global = @enumFromInt(o.builder.globals.count()),
|
||||
.body = {},
|
||||
};
|
||||
|
||||
const prev_block = self.builder.getInsertBlock();
|
||||
@@ -9395,6 +9379,7 @@ pub const FuncGen = struct {
|
||||
};
|
||||
var function = Builder.Function{
|
||||
.global = @enumFromInt(o.builder.globals.count()),
|
||||
.body = {},
|
||||
};
|
||||
|
||||
const prev_block = self.builder.getInsertBlock();
|
||||
@@ -9485,6 +9470,7 @@ pub const FuncGen = struct {
|
||||
};
|
||||
var function = Builder.Function{
|
||||
.global = @enumFromInt(o.builder.globals.count()),
|
||||
.body = {},
|
||||
};
|
||||
|
||||
try o.builder.llvm.globals.append(self.gpa, llvm_fn);
|
||||
|
||||
@@ -29,6 +29,7 @@ type_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
|
||||
globals: std.AutoArrayHashMapUnmanaged(String, Global) = .{},
|
||||
next_unnamed_global: String = @enumFromInt(0),
|
||||
next_replaced_global: String = .none,
|
||||
next_unique_global_id: std.AutoHashMapUnmanaged(String, u32) = .{},
|
||||
aliases: std.ArrayListUnmanaged(Alias) = .{},
|
||||
variables: std.ArrayListUnmanaged(Variable) = .{},
|
||||
@@ -55,6 +56,11 @@ pub const String = enum(u32) {
|
||||
empty,
|
||||
_,
|
||||
|
||||
pub fn isAnon(self: String) bool {
|
||||
assert(self != .none);
|
||||
return self.toIndex() == null;
|
||||
}
|
||||
|
||||
pub fn toSlice(self: String, b: *const Builder) ?[:0]const u8 {
|
||||
const index = self.toIndex() orelse return null;
|
||||
const start = b.string_indices.items[index];
|
||||
@@ -743,18 +749,36 @@ pub const Global = struct {
|
||||
alias: Alias.Index,
|
||||
variable: Variable.Index,
|
||||
function: Function.Index,
|
||||
replaced: Global.Index,
|
||||
},
|
||||
|
||||
pub const Index = enum(u32) {
|
||||
none = std.math.maxInt(u32),
|
||||
_,
|
||||
|
||||
pub fn unwrap(self: Index, builder: *const Builder) Index {
|
||||
var cur = self;
|
||||
while (true) {
|
||||
const replacement = cur.getReplacement(builder);
|
||||
if (replacement == .none) return cur;
|
||||
cur = replacement;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eql(self: Index, other: Index, builder: *const Builder) bool {
|
||||
return self.unwrap(builder) == other.unwrap(builder);
|
||||
}
|
||||
|
||||
pub fn name(self: Index, builder: *const Builder) String {
|
||||
return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
|
||||
}
|
||||
|
||||
pub fn ptr(self: Index, builder: *Builder) *Global {
|
||||
return &builder.globals.values()[@intFromEnum(self)];
|
||||
return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
|
||||
}
|
||||
|
||||
pub fn ptrConst(self: Index, builder: *const Builder) *const Global {
|
||||
return &builder.globals.values()[@intFromEnum(self)];
|
||||
return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
|
||||
}
|
||||
|
||||
pub fn toConst(self: Index) Constant {
|
||||
@@ -763,7 +787,7 @@ pub const Global = struct {
|
||||
|
||||
pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
|
||||
assert(builder.useLibLlvm());
|
||||
return builder.llvm.globals.items[@intFromEnum(self)];
|
||||
return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))];
|
||||
}
|
||||
|
||||
const FormatData = struct {
|
||||
@@ -777,44 +801,80 @@ pub const Global = struct {
|
||||
writer: anytype,
|
||||
) @TypeOf(writer).Error!void {
|
||||
try writer.print("@{}", .{
|
||||
data.builder.globals.keys()[@intFromEnum(data.global)].fmt(data.builder),
|
||||
data.global.unwrap(data.builder).name(data.builder).fmt(data.builder),
|
||||
});
|
||||
}
|
||||
pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(format) {
|
||||
return .{ .data = .{ .global = self, .builder = builder } };
|
||||
}
|
||||
|
||||
pub fn rename(self: Index, builder: *Builder, name: String) Allocator.Error!void {
|
||||
try builder.ensureUnusedCapacityGlobal(name);
|
||||
self.renameAssumeCapacity(builder, name);
|
||||
pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
|
||||
try builder.ensureUnusedCapacityGlobal(new_name);
|
||||
self.renameAssumeCapacity(new_name, builder);
|
||||
}
|
||||
|
||||
pub fn renameAssumeCapacity(self: Index, builder: *Builder, name: String) void {
|
||||
const index = @intFromEnum(self);
|
||||
if (builder.globals.keys()[index] == name) return;
|
||||
if (builder.useLibLlvm()) builder.llvm.globals.appendAssumeCapacity(builder.llvm.globals.items[index]);
|
||||
_ = builder.addGlobalAssumeCapacity(name, builder.globals.values()[index]);
|
||||
pub fn takeName(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
|
||||
try builder.ensureUnusedCapacityGlobal(.empty);
|
||||
self.takeNameAssumeCapacity(other, builder);
|
||||
}
|
||||
|
||||
pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
|
||||
try builder.ensureUnusedCapacityGlobal(.empty);
|
||||
self.replaceAssumeCapacity(other, builder);
|
||||
}
|
||||
|
||||
fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void {
|
||||
const old_name = self.name(builder);
|
||||
if (new_name == old_name) return;
|
||||
const index = @intFromEnum(self.unwrap(builder));
|
||||
if (builder.useLibLlvm())
|
||||
builder.llvm.globals.appendAssumeCapacity(builder.llvm.globals.items[index]);
|
||||
_ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]);
|
||||
if (builder.useLibLlvm()) _ = builder.llvm.globals.pop();
|
||||
builder.globals.swapRemoveAt(index);
|
||||
self.updateName(builder);
|
||||
if (!old_name.isAnon()) return;
|
||||
builder.next_unnamed_global = @enumFromInt(@intFromEnum(builder.next_unnamed_global) - 1);
|
||||
if (builder.next_unnamed_global == old_name) return;
|
||||
builder.getGlobal(builder.next_unnamed_global).?.renameAssumeCapacity(old_name, builder);
|
||||
}
|
||||
|
||||
pub fn takeName(self: Index, builder: *Builder, other: Index) Allocator.Error!void {
|
||||
try builder.ensureUnusedCapacityGlobal(.empty);
|
||||
self.takeNameAssumeCapacity(builder, other);
|
||||
}
|
||||
|
||||
pub fn takeNameAssumeCapacity(self: Index, builder: *Builder, other: Index) void {
|
||||
const other_name = builder.globals.keys()[@intFromEnum(other)];
|
||||
other.renameAssumeCapacity(builder, .none);
|
||||
self.renameAssumeCapacity(builder, other_name);
|
||||
fn takeNameAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
|
||||
const other_name = other.name(builder);
|
||||
other.renameAssumeCapacity(.empty, builder);
|
||||
self.renameAssumeCapacity(other_name, builder);
|
||||
}
|
||||
|
||||
fn updateName(self: Index, builder: *const Builder) void {
|
||||
if (!builder.useLibLlvm()) return;
|
||||
const index = @intFromEnum(self);
|
||||
const slice = builder.globals.keys()[index].toSlice(builder) orelse "";
|
||||
builder.llvm.globals.items[index].setValueName2(slice.ptr, slice.len);
|
||||
const index = @intFromEnum(self.unwrap(builder));
|
||||
const name_slice = self.name(builder).toSlice(builder) orelse "";
|
||||
builder.llvm.globals.items[index].setValueName2(name_slice.ptr, name_slice.len);
|
||||
}
|
||||
|
||||
fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
|
||||
if (self.eql(other, builder)) return;
|
||||
builder.next_replaced_global = @enumFromInt(@intFromEnum(builder.next_replaced_global) - 1);
|
||||
self.renameAssumeCapacity(builder.next_replaced_global, builder);
|
||||
if (builder.useLibLlvm()) {
|
||||
const self_llvm = self.toLlvm(builder);
|
||||
self_llvm.replaceAllUsesWith(other.toLlvm(builder));
|
||||
switch (self.ptr(builder).kind) {
|
||||
.alias,
|
||||
.variable,
|
||||
=> self_llvm.deleteGlobal(),
|
||||
.function => self_llvm.deleteFunction(),
|
||||
.replaced => unreachable,
|
||||
}
|
||||
}
|
||||
self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
|
||||
}
|
||||
|
||||
fn getReplacement(self: Index, builder: *const Builder) Index {
|
||||
return switch (builder.globals.values()[@intFromEnum(self)].kind) {
|
||||
.replaced => |replacement| replacement,
|
||||
else => .none,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1014,8 +1074,14 @@ pub const Constant = enum(u32) {
|
||||
insertelement,
|
||||
shufflevector,
|
||||
add,
|
||||
@"add nsw",
|
||||
@"add nuw",
|
||||
sub,
|
||||
@"sub nsw",
|
||||
@"sub nuw",
|
||||
mul,
|
||||
@"mul nsw",
|
||||
@"mul nuw",
|
||||
shl,
|
||||
lshr,
|
||||
ashr,
|
||||
@@ -1084,24 +1150,24 @@ pub const Constant = enum(u32) {
|
||||
pub const Kind = enum { normal, inbounds };
|
||||
};
|
||||
|
||||
pub const Compare = struct {
|
||||
pub const Compare = extern struct {
|
||||
cond: u32,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
};
|
||||
|
||||
pub const ExtractElement = struct {
|
||||
pub const ExtractElement = extern struct {
|
||||
arg: Constant,
|
||||
index: Constant,
|
||||
};
|
||||
|
||||
pub const InsertElement = struct {
|
||||
pub const InsertElement = extern struct {
|
||||
arg: Constant,
|
||||
elem: Constant,
|
||||
index: Constant,
|
||||
};
|
||||
|
||||
pub const ShuffleVector = struct {
|
||||
pub const ShuffleVector = extern struct {
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
mask: Constant,
|
||||
@@ -1243,8 +1309,14 @@ pub const Constant = enum(u32) {
|
||||
};
|
||||
},
|
||||
.add,
|
||||
.@"add nsw",
|
||||
.@"add nuw",
|
||||
.sub,
|
||||
.@"sub nsw",
|
||||
.@"sub nuw",
|
||||
.mul,
|
||||
.@"mul nsw",
|
||||
.@"mul nuw",
|
||||
.shl,
|
||||
.lshr,
|
||||
.ashr,
|
||||
@@ -1326,14 +1398,14 @@ pub const Constant = enum(u32) {
|
||||
switch (item.tag) {
|
||||
.positive_integer,
|
||||
.negative_integer,
|
||||
=> {
|
||||
=> |tag| {
|
||||
const extra: *align(@alignOf(std.math.big.Limb)) Integer =
|
||||
@ptrCast(data.builder.constant_limbs.items[item.data..][0..Integer.limbs]);
|
||||
const limbs = data.builder.constant_limbs
|
||||
.items[item.data + Integer.limbs ..][0..extra.limbs_len];
|
||||
const bigint = std.math.big.int.Const{
|
||||
.limbs = limbs,
|
||||
.positive = item.tag == .positive_integer,
|
||||
.positive = tag == .positive_integer,
|
||||
};
|
||||
const ExpectedContents = extern struct {
|
||||
string: [(64 * 8 / std.math.log2(10)) + 2]u8,
|
||||
@@ -1352,23 +1424,63 @@ pub const Constant = enum(u32) {
|
||||
defer allocator.free(str);
|
||||
try writer.writeAll(str);
|
||||
},
|
||||
.half,
|
||||
.bfloat,
|
||||
=> |tag| try writer.print("0x{c}{X:0>4}", .{ @as(u8, switch (tag) {
|
||||
.half => 'H',
|
||||
.bfloat => 'R',
|
||||
else => unreachable,
|
||||
}), item.data >> switch (tag) {
|
||||
.half => 0,
|
||||
.bfloat => 16,
|
||||
else => unreachable,
|
||||
} }),
|
||||
.float => try writer.print("0x{X:0>16}", .{
|
||||
@as(u64, @bitCast(@as(f64, @as(f32, @bitCast(item.data))))),
|
||||
}),
|
||||
.double => {
|
||||
const extra = data.builder.constantExtraData(Double, item.data);
|
||||
try writer.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });
|
||||
},
|
||||
.fp128,
|
||||
.ppc_fp128,
|
||||
=> |tag| {
|
||||
const extra = data.builder.constantExtraData(Fp128, item.data);
|
||||
try writer.print("0x{c}{X:0>8}{X:0>8}{X:0>8}{X:0>8}", .{
|
||||
@as(u8, switch (tag) {
|
||||
.fp128 => 'L',
|
||||
.ppc_fp128 => 'M',
|
||||
else => unreachable,
|
||||
}),
|
||||
extra.lo_hi,
|
||||
extra.lo_lo,
|
||||
extra.hi_hi,
|
||||
extra.hi_lo,
|
||||
});
|
||||
},
|
||||
.x86_fp80 => {
|
||||
const extra = data.builder.constantExtraData(Fp80, item.data);
|
||||
try writer.print("0xK{X:0>4}{X:0>8}{X:0>8}", .{
|
||||
extra.hi, extra.lo_hi, extra.lo_lo,
|
||||
});
|
||||
},
|
||||
.null,
|
||||
.none,
|
||||
.zeroinitializer,
|
||||
.undef,
|
||||
.poison,
|
||||
=> try writer.writeAll(@tagName(item.tag)),
|
||||
=> |tag| try writer.writeAll(@tagName(tag)),
|
||||
.structure,
|
||||
.packed_structure,
|
||||
.array,
|
||||
.vector,
|
||||
=> {
|
||||
=> |tag| {
|
||||
const extra = data.builder.constantExtraDataTrail(Aggregate, item.data);
|
||||
const len = extra.data.type.aggregateLen(data.builder);
|
||||
const vals: []const Constant =
|
||||
@ptrCast(data.builder.constant_extra.items[extra.end..][0..len]);
|
||||
|
||||
try writer.writeAll(switch (item.tag) {
|
||||
try writer.writeAll(switch (tag) {
|
||||
.structure => "{ ",
|
||||
.packed_structure => "<{ ",
|
||||
.array => "[",
|
||||
@@ -1379,7 +1491,7 @@ pub const Constant = enum(u32) {
|
||||
if (index > 0) try writer.writeAll(", ");
|
||||
try writer.print("{%}", .{val.fmt(data.builder)});
|
||||
}
|
||||
try writer.writeAll(switch (item.tag) {
|
||||
try writer.writeAll(switch (tag) {
|
||||
.structure => " }",
|
||||
.packed_structure => " }>",
|
||||
.array => "]",
|
||||
@@ -1387,33 +1499,130 @@ pub const Constant = enum(u32) {
|
||||
else => unreachable,
|
||||
});
|
||||
},
|
||||
.string => try writer.print(
|
||||
\\c{"}
|
||||
, .{@as(String, @enumFromInt(item.data)).fmt(data.builder)}),
|
||||
.string_null => try writer.print(
|
||||
\\c{"@}
|
||||
, .{@as(String, @enumFromInt(item.data)).fmt(data.builder)}),
|
||||
.blockaddress => {
|
||||
inline .string,
|
||||
.string_null,
|
||||
=> |tag| try writer.print("c{\"" ++ switch (tag) {
|
||||
.string => "",
|
||||
.string_null => "@",
|
||||
else => unreachable,
|
||||
} ++ "}", .{@as(String, @enumFromInt(item.data)).fmt(data.builder)}),
|
||||
.blockaddress => |tag| {
|
||||
const extra = data.builder.constantExtraData(BlockAddress, item.data);
|
||||
const function = extra.function.ptrConst(data.builder);
|
||||
try writer.print("{s}({}, %{d})", .{
|
||||
@tagName(item.tag),
|
||||
@tagName(tag),
|
||||
function.global.fmt(data.builder),
|
||||
@intFromEnum(extra.block), // TODO
|
||||
});
|
||||
},
|
||||
.dso_local_equivalent,
|
||||
.no_cfi,
|
||||
=> {
|
||||
=> |tag| {
|
||||
const extra = data.builder.constantExtraData(FunctionReference, item.data);
|
||||
try writer.print("{s} {}", .{
|
||||
@tagName(item.tag),
|
||||
@tagName(tag),
|
||||
extra.function.ptrConst(data.builder).global.fmt(data.builder),
|
||||
});
|
||||
},
|
||||
else => try writer.print("<{s}:0x{X}>", .{
|
||||
@tagName(item.tag), @intFromEnum(data.constant),
|
||||
}),
|
||||
.trunc,
|
||||
.zext,
|
||||
.sext,
|
||||
.fptrunc,
|
||||
.fpext,
|
||||
.fptoui,
|
||||
.fptosi,
|
||||
.uitofp,
|
||||
.sitofp,
|
||||
.ptrtoint,
|
||||
.inttoptr,
|
||||
.bitcast,
|
||||
.addrspacecast,
|
||||
=> |tag| {
|
||||
const extra = data.builder.constantExtraData(Cast, item.data);
|
||||
try writer.print("{s} ({%} to {%})", .{
|
||||
@tagName(tag),
|
||||
extra.arg.fmt(data.builder),
|
||||
extra.type.fmt(data.builder),
|
||||
});
|
||||
},
|
||||
.getelementptr,
|
||||
.@"getelementptr inbounds",
|
||||
=> |tag| {
|
||||
const extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data);
|
||||
const indices: []const Constant = @ptrCast(data.builder.constant_extra
|
||||
.items[extra.end..][0..extra.data.indices_len]);
|
||||
try writer.print("{s} ({%}, {%}", .{
|
||||
@tagName(tag),
|
||||
extra.data.type.fmt(data.builder),
|
||||
extra.data.base.fmt(data.builder),
|
||||
});
|
||||
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.arg.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.arg.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);
|
||||
try writer.print("{s} ({%}, {%})", .{
|
||||
@tagName(tag),
|
||||
extra.lhs.fmt(data.builder),
|
||||
extra.rhs.fmt(data.builder),
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
.global => |global| try writer.print("{}", .{global.fmt(data.builder)}),
|
||||
@@ -1882,6 +2091,7 @@ pub fn namedTypeSetBody(
|
||||
}
|
||||
|
||||
pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!Global.Index {
|
||||
assert(!name.isAnon());
|
||||
try self.ensureUnusedTypeCapacity(1, null, 0);
|
||||
try self.ensureUnusedCapacityGlobal(name);
|
||||
return self.addGlobalAssumeCapacity(name, global);
|
||||
@@ -1890,9 +2100,10 @@ pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!G
|
||||
pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Global.Index {
|
||||
_ = self.ptrTypeAssumeCapacity(global.addr_space);
|
||||
var id = name;
|
||||
if (id == .none) {
|
||||
if (name == .empty) {
|
||||
id = self.next_unnamed_global;
|
||||
self.next_unnamed_global = @enumFromInt(@intFromEnum(self.next_unnamed_global) + 1);
|
||||
assert(id != self.next_replaced_global);
|
||||
self.next_unnamed_global = @enumFromInt(@intFromEnum(id) + 1);
|
||||
}
|
||||
while (true) {
|
||||
const global_gop = self.globals.getOrPutAssumeCapacity(id);
|
||||
@@ -2136,7 +2347,7 @@ pub fn binConst(
|
||||
return self.binConstAssumeCapacity(tag, lhs, rhs);
|
||||
}
|
||||
|
||||
pub fn dump(self: *Builder, writer: anytype) @TypeOf(writer).Error!void {
|
||||
pub fn dump(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator.Error)!void {
|
||||
if (self.source_filename != .none) try writer.print(
|
||||
\\; ModuleID = '{s}'
|
||||
\\source_filename = {"}
|
||||
@@ -2157,7 +2368,8 @@ pub fn dump(self: *Builder, writer: anytype) @TypeOf(writer).Error!void {
|
||||
, .{ id.fmt(self), ty.fmt(self) });
|
||||
try writer.writeByte('\n');
|
||||
for (self.variables.items) |variable| {
|
||||
const global = self.globals.values()[@intFromEnum(variable.global)];
|
||||
if (variable.global.getReplacement(self) != .none) continue;
|
||||
const global = variable.global.ptrConst(self);
|
||||
try writer.print(
|
||||
\\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{,}
|
||||
\\
|
||||
@@ -2179,7 +2391,8 @@ pub fn dump(self: *Builder, writer: anytype) @TypeOf(writer).Error!void {
|
||||
}
|
||||
try writer.writeByte('\n');
|
||||
for (self.functions.items) |function| {
|
||||
const global = self.globals.values()[@intFromEnum(function.global)];
|
||||
if (function.global.getReplacement(self) != .none) continue;
|
||||
const global = function.global.ptrConst(self);
|
||||
const item = self.type_items.items[@intFromEnum(global.type)];
|
||||
const extra = self.typeExtraDataTrail(Type.Function, item.data);
|
||||
const params: []const Type =
|
||||
@@ -2207,14 +2420,51 @@ pub fn dump(self: *Builder, writer: anytype) @TypeOf(writer).Error!void {
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
try writer.print(") {}{}", .{ global.unnamed_addr, global.alignment });
|
||||
if (function.body) |_| try writer.print(
|
||||
\\{{
|
||||
\\ ret {%}
|
||||
\\}}
|
||||
\\
|
||||
, .{extra.data.ret.fmt(self)});
|
||||
try writer.writeByte('\n');
|
||||
try writer.print("){}{}", .{ global.unnamed_addr, global.alignment });
|
||||
if (function.body) |_| {
|
||||
try writer.writeAll(" {\n ret ");
|
||||
void: {
|
||||
try writer.print("{%}", .{switch (extra.data.ret) {
|
||||
.void => |tag| {
|
||||
try writer.writeAll(@tagName(tag));
|
||||
break :void;
|
||||
},
|
||||
inline .half,
|
||||
.bfloat,
|
||||
.float,
|
||||
.double,
|
||||
.fp128,
|
||||
.x86_fp80,
|
||||
=> |tag| try @field(Builder, @tagName(tag) ++ "Const")(self, 0.0),
|
||||
.ppc_fp128 => try self.ppc_fp128Const(.{ 0.0, 0.0 }),
|
||||
.x86_amx,
|
||||
.x86_mmx,
|
||||
.label,
|
||||
.metadata,
|
||||
=> unreachable,
|
||||
.token => Constant.none,
|
||||
else => switch (extra.data.ret.tag(self)) {
|
||||
.simple,
|
||||
.function,
|
||||
.vararg_function,
|
||||
=> unreachable,
|
||||
.integer => try self.intConst(extra.data.ret, 0),
|
||||
.pointer => try self.nullConst(extra.data.ret),
|
||||
.target,
|
||||
.vector,
|
||||
.scalable_vector,
|
||||
.small_array,
|
||||
.array,
|
||||
.structure,
|
||||
.packed_structure,
|
||||
.named_structure,
|
||||
=> try self.zeroInitConst(extra.data.ret),
|
||||
},
|
||||
}.fmt(self)});
|
||||
}
|
||||
try writer.writeAll("\n}");
|
||||
}
|
||||
try writer.writeAll("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2497,11 +2747,11 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type {
|
||||
}
|
||||
};
|
||||
var id = name;
|
||||
if (name == .none) {
|
||||
if (name == .empty) {
|
||||
id = self.next_unnamed_type;
|
||||
assert(id != .none);
|
||||
self.next_unnamed_type = @enumFromInt(@intFromEnum(id) + 1);
|
||||
} else assert(name.toIndex() != null);
|
||||
} else assert(!name.isAnon());
|
||||
while (true) {
|
||||
const type_gop = self.types.getOrPutAssumeCapacity(id);
|
||||
if (!type_gop.found_existing) {
|
||||
@@ -2783,8 +3033,8 @@ fn doubleConstAssumeCapacity(self: *Builder, val: f64) Constant {
|
||||
self.constant_items.appendAssumeCapacity(.{
|
||||
.tag = .double,
|
||||
.data = self.addConstantExtraAssumeCapacity(Constant.Double{
|
||||
.lo = @intCast(@as(u64, @bitCast(val)) >> 32),
|
||||
.hi = @truncate(@as(u64, @bitCast(val))),
|
||||
.lo = @truncate(@as(u64, @bitCast(val))),
|
||||
.hi = @intCast(@as(u64, @bitCast(val)) >> 32),
|
||||
}),
|
||||
});
|
||||
if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
|
||||
@@ -3401,6 +3651,190 @@ 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),
|
||||
});
|
||||
if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
|
||||
llvm.constICmp(@enumFromInt(@intFromEnum(cond)), lhs.toLlvm(self), rhs.toLlvm(self)),
|
||||
);
|
||||
}
|
||||
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),
|
||||
});
|
||||
if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
|
||||
llvm.constFCmp(@enumFromInt(@intFromEnum(cond)), lhs.toLlvm(self), rhs.toLlvm(self)),
|
||||
);
|
||||
}
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn extractElementConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
arg: 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{ .arg = arg, .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),
|
||||
});
|
||||
if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
|
||||
arg.toLlvm(self).constExtractElement(index.toLlvm(self)),
|
||||
);
|
||||
}
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn insertElementConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
arg: 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{ .arg = arg, .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),
|
||||
});
|
||||
if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
|
||||
arg.toLlvm(self).constInsertElement(elem.toLlvm(self), index.toLlvm(self)),
|
||||
);
|
||||
}
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn shuffleVectorConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
lhs: Constant,
|
||||
rhs: Constant,
|
||||
mask: Constant,
|
||||
) Constant {
|
||||
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),
|
||||
});
|
||||
if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
|
||||
lhs.toLlvm(self).constShuffleVector(rhs.toLlvm(self), mask.toLlvm(self)),
|
||||
);
|
||||
}
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
fn binConstAssumeCapacity(
|
||||
self: *Builder,
|
||||
tag: Constant.Tag,
|
||||
@@ -3408,7 +3842,22 @@ fn binConstAssumeCapacity(
|
||||
rhs: Constant,
|
||||
) Constant {
|
||||
switch (tag) {
|
||||
.add, .sub, .mul, .shl, .lshr, .ashr, .@"and", .@"or", .xor => {},
|
||||
.add,
|
||||
.@"add nsw",
|
||||
.@"add nuw",
|
||||
.sub,
|
||||
.@"sub nsw",
|
||||
.@"sub nuw",
|
||||
.mul,
|
||||
.@"mul nsw",
|
||||
.@"mul nuw",
|
||||
.shl,
|
||||
.lshr,
|
||||
.ashr,
|
||||
.@"and",
|
||||
.@"or",
|
||||
.xor,
|
||||
=> {},
|
||||
else => unreachable,
|
||||
}
|
||||
const Key = struct { tag: Constant.Tag, bin: Constant.Binary };
|
||||
|
||||
@@ -168,6 +168,66 @@ pub const Value = opaque {
|
||||
pub const setAliasee = LLVMAliasSetAliasee;
|
||||
extern fn LLVMAliasSetAliasee(Alias: *Value, Aliasee: *Value) void;
|
||||
|
||||
pub const constZExtOrBitCast = LLVMConstZExtOrBitCast;
|
||||
extern fn LLVMConstZExtOrBitCast(ConstantVal: *Value, ToType: *Type) *Value;
|
||||
|
||||
pub const constNeg = LLVMConstNeg;
|
||||
extern fn LLVMConstNeg(ConstantVal: *Value) *Value;
|
||||
|
||||
pub const constNSWNeg = LLVMConstNSWNeg;
|
||||
extern fn LLVMConstNSWNeg(ConstantVal: *Value) *Value;
|
||||
|
||||
pub const constNUWNeg = LLVMConstNUWNeg;
|
||||
extern fn LLVMConstNUWNeg(ConstantVal: *Value) *Value;
|
||||
|
||||
pub const constNot = LLVMConstNot;
|
||||
extern fn LLVMConstNot(ConstantVal: *Value) *Value;
|
||||
|
||||
pub const constAdd = LLVMConstAdd;
|
||||
extern fn LLVMConstAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constNSWAdd = LLVMConstNSWAdd;
|
||||
extern fn LLVMConstNSWAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constNUWAdd = LLVMConstNUWAdd;
|
||||
extern fn LLVMConstNUWAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constSub = LLVMConstSub;
|
||||
extern fn LLVMConstSub(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constNSWSub = LLVMConstNSWSub;
|
||||
extern fn LLVMConstNSWSub(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constNUWSub = LLVMConstNUWSub;
|
||||
extern fn LLVMConstNUWSub(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constMul = LLVMConstMul;
|
||||
extern fn LLVMConstMul(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constNSWMul = LLVMConstNSWMul;
|
||||
extern fn LLVMConstNSWMul(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constNUWMul = LLVMConstNUWMul;
|
||||
extern fn LLVMConstNUWMul(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constAnd = LLVMConstAnd;
|
||||
extern fn LLVMConstAnd(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constOr = LLVMConstOr;
|
||||
extern fn LLVMConstOr(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constXor = LLVMConstXor;
|
||||
extern fn LLVMConstXor(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constShl = LLVMConstShl;
|
||||
extern fn LLVMConstShl(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constLShr = LLVMConstLShr;
|
||||
extern fn LLVMConstLShr(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constAShr = LLVMConstAShr;
|
||||
extern fn LLVMConstAShr(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constTrunc = LLVMConstTrunc;
|
||||
extern fn LLVMConstTrunc(ConstantVal: *Value, ToType: *Type) *Value;
|
||||
|
||||
@@ -204,42 +264,36 @@ pub const Value = opaque {
|
||||
pub const constBitCast = LLVMConstBitCast;
|
||||
extern fn LLVMConstBitCast(ConstantVal: *Value, ToType: *Type) *Value;
|
||||
|
||||
pub const constZExtOrBitCast = LLVMConstZExtOrBitCast;
|
||||
extern fn LLVMConstZExtOrBitCast(ConstantVal: *Value, ToType: *Type) *Value;
|
||||
|
||||
pub const constNot = LLVMConstNot;
|
||||
extern fn LLVMConstNot(ConstantVal: *Value) *Value;
|
||||
|
||||
pub const constAdd = LLVMConstAdd;
|
||||
extern fn LLVMConstAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constSub = LLVMConstSub;
|
||||
extern fn LLVMConstSub(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constMul = LLVMConstMul;
|
||||
extern fn LLVMConstMul(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constAnd = LLVMConstAnd;
|
||||
extern fn LLVMConstAnd(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constOr = LLVMConstOr;
|
||||
extern fn LLVMConstOr(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constXor = LLVMConstXor;
|
||||
extern fn LLVMConstXor(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constShl = LLVMConstShl;
|
||||
extern fn LLVMConstShl(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constLShr = LLVMConstLShr;
|
||||
extern fn LLVMConstLShr(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constAShr = LLVMConstAShr;
|
||||
extern fn LLVMConstAShr(LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constAddrSpaceCast = LLVMConstAddrSpaceCast;
|
||||
extern fn LLVMConstAddrSpaceCast(ConstantVal: *Value, ToType: *Type) *Value;
|
||||
|
||||
pub const constSelect = LLVMConstSelect;
|
||||
extern fn LLVMConstSelect(
|
||||
ConstantCondition: *Value,
|
||||
ConstantIfTrue: *Value,
|
||||
ConstantIfFalse: *Value,
|
||||
) *Value;
|
||||
|
||||
pub const constExtractElement = LLVMConstExtractElement;
|
||||
extern fn LLVMConstExtractElement(VectorConstant: *Value, IndexConstant: *Value) *Value;
|
||||
|
||||
pub const constInsertElement = LLVMConstInsertElement;
|
||||
extern fn LLVMConstInsertElement(
|
||||
VectorConstant: *Value,
|
||||
ElementValueConstant: *Value,
|
||||
IndexConstant: *Value,
|
||||
) *Value;
|
||||
|
||||
pub const constShuffleVector = LLVMConstShuffleVector;
|
||||
extern fn LLVMConstShuffleVector(
|
||||
VectorAConstant: *Value,
|
||||
VectorBConstant: *Value,
|
||||
MaskConstant: *Value,
|
||||
) *Value;
|
||||
|
||||
pub const blockAddress = LLVMBlockAddress;
|
||||
extern fn LLVMBlockAddress(F: *Value, BB: *BasicBlock) *Value;
|
||||
|
||||
pub const setWeak = LLVMSetWeak;
|
||||
extern fn LLVMSetWeak(CmpXchgInst: *Value, IsWeak: Bool) void;
|
||||
|
||||
@@ -323,9 +377,6 @@ pub const Value = opaque {
|
||||
pub const attachMetaData = ZigLLVMAttachMetaData;
|
||||
extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void;
|
||||
|
||||
pub const blockAddress = LLVMBlockAddress;
|
||||
extern fn LLVMBlockAddress(F: *Value, BB: *BasicBlock) *Value;
|
||||
|
||||
pub const dump = LLVMDumpValue;
|
||||
extern fn LLVMDumpValue(Val: *Value) void;
|
||||
};
|
||||
@@ -522,15 +573,18 @@ pub const VerifierFailureAction = enum(c_int) {
|
||||
ReturnStatus,
|
||||
};
|
||||
|
||||
pub const constNeg = LLVMConstNeg;
|
||||
extern fn LLVMConstNeg(ConstantVal: *Value) *Value;
|
||||
|
||||
pub const constVector = LLVMConstVector;
|
||||
extern fn LLVMConstVector(
|
||||
ScalarConstantVals: [*]*Value,
|
||||
Size: c_uint,
|
||||
) *Value;
|
||||
|
||||
pub const constICmp = LLVMConstICmp;
|
||||
extern fn LLVMConstICmp(Predicate: IntPredicate, LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const constFCmp = LLVMConstFCmp;
|
||||
extern fn LLVMConstFCmp(Predicate: RealPredicate, LHSConstant: *Value, RHSConstant: *Value) *Value;
|
||||
|
||||
pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName;
|
||||
extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user