llvm: finish converting instructions

This commit is contained in:
Jacob Young 2023-08-07 09:35:38 -04:00
parent 49cc1bff08
commit a0cb03ed99
4 changed files with 364 additions and 217 deletions

View File

@ -4911,8 +4911,8 @@ pub const FuncGen = struct {
.array_to_slice => try self.airArrayToSlice(inst),
.float_from_int => try self.airFloatFromInt(inst),
.cmpxchg_weak => try self.airCmpxchg(inst, true),
.cmpxchg_strong => try self.airCmpxchg(inst, false),
.cmpxchg_weak => try self.airCmpxchg(inst, .weak),
.cmpxchg_strong => try self.airCmpxchg(inst, .strong),
.fence => try self.airFence(inst),
.atomic_rmw => try self.airAtomicRmw(inst),
.atomic_load => try self.airAtomicLoad(inst),
@ -8723,15 +8723,20 @@ pub const FuncGen = struct {
return .none;
}
fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !Builder.Value {
fn airCmpxchg(
self: *FuncGen,
inst: Air.Inst.Index,
kind: Builder.Function.Instruction.CmpXchg.Kind,
) !Builder.Value {
const o = self.dg.object;
const mod = o.module;
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
const ptr = try self.resolveInst(extra.ptr);
const ptr_ty = self.typeOf(extra.ptr);
var expected_value = try self.resolveInst(extra.expected_value);
var new_value = try self.resolveInst(extra.new_value);
const operand_ty = self.typeOf(extra.ptr).childType(mod);
const operand_ty = ptr_ty.childType(mod);
const llvm_operand_ty = try o.lowerType(operand_ty);
const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, false);
if (llvm_abi_ty != .none) {
@ -8742,22 +8747,18 @@ pub const FuncGen = struct {
new_value = try self.wip.conv(signedness, new_value, llvm_abi_ty, "");
}
const llvm_result_ty = try o.builder.structType(.normal, &.{
if (llvm_abi_ty != .none) llvm_abi_ty else llvm_operand_ty,
.i1,
});
const result = (try self.wip.unimplemented(llvm_result_ty, "")).finish(
self.builder.buildAtomicCmpXchg(
ptr.toLlvm(&self.wip),
expected_value.toLlvm(&self.wip),
new_value.toLlvm(&self.wip),
@enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.successOrder()))),
@enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.failureOrder()))),
llvm.Bool.fromBool(self.sync_scope == .singlethread),
),
&self.wip,
const result = try self.wip.cmpxchg(
kind,
if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal,
ptr,
expected_value,
new_value,
self.sync_scope,
toLlvmAtomicOrdering(extra.successOrder()),
toLlvmAtomicOrdering(extra.failureOrder()),
Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)),
"",
);
result.toLlvm(&self.wip).setWeak(llvm.Bool.fromBool(is_weak));
const optional_ty = self.typeOfIndex(inst);
@ -8789,63 +8790,54 @@ pub const FuncGen = struct {
const is_float = operand_ty.isRuntimeFloat();
const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
const ordering = toLlvmAtomicOrdering(extra.ordering());
const single_threaded = llvm.Bool.fromBool(self.sync_scope == .singlethread);
const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .Xchg);
const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .xchg);
const llvm_operand_ty = try o.lowerType(operand_ty);
const access_kind: Builder.MemoryAccessKind =
if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal;
const ptr_alignment = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));
if (llvm_abi_ty != .none) {
// operand needs widening and truncating or bitcasting.
const casted_operand = try self.wip.cast(
if (is_float) .bitcast else if (is_signed_int) .sext else .zext,
@enumFromInt(@intFromEnum(operand)),
llvm_abi_ty,
return self.wip.cast(if (is_float) .bitcast else .trunc, try self.wip.atomicrmw(
access_kind,
op,
ptr,
try self.wip.cast(
if (is_float) .bitcast else if (is_signed_int) .sext else .zext,
operand,
llvm_abi_ty,
"",
),
self.sync_scope,
ordering,
ptr_alignment,
"",
);
const uncasted_result = (try self.wip.unimplemented(llvm_abi_ty, "")).finish(
self.builder.buildAtomicRmw(
op,
ptr.toLlvm(&self.wip),
casted_operand.toLlvm(&self.wip),
@enumFromInt(@intFromEnum(ordering)),
single_threaded,
),
&self.wip,
);
if (is_float) {
return self.wip.cast(.bitcast, uncasted_result, llvm_operand_ty, "");
} else {
return self.wip.cast(.trunc, uncasted_result, llvm_operand_ty, "");
}
), llvm_operand_ty, "");
}
if (!llvm_operand_ty.isPointer(&o.builder)) {
return (try self.wip.unimplemented(llvm_operand_ty, "")).finish(
self.builder.buildAtomicRmw(
op,
ptr.toLlvm(&self.wip),
operand.toLlvm(&self.wip),
@enumFromInt(@intFromEnum(ordering)),
single_threaded,
),
&self.wip,
);
}
if (!llvm_operand_ty.isPointer(&o.builder)) return self.wip.atomicrmw(
access_kind,
op,
ptr,
operand,
self.sync_scope,
ordering,
ptr_alignment,
"",
);
// It's a pointer but we need to treat it as an int.
const llvm_usize = try o.lowerType(Type.usize);
const casted_operand = try self.wip.cast(.ptrtoint, operand, llvm_usize, "");
const uncasted_result = (try self.wip.unimplemented(llvm_usize, "")).finish(
self.builder.buildAtomicRmw(
op,
ptr.toLlvm(&self.wip),
casted_operand.toLlvm(&self.wip),
@enumFromInt(@intFromEnum(ordering)),
single_threaded,
),
&self.wip,
);
return self.wip.cast(.inttoptr, uncasted_result, llvm_operand_ty, "");
return self.wip.cast(.inttoptr, try self.wip.atomicrmw(
access_kind,
op,
ptr,
try self.wip.cast(.ptrtoint, operand, try o.lowerType(Type.usize), ""),
self.sync_scope,
ordering,
ptr_alignment,
"",
), llvm_operand_ty, "");
}
fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
@ -10581,17 +10573,17 @@ fn toLlvmAtomicRmwBinOp(
op: std.builtin.AtomicRmwOp,
is_signed: bool,
is_float: bool,
) llvm.AtomicRMWBinOp {
) Builder.Function.Instruction.AtomicRmw.Operation {
return switch (op) {
.Xchg => .Xchg,
.Add => if (is_float) .FAdd else return .Add,
.Sub => if (is_float) .FSub else return .Sub,
.And => .And,
.Nand => .Nand,
.Or => .Or,
.Xor => .Xor,
.Max => if (is_float) .FMax else if (is_signed) .Max else return .UMax,
.Min => if (is_float) .FMin else if (is_signed) .Min else return .UMin,
.Xchg => .xchg,
.Add => if (is_float) .fadd else return .add,
.Sub => if (is_float) .fsub else return .sub,
.And => .@"and",
.Nand => .nand,
.Or => .@"or",
.Xor => .xor,
.Max => if (is_float) .fmax else if (is_signed) .max else return .umax,
.Min => if (is_float) .fmin else if (is_signed) .min else return .umin,
};
}

View File

@ -2177,7 +2177,7 @@ pub const Global = struct {
if (!builder.useLibLlvm()) return;
const index = @intFromEnum(self.unwrap(builder));
const name_slice = self.name(builder).slice(builder) orelse "";
builder.llvm.globals.items[index].setValueName2(name_slice.ptr, name_slice.len);
builder.llvm.globals.items[index].setValueName(name_slice.ptr, name_slice.len);
}
fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
@ -3759,12 +3759,15 @@ pub const Function = struct {
arg,
ashr,
@"ashr exact",
atomicrmw,
bitcast,
block,
br,
br_cond,
call,
@"call fast",
cmpxchg,
@"cmpxchg weak",
extractelement,
extractvalue,
fadd,
@ -3833,8 +3836,6 @@ pub const Function = struct {
inttoptr,
load,
@"load atomic",
@"load atomic volatile",
@"load volatile",
lshr,
@"lshr exact",
mul,
@ -3865,8 +3866,6 @@ pub const Function = struct {
srem,
store,
@"store atomic",
@"store atomic volatile",
@"store volatile",
sub,
@"sub nsw",
@"sub nuw",
@ -3879,7 +3878,6 @@ pub const Function = struct {
@"udiv exact",
urem,
uitofp,
unimplemented,
@"unreachable",
va_arg,
xor,
@ -3920,8 +3918,6 @@ pub const Function = struct {
.@"ret void",
.store,
.@"store atomic",
.@"store atomic volatile",
.@"store volatile",
.@"switch",
.@"unreachable",
=> false,
@ -3933,7 +3929,6 @@ pub const Function = struct {
.@"notail call fast",
.@"tail call",
.@"tail call fast",
.unimplemented,
=> self.typeOfWip(wip) != .void,
else => true,
};
@ -4003,6 +3998,7 @@ pub const Function = struct {
),
.arg => wip.function.typeOf(wip.builder)
.functionParameters(wip.builder)[instruction.data],
.atomicrmw => wip.extraData(AtomicRmw, instruction.data).val.typeOfWip(wip),
.block => .label,
.br,
.br_cond,
@ -4011,8 +4007,6 @@ pub const Function = struct {
.@"ret void",
.store,
.@"store atomic",
.@"store atomic volatile",
.@"store volatile",
.@"switch",
.@"unreachable",
=> .none,
@ -4025,6 +4019,12 @@ pub const Function = struct {
.@"tail call",
.@"tail call fast",
=> wip.extraData(Call, instruction.data).ty.functionReturn(wip.builder),
.cmpxchg,
.@"cmpxchg weak",
=> wip.builder.structTypeAssumeCapacity(.normal, &.{
wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip),
.i1,
}) catch unreachable,
.extractelement => wip.extraData(ExtractElement, instruction.data)
.val.typeOfWip(wip).childType(wip.builder),
.extractvalue => {
@ -4096,8 +4096,6 @@ pub const Function = struct {
.insertvalue => wip.extraData(InsertValue, instruction.data).val.typeOfWip(wip),
.load,
.@"load atomic",
.@"load atomic volatile",
.@"load volatile",
=> wip.extraData(Load, instruction.data).type,
.phi,
.@"phi fast",
@ -4112,7 +4110,6 @@ pub const Function = struct {
wip.builder,
);
},
.unimplemented => @enumFromInt(instruction.data),
.va_arg => wip.extraData(VaArg, instruction.data).type,
};
}
@ -4186,6 +4183,8 @@ pub const Function = struct {
),
.arg => function.global.typeOf(builder)
.functionParameters(builder)[instruction.data],
.atomicrmw => function.extraData(AtomicRmw, instruction.data)
.val.typeOf(function_index, builder),
.block => .label,
.br,
.br_cond,
@ -4194,8 +4193,6 @@ pub const Function = struct {
.@"ret void",
.store,
.@"store atomic",
.@"store atomic volatile",
.@"store volatile",
.@"switch",
.@"unreachable",
=> .none,
@ -4208,6 +4205,13 @@ pub const Function = struct {
.@"tail call",
.@"tail call fast",
=> function.extraData(Call, instruction.data).ty.functionReturn(builder),
.cmpxchg,
.@"cmpxchg weak",
=> builder.structTypeAssumeCapacity(.normal, &.{
function.extraData(CmpXchg, instruction.data)
.cmp.typeOf(function_index, builder),
.i1,
}) catch unreachable,
.extractelement => function.extraData(ExtractElement, instruction.data)
.val.typeOf(function_index, builder).childType(builder),
.extractvalue => {
@ -4282,8 +4286,6 @@ pub const Function = struct {
.val.typeOf(function_index, builder),
.load,
.@"load atomic",
.@"load atomic volatile",
.@"load volatile",
=> function.extraData(Load, instruction.data).type,
.phi,
.@"phi fast",
@ -4298,7 +4300,6 @@ pub const Function = struct {
builder,
);
},
.unimplemented => @enumFromInt(instruction.data),
.va_arg => function.extraData(VaArg, instruction.data).type,
};
}
@ -4346,7 +4347,7 @@ pub const Function = struct {
return wip.llvm.instructions.items[@intFromEnum(self)];
}
fn llvmName(self: Instruction.Index, wip: *const WipFunction) [*:0]const u8 {
fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 {
return if (wip.builder.strip)
""
else
@ -4419,15 +4420,49 @@ pub const Function = struct {
};
pub const Load = struct {
info: MemoryAccessInfo,
type: Type,
ptr: Value,
info: MemoryAccessInfo,
};
pub const Store = struct {
info: MemoryAccessInfo,
val: Value,
ptr: Value,
};
pub const CmpXchg = struct {
info: MemoryAccessInfo,
ptr: Value,
cmp: Value,
new: Value,
pub const Kind = enum { strong, weak };
};
pub const AtomicRmw = struct {
info: MemoryAccessInfo,
ptr: Value,
val: Value,
pub const Operation = enum(u5) {
xchg,
add,
sub,
@"and",
nand,
@"or",
xor,
max,
min,
umax,
umin,
fadd,
fsub,
fmax,
fmin,
none = std.math.maxInt(u5),
};
};
pub const GetElementPtr = struct {
@ -5163,21 +5198,21 @@ pub const WipFunction = struct {
pub fn load(
self: *WipFunction,
kind: MemoryAccessKind,
access_kind: MemoryAccessKind,
ty: Type,
ptr: Value,
alignment: Alignment,
name: []const u8,
) Allocator.Error!Value {
return self.loadAtomic(kind, ty, ptr, .system, .none, alignment, name);
return self.loadAtomic(access_kind, ty, ptr, .system, .none, alignment, name);
}
pub fn loadAtomic(
self: *WipFunction,
kind: MemoryAccessKind,
access_kind: MemoryAccessKind,
ty: Type,
ptr: Value,
scope: SyncScope,
sync_scope: SyncScope,
ordering: AtomicOrdering,
alignment: Alignment,
name: []const u8,
@ -5186,22 +5221,21 @@ pub const WipFunction = struct {
try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0);
const instruction = try self.addInst(name, .{
.tag = switch (ordering) {
.none => switch (kind) {
.normal => .load,
.@"volatile" => .@"load volatile",
},
else => switch (kind) {
.normal => .@"load atomic",
.@"volatile" => .@"load atomic volatile",
},
.none => .load,
else => .@"load atomic",
},
.data = self.addExtraAssumeCapacity(Instruction.Load{
.info = .{
.access_kind = access_kind,
.sync_scope = switch (ordering) {
.none => .system,
else => sync_scope,
},
.success_ordering = ordering,
.alignment = alignment,
},
.type = ty,
.ptr = ptr,
.info = .{ .scope = switch (ordering) {
.none => .system,
else => scope,
}, .ordering = ordering, .alignment = alignment },
}),
});
if (self.builder.useLibLlvm()) {
@ -5210,6 +5244,7 @@ pub const WipFunction = struct {
ptr.toLlvm(self),
instruction.llvmName(self),
);
if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
@ -5229,10 +5264,10 @@ pub const WipFunction = struct {
pub fn storeAtomic(
self: *WipFunction,
kind: MemoryAccessKind,
access_kind: MemoryAccessKind,
val: Value,
ptr: Value,
scope: SyncScope,
sync_scope: SyncScope,
ordering: AtomicOrdering,
alignment: Alignment,
) Allocator.Error!Instruction.Index {
@ -5240,30 +5275,26 @@ pub const WipFunction = struct {
try self.ensureUnusedExtraCapacity(1, Instruction.Store, 0);
const instruction = try self.addInst(null, .{
.tag = switch (ordering) {
.none => switch (kind) {
.normal => .store,
.@"volatile" => .@"store volatile",
},
else => switch (kind) {
.normal => .@"store atomic",
.@"volatile" => .@"store atomic volatile",
},
.none => .store,
else => .@"store atomic",
},
.data = self.addExtraAssumeCapacity(Instruction.Store{
.info = .{
.access_kind = access_kind,
.sync_scope = switch (ordering) {
.none => .system,
else => sync_scope,
},
.success_ordering = ordering,
.alignment = alignment,
},
.val = val,
.ptr = ptr,
.info = .{ .scope = switch (ordering) {
.none => .system,
else => scope,
}, .ordering = ordering, .alignment = alignment },
}),
});
if (self.builder.useLibLlvm()) {
const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self));
switch (kind) {
.normal => {},
.@"volatile" => llvm_instruction.setVolatile(.True),
}
if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
@ -5273,7 +5304,7 @@ pub const WipFunction = struct {
pub fn fence(
self: *WipFunction,
scope: SyncScope,
sync_scope: SyncScope,
ordering: AtomicOrdering,
) Allocator.Error!Instruction.Index {
assert(ordering != .none);
@ -5281,21 +5312,130 @@ pub const WipFunction = struct {
const instruction = try self.addInst(null, .{
.tag = .fence,
.data = @bitCast(MemoryAccessInfo{
.scope = scope,
.ordering = ordering,
.alignment = undefined,
.sync_scope = sync_scope,
.success_ordering = ordering,
}),
});
if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
self.llvm.builder.buildFence(
@enumFromInt(@intFromEnum(ordering)),
llvm.Bool.fromBool(scope == .singlethread),
llvm.Bool.fromBool(sync_scope == .singlethread),
"",
),
);
return instruction;
}
pub fn cmpxchg(
self: *WipFunction,
kind: Instruction.CmpXchg.Kind,
access_kind: MemoryAccessKind,
ptr: Value,
cmp: Value,
new: Value,
sync_scope: SyncScope,
success_ordering: AtomicOrdering,
failure_ordering: AtomicOrdering,
alignment: Alignment,
name: []const u8,
) Allocator.Error!Value {
assert(ptr.typeOfWip(self).isPointer(self.builder));
const ty = cmp.typeOfWip(self);
assert(ty == new.typeOfWip(self));
assert(success_ordering != .none);
assert(failure_ordering != .none);
_ = try self.builder.structType(.normal, &.{ ty, .i1 });
try self.ensureUnusedExtraCapacity(1, Instruction.CmpXchg, 0);
const instruction = try self.addInst(name, .{
.tag = switch (kind) {
.strong => .cmpxchg,
.weak => .@"cmpxchg weak",
},
.data = self.addExtraAssumeCapacity(Instruction.CmpXchg{
.info = .{
.access_kind = access_kind,
.sync_scope = sync_scope,
.success_ordering = success_ordering,
.failure_ordering = failure_ordering,
.alignment = alignment,
},
.ptr = ptr,
.cmp = cmp,
.new = new,
}),
});
if (self.builder.useLibLlvm()) {
const llvm_instruction = self.llvm.builder.buildAtomicCmpXchg(
ptr.toLlvm(self),
cmp.toLlvm(self),
new.toLlvm(self),
@enumFromInt(@intFromEnum(success_ordering)),
@enumFromInt(@intFromEnum(failure_ordering)),
llvm.Bool.fromBool(sync_scope == .singlethread),
);
if (kind == .weak) llvm_instruction.setWeak(.True);
if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
const llvm_name = instruction.llvmName(self);
if (llvm_name.len > 0) llvm_instruction.setValueName(
llvm_name.ptr,
@intCast(llvm_name.len),
);
self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
}
return instruction.toValue();
}
pub fn atomicrmw(
self: *WipFunction,
access_kind: MemoryAccessKind,
operation: Instruction.AtomicRmw.Operation,
ptr: Value,
val: Value,
sync_scope: SyncScope,
ordering: AtomicOrdering,
alignment: Alignment,
name: []const u8,
) Allocator.Error!Value {
assert(ptr.typeOfWip(self).isPointer(self.builder));
assert(ordering != .none);
try self.ensureUnusedExtraCapacity(1, Instruction.AtomicRmw, 0);
const instruction = try self.addInst(name, .{
.tag = .atomicrmw,
.data = self.addExtraAssumeCapacity(Instruction.AtomicRmw{
.info = .{
.access_kind = access_kind,
.atomic_rmw_operation = operation,
.sync_scope = sync_scope,
.success_ordering = ordering,
.alignment = alignment,
},
.ptr = ptr,
.val = val,
}),
});
if (self.builder.useLibLlvm()) {
const llvm_instruction = self.llvm.builder.buildAtomicRmw(
@enumFromInt(@intFromEnum(operation)),
ptr.toLlvm(self),
val.toLlvm(self),
@enumFromInt(@intFromEnum(ordering)),
llvm.Bool.fromBool(sync_scope == .singlethread),
);
if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
const llvm_name = instruction.llvmName(self);
if (llvm_name.len > 0) llvm_instruction.setValueName(
llvm_name.ptr,
@intCast(llvm_name.len),
);
self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
}
return instruction.toValue();
}
pub fn gep(
self: *WipFunction,
kind: Instruction.GetElementPtr.Kind,
@ -5747,30 +5887,6 @@ pub const WipFunction = struct {
return instruction.toValue();
}
pub const WipUnimplemented = struct {
instruction: Instruction.Index,
pub fn finish(self: WipUnimplemented, val: *llvm.Value, wip: *WipFunction) Value {
assert(wip.builder.useLibLlvm());
wip.llvm.instructions.items[@intFromEnum(self.instruction)] = val;
return self.instruction.toValue();
}
};
pub fn unimplemented(
self: *WipFunction,
ty: Type,
name: []const u8,
) Allocator.Error!WipUnimplemented {
try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
const instruction = try self.addInst(name, .{
.tag = .unimplemented,
.data = @intFromEnum(ty),
});
if (self.builder.useLibLlvm()) _ = self.llvm.instructions.addOneAssumeCapacity();
return .{ .instruction = instruction };
}
pub fn finish(self: *WipFunction) Allocator.Error!void {
const gpa = self.builder.gpa;
const function = self.function.ptr(self.builder);
@ -6035,19 +6151,19 @@ pub const WipFunction = struct {
.arg,
.block,
=> unreachable,
.atomicrmw => {
const extra = self.extraData(Instruction.AtomicRmw, instruction.data);
instruction.data = wip_extra.addExtra(Instruction.AtomicRmw{
.info = extra.info,
.ptr = instructions.map(extra.ptr),
.val = instructions.map(extra.val),
});
},
.br,
.fence,
.@"ret void",
.unimplemented,
.@"unreachable",
=> {},
.extractelement => {
const extra = self.extraData(Instruction.ExtractElement, instruction.data);
instruction.data = wip_extra.addExtra(Instruction.ExtractElement{
.val = instructions.map(extra.val),
.index = instructions.map(extra.index),
});
},
.br_cond => {
const extra = self.extraData(Instruction.BrCond, instruction.data);
instruction.data = wip_extra.addExtra(Instruction.BrCond{
@ -6076,6 +6192,24 @@ pub const WipFunction = struct {
});
wip_extra.appendMappedValues(args, instructions);
},
.cmpxchg,
.@"cmpxchg weak",
=> {
const extra = self.extraData(Instruction.CmpXchg, instruction.data);
instruction.data = wip_extra.addExtra(Instruction.CmpXchg{
.info = extra.info,
.ptr = instructions.map(extra.ptr),
.cmp = instructions.map(extra.cmp),
.new = instructions.map(extra.new),
});
},
.extractelement => {
const extra = self.extraData(Instruction.ExtractElement, instruction.data);
instruction.data = wip_extra.addExtra(Instruction.ExtractElement{
.val = instructions.map(extra.val),
.index = instructions.map(extra.index),
});
},
.extractvalue => {
var extra = self.extraDataTrail(Instruction.ExtractValue, instruction.data);
const indices = extra.trail.next(extra.data.indices_len, u32, self);
@ -6121,8 +6255,6 @@ pub const WipFunction = struct {
},
.load,
.@"load atomic",
.@"load atomic volatile",
.@"load volatile",
=> {
const extra = self.extraData(Instruction.Load, instruction.data);
instruction.data = wip_extra.addExtra(Instruction.Load{
@ -6164,8 +6296,6 @@ pub const WipFunction = struct {
},
.store,
.@"store atomic",
.@"store atomic volatile",
.@"store volatile",
=> {
const extra = self.extraData(Instruction.Store, instruction.data);
instruction.data = wip_extra.addExtra(Instruction.Store{
@ -6619,6 +6749,15 @@ pub const IntegerCondition = enum(u6) {
pub const MemoryAccessKind = enum(u1) {
normal,
@"volatile",
pub fn format(
self: MemoryAccessKind,
comptime prefix: []const u8,
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
if (self != .normal) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
}
};
pub const SyncScope = enum(u1) {
@ -6632,7 +6771,7 @@ pub const SyncScope = enum(u1) {
writer: anytype,
) @TypeOf(writer).Error!void {
if (self != .system) try writer.print(
\\{s} syncscope("{s}")
\\{s}syncscope("{s}")
, .{ prefix, @tagName(self) });
}
};
@ -6652,15 +6791,18 @@ pub const AtomicOrdering = enum(u3) {
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
if (self != .none) try writer.print("{s} {s}", .{ prefix, @tagName(self) });
if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
}
};
const MemoryAccessInfo = packed struct(u32) {
scope: SyncScope,
ordering: AtomicOrdering,
alignment: Alignment,
_: u22 = undefined,
access_kind: MemoryAccessKind = .normal,
atomic_rmw_operation: Function.Instruction.AtomicRmw.Operation = .none,
sync_scope: SyncScope,
success_ordering: AtomicOrdering,
failure_ordering: AtomicOrdering = .none,
alignment: Alignment = .default,
_: u13 = undefined,
};
pub const FastMath = packed struct(u32) {
@ -7542,7 +7684,7 @@ pub fn init(options: Options) InitError!Builder {
if (options.name.len > 0) self.source_filename = try self.string(options.name);
self.initializeLLVMTarget(options.target.cpu.arch);
if (self.useLibLlvm()) self.llvm.module = llvm.Module.createWithName(
(self.source_filename.slice(&self) orelse "").ptr,
(self.source_filename.slice(&self) orelse ""),
self.llvm.context,
);
@ -8983,6 +9125,21 @@ pub fn printUnbuffered(
});
},
.arg => unreachable,
.atomicrmw => |tag| {
const extra =
function.extraData(Function.Instruction.AtomicRmw, instruction.data);
try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.info.access_kind,
@tagName(extra.info.atomic_rmw_operation),
extra.ptr.fmt(function_index, self),
extra.val.fmt(function_index, self),
extra.info.sync_scope,
extra.info.success_ordering,
extra.info.alignment,
});
},
.block => {
block_incoming_len = instruction.data;
const name = instruction_index.name(&function);
@ -9056,6 +9213,24 @@ pub fn printUnbuffered(
});
try writer.writeByte('\n');
},
.cmpxchg,
.@"cmpxchg weak",
=> |tag| {
const extra =
function.extraData(Function.Instruction.CmpXchg, instruction.data);
try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.info.access_kind,
extra.ptr.fmt(function_index, self),
extra.cmp.fmt(function_index, self),
extra.new.fmt(function_index, self),
extra.info.sync_scope,
extra.info.success_ordering,
extra.info.failure_ordering,
extra.info.alignment,
});
},
.extractelement => |tag| {
const extra = function.extraData(
Function.Instruction.ExtractElement,
@ -9084,7 +9259,11 @@ pub fn printUnbuffered(
},
.fence => |tag| {
const info: MemoryAccessInfo = @bitCast(instruction.data);
try writer.print(" {s}{}{}", .{ @tagName(tag), info.scope, info.ordering });
try writer.print(" {s}{ }{ }", .{
@tagName(tag),
info.sync_scope,
info.success_ordering,
});
},
.fneg,
.@"fneg fast",
@ -9145,18 +9324,17 @@ pub fn printUnbuffered(
},
.load,
.@"load atomic",
.@"load atomic volatile",
.@"load volatile",
=> |tag| {
const extra =
function.extraData(Function.Instruction.Load, instruction.data);
try writer.print(" %{} = {s} {%}, {%}{}{}{, }\n", .{
try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.info.access_kind,
extra.type.fmt(self),
extra.ptr.fmt(function_index, self),
extra.info.scope,
extra.info.ordering,
extra.info.sync_scope,
extra.info.success_ordering,
extra.info.alignment,
});
},
@ -9220,17 +9398,16 @@ pub fn printUnbuffered(
},
.store,
.@"store atomic",
.@"store atomic volatile",
.@"store volatile",
=> |tag| {
const extra =
function.extraData(Function.Instruction.Store, instruction.data);
try writer.print(" {s} {%}, {%}{}{}{, }\n", .{
try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{
@tagName(tag),
extra.info.access_kind,
extra.val.fmt(function_index, self),
extra.ptr.fmt(function_index, self),
extra.info.scope,
extra.info.ordering,
extra.info.sync_scope,
extra.info.success_ordering,
extra.info.alignment,
});
},
@ -9254,25 +9431,6 @@ pub fn printUnbuffered(
);
try writer.writeAll(" ]\n");
},
.unimplemented => |tag| {
const ty: Type = @enumFromInt(instruction.data);
if (true) {
try writer.writeAll(" ");
switch (ty) {
.none, .void => {},
else => try writer.print("%{} = ", .{
instruction_index.name(&function).fmt(self),
}),
}
try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) });
} else switch (ty) {
.none, .void => {},
else => try writer.print(" %{} = load {%}, ptr undef\n", .{
instruction_index.name(&function).fmt(self),
ty.fmt(self),
}),
}
},
.va_arg => |tag| {
const extra =
function.extraData(Function.Instruction.VaArg, instruction.data);

View File

@ -330,10 +330,7 @@ pub const Value = opaque {
pub const fnSetSubprogram = ZigLLVMFnSetSubprogram;
extern fn ZigLLVMFnSetSubprogram(f: *Value, subprogram: *DISubprogram) void;
pub const setValueName = LLVMSetValueName;
extern fn LLVMSetValueName(Val: *Value, Name: [*:0]const u8) void;
pub const setValueName2 = LLVMSetValueName2;
pub const setValueName = LLVMSetValueName2;
extern fn LLVMSetValueName2(Val: *Value, Name: [*]const u8, NameLen: usize) void;
pub const getValueName = LLVMGetValueName;

View File

@ -1123,11 +1123,11 @@ void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) {
}
ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
}
void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression));
unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression));
}
static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");