authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-07 09:35:38-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-08 21:32:50-04:00
loga0cb03ed99d0e157389d8afad4ab4f9c8e8ea2db
treeb7bac1f57b40c2f53e86fd8a2183c11add1a7d9c
parent49cc1bff086e9c521c110b35692a87f75e25c7ad

llvm: finish converting instructions


4 files changed, 364 insertions(+), 217 deletions(-)

src/codegen/llvm.zig+70-78
......@@ -4911,8 +4911,8 @@ pub const FuncGen = struct {
49114911
49124912 .array_to_slice => try self.airArrayToSlice(inst),
49134913 .float_from_int => try self.airFloatFromInt(inst),
4914 .cmpxchg_weak => try self.airCmpxchg(inst, true),
4915 .cmpxchg_strong => try self.airCmpxchg(inst, false),
4914 .cmpxchg_weak => try self.airCmpxchg(inst, .weak),
4915 .cmpxchg_strong => try self.airCmpxchg(inst, .strong),
49164916 .fence => try self.airFence(inst),
49174917 .atomic_rmw => try self.airAtomicRmw(inst),
49184918 .atomic_load => try self.airAtomicLoad(inst),
......@@ -8723,15 +8723,20 @@ pub const FuncGen = struct {
87238723 return .none;
87248724 }
87258725
8726 fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !Builder.Value {
8726 fn airCmpxchg(
8727 self: *FuncGen,
8728 inst: Air.Inst.Index,
8729 kind: Builder.Function.Instruction.CmpXchg.Kind,
8730 ) !Builder.Value {
87278731 const o = self.dg.object;
87288732 const mod = o.module;
87298733 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
87308734 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
87318735 const ptr = try self.resolveInst(extra.ptr);
8736 const ptr_ty = self.typeOf(extra.ptr);
87328737 var expected_value = try self.resolveInst(extra.expected_value);
87338738 var new_value = try self.resolveInst(extra.new_value);
8734 const operand_ty = self.typeOf(extra.ptr).childType(mod);
8739 const operand_ty = ptr_ty.childType(mod);
87358740 const llvm_operand_ty = try o.lowerType(operand_ty);
87368741 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, false);
87378742 if (llvm_abi_ty != .none) {
......@@ -8742,22 +8747,18 @@ pub const FuncGen = struct {
87428747 new_value = try self.wip.conv(signedness, new_value, llvm_abi_ty, "");
87438748 }
87448749
8745 const llvm_result_ty = try o.builder.structType(.normal, &.{
8746 if (llvm_abi_ty != .none) llvm_abi_ty else llvm_operand_ty,
8747 .i1,
8748 });
8749 const result = (try self.wip.unimplemented(llvm_result_ty, "")).finish(
8750 self.builder.buildAtomicCmpXchg(
8751 ptr.toLlvm(&self.wip),
8752 expected_value.toLlvm(&self.wip),
8753 new_value.toLlvm(&self.wip),
8754 @enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.successOrder()))),
8755 @enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.failureOrder()))),
8756 llvm.Bool.fromBool(self.sync_scope == .singlethread),
8757 ),
8758 &self.wip,
8750 const result = try self.wip.cmpxchg(
8751 kind,
8752 if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal,
8753 ptr,
8754 expected_value,
8755 new_value,
8756 self.sync_scope,
8757 toLlvmAtomicOrdering(extra.successOrder()),
8758 toLlvmAtomicOrdering(extra.failureOrder()),
8759 Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)),
8760 "",
87598761 );
8760 result.toLlvm(&self.wip).setWeak(llvm.Bool.fromBool(is_weak));
87618762
87628763 const optional_ty = self.typeOfIndex(inst);
87638764
......@@ -8789,63 +8790,54 @@ pub const FuncGen = struct {
87898790 const is_float = operand_ty.isRuntimeFloat();
87908791 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
87918792 const ordering = toLlvmAtomicOrdering(extra.ordering());
8792 const single_threaded = llvm.Bool.fromBool(self.sync_scope == .singlethread);
8793 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .Xchg);
8793 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .xchg);
87948794 const llvm_operand_ty = try o.lowerType(operand_ty);
8795
8796 const access_kind: Builder.MemoryAccessKind =
8797 if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal;
8798 const ptr_alignment = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));
8799
87958800 if (llvm_abi_ty != .none) {
87968801 // operand needs widening and truncating or bitcasting.
8797 const casted_operand = try self.wip.cast(
8798 if (is_float) .bitcast else if (is_signed_int) .sext else .zext,
8799 @enumFromInt(@intFromEnum(operand)),
8800 llvm_abi_ty,
8801 "",
8802 );
8803
8804 const uncasted_result = (try self.wip.unimplemented(llvm_abi_ty, "")).finish(
8805 self.builder.buildAtomicRmw(
8806 op,
8807 ptr.toLlvm(&self.wip),
8808 casted_operand.toLlvm(&self.wip),
8809 @enumFromInt(@intFromEnum(ordering)),
8810 single_threaded,
8802 return self.wip.cast(if (is_float) .bitcast else .trunc, try self.wip.atomicrmw(
8803 access_kind,
8804 op,
8805 ptr,
8806 try self.wip.cast(
8807 if (is_float) .bitcast else if (is_signed_int) .sext else .zext,
8808 operand,
8809 llvm_abi_ty,
8810 "",
88118811 ),
8812 &self.wip,
8813 );
8814
8815 if (is_float) {
8816 return self.wip.cast(.bitcast, uncasted_result, llvm_operand_ty, "");
8817 } else {
8818 return self.wip.cast(.trunc, uncasted_result, llvm_operand_ty, "");
8819 }
8812 self.sync_scope,
8813 ordering,
8814 ptr_alignment,
8815 "",
8816 ), llvm_operand_ty, "");
88208817 }
88218818
8822 if (!llvm_operand_ty.isPointer(&o.builder)) {
8823 return (try self.wip.unimplemented(llvm_operand_ty, "")).finish(
8824 self.builder.buildAtomicRmw(
8825 op,
8826 ptr.toLlvm(&self.wip),
8827 operand.toLlvm(&self.wip),
8828 @enumFromInt(@intFromEnum(ordering)),
8829 single_threaded,
8830 ),
8831 &self.wip,
8832 );
8833 }
8819 if (!llvm_operand_ty.isPointer(&o.builder)) return self.wip.atomicrmw(
8820 access_kind,
8821 op,
8822 ptr,
8823 operand,
8824 self.sync_scope,
8825 ordering,
8826 ptr_alignment,
8827 "",
8828 );
88348829
88358830 // It's a pointer but we need to treat it as an int.
8836 const llvm_usize = try o.lowerType(Type.usize);
8837 const casted_operand = try self.wip.cast(.ptrtoint, operand, llvm_usize, "");
8838 const uncasted_result = (try self.wip.unimplemented(llvm_usize, "")).finish(
8839 self.builder.buildAtomicRmw(
8840 op,
8841 ptr.toLlvm(&self.wip),
8842 casted_operand.toLlvm(&self.wip),
8843 @enumFromInt(@intFromEnum(ordering)),
8844 single_threaded,
8845 ),
8846 &self.wip,
8847 );
8848 return self.wip.cast(.inttoptr, uncasted_result, llvm_operand_ty, "");
8831 return self.wip.cast(.inttoptr, try self.wip.atomicrmw(
8832 access_kind,
8833 op,
8834 ptr,
8835 try self.wip.cast(.ptrtoint, operand, try o.lowerType(Type.usize), ""),
8836 self.sync_scope,
8837 ordering,
8838 ptr_alignment,
8839 "",
8840 ), llvm_operand_ty, "");
88498841 }
88508842
88518843 fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -10581,17 +10573,17 @@ fn toLlvmAtomicRmwBinOp(
1058110573 op: std.builtin.AtomicRmwOp,
1058210574 is_signed: bool,
1058310575 is_float: bool,
10584) llvm.AtomicRMWBinOp {
10576) Builder.Function.Instruction.AtomicRmw.Operation {
1058510577 return switch (op) {
10586 .Xchg => .Xchg,
10587 .Add => if (is_float) .FAdd else return .Add,
10588 .Sub => if (is_float) .FSub else return .Sub,
10589 .And => .And,
10590 .Nand => .Nand,
10591 .Or => .Or,
10592 .Xor => .Xor,
10593 .Max => if (is_float) .FMax else if (is_signed) .Max else return .UMax,
10594 .Min => if (is_float) .FMin else if (is_signed) .Min else return .UMin,
10578 .Xchg => .xchg,
10579 .Add => if (is_float) .fadd else return .add,
10580 .Sub => if (is_float) .fsub else return .sub,
10581 .And => .@"and",
10582 .Nand => .nand,
10583 .Or => .@"or",
10584 .Xor => .xor,
10585 .Max => if (is_float) .fmax else if (is_signed) .max else return .umax,
10586 .Min => if (is_float) .fmin else if (is_signed) .min else return .umin,
1059510587 };
1059610588}
1059710589
src/codegen/llvm/Builder.zig+291-133
......@@ -2177,7 +2177,7 @@ pub const Global = struct {
21772177 if (!builder.useLibLlvm()) return;
21782178 const index = @intFromEnum(self.unwrap(builder));
21792179 const name_slice = self.name(builder).slice(builder) orelse "";
2180 builder.llvm.globals.items[index].setValueName2(name_slice.ptr, name_slice.len);
2180 builder.llvm.globals.items[index].setValueName(name_slice.ptr, name_slice.len);
21812181 }
21822182
21832183 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
......@@ -3759,12 +3759,15 @@ pub const Function = struct {
37593759 arg,
37603760 ashr,
37613761 @"ashr exact",
3762 atomicrmw,
37623763 bitcast,
37633764 block,
37643765 br,
37653766 br_cond,
37663767 call,
37673768 @"call fast",
3769 cmpxchg,
3770 @"cmpxchg weak",
37683771 extractelement,
37693772 extractvalue,
37703773 fadd,
......@@ -3833,8 +3836,6 @@ pub const Function = struct {
38333836 inttoptr,
38343837 load,
38353838 @"load atomic",
3836 @"load atomic volatile",
3837 @"load volatile",
38383839 lshr,
38393840 @"lshr exact",
38403841 mul,
......@@ -3865,8 +3866,6 @@ pub const Function = struct {
38653866 srem,
38663867 store,
38673868 @"store atomic",
3868 @"store atomic volatile",
3869 @"store volatile",
38703869 sub,
38713870 @"sub nsw",
38723871 @"sub nuw",
......@@ -3879,7 +3878,6 @@ pub const Function = struct {
38793878 @"udiv exact",
38803879 urem,
38813880 uitofp,
3882 unimplemented,
38833881 @"unreachable",
38843882 va_arg,
38853883 xor,
......@@ -3920,8 +3918,6 @@ pub const Function = struct {
39203918 .@"ret void",
39213919 .store,
39223920 .@"store atomic",
3923 .@"store atomic volatile",
3924 .@"store volatile",
39253921 .@"switch",
39263922 .@"unreachable",
39273923 => false,
......@@ -3933,7 +3929,6 @@ pub const Function = struct {
39333929 .@"notail call fast",
39343930 .@"tail call",
39353931 .@"tail call fast",
3936 .unimplemented,
39373932 => self.typeOfWip(wip) != .void,
39383933 else => true,
39393934 };
......@@ -4003,6 +3998,7 @@ pub const Function = struct {
40033998 ),
40043999 .arg => wip.function.typeOf(wip.builder)
40054000 .functionParameters(wip.builder)[instruction.data],
4001 .atomicrmw => wip.extraData(AtomicRmw, instruction.data).val.typeOfWip(wip),
40064002 .block => .label,
40074003 .br,
40084004 .br_cond,
......@@ -4011,8 +4007,6 @@ pub const Function = struct {
40114007 .@"ret void",
40124008 .store,
40134009 .@"store atomic",
4014 .@"store atomic volatile",
4015 .@"store volatile",
40164010 .@"switch",
40174011 .@"unreachable",
40184012 => .none,
......@@ -4025,6 +4019,12 @@ pub const Function = struct {
40254019 .@"tail call",
40264020 .@"tail call fast",
40274021 => wip.extraData(Call, instruction.data).ty.functionReturn(wip.builder),
4022 .cmpxchg,
4023 .@"cmpxchg weak",
4024 => wip.builder.structTypeAssumeCapacity(.normal, &.{
4025 wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip),
4026 .i1,
4027 }) catch unreachable,
40284028 .extractelement => wip.extraData(ExtractElement, instruction.data)
40294029 .val.typeOfWip(wip).childType(wip.builder),
40304030 .extractvalue => {
......@@ -4096,8 +4096,6 @@ pub const Function = struct {
40964096 .insertvalue => wip.extraData(InsertValue, instruction.data).val.typeOfWip(wip),
40974097 .load,
40984098 .@"load atomic",
4099 .@"load atomic volatile",
4100 .@"load volatile",
41014099 => wip.extraData(Load, instruction.data).type,
41024100 .phi,
41034101 .@"phi fast",
......@@ -4112,7 +4110,6 @@ pub const Function = struct {
41124110 wip.builder,
41134111 );
41144112 },
4115 .unimplemented => @enumFromInt(instruction.data),
41164113 .va_arg => wip.extraData(VaArg, instruction.data).type,
41174114 };
41184115 }
......@@ -4186,6 +4183,8 @@ pub const Function = struct {
41864183 ),
41874184 .arg => function.global.typeOf(builder)
41884185 .functionParameters(builder)[instruction.data],
4186 .atomicrmw => function.extraData(AtomicRmw, instruction.data)
4187 .val.typeOf(function_index, builder),
41894188 .block => .label,
41904189 .br,
41914190 .br_cond,
......@@ -4194,8 +4193,6 @@ pub const Function = struct {
41944193 .@"ret void",
41954194 .store,
41964195 .@"store atomic",
4197 .@"store atomic volatile",
4198 .@"store volatile",
41994196 .@"switch",
42004197 .@"unreachable",
42014198 => .none,
......@@ -4208,6 +4205,13 @@ pub const Function = struct {
42084205 .@"tail call",
42094206 .@"tail call fast",
42104207 => function.extraData(Call, instruction.data).ty.functionReturn(builder),
4208 .cmpxchg,
4209 .@"cmpxchg weak",
4210 => builder.structTypeAssumeCapacity(.normal, &.{
4211 function.extraData(CmpXchg, instruction.data)
4212 .cmp.typeOf(function_index, builder),
4213 .i1,
4214 }) catch unreachable,
42114215 .extractelement => function.extraData(ExtractElement, instruction.data)
42124216 .val.typeOf(function_index, builder).childType(builder),
42134217 .extractvalue => {
......@@ -4282,8 +4286,6 @@ pub const Function = struct {
42824286 .val.typeOf(function_index, builder),
42834287 .load,
42844288 .@"load atomic",
4285 .@"load atomic volatile",
4286 .@"load volatile",
42874289 => function.extraData(Load, instruction.data).type,
42884290 .phi,
42894291 .@"phi fast",
......@@ -4298,7 +4300,6 @@ pub const Function = struct {
42984300 builder,
42994301 );
43004302 },
4301 .unimplemented => @enumFromInt(instruction.data),
43024303 .va_arg => function.extraData(VaArg, instruction.data).type,
43034304 };
43044305 }
......@@ -4346,7 +4347,7 @@ pub const Function = struct {
43464347 return wip.llvm.instructions.items[@intFromEnum(self)];
43474348 }
43484349
4349 fn llvmName(self: Instruction.Index, wip: *const WipFunction) [*:0]const u8 {
4350 fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 {
43504351 return if (wip.builder.strip)
43514352 ""
43524353 else
......@@ -4419,15 +4420,49 @@ pub const Function = struct {
44194420 };
44204421
44214422 pub const Load = struct {
4423 info: MemoryAccessInfo,
44224424 type: Type,
44234425 ptr: Value,
4424 info: MemoryAccessInfo,
44254426 };
44264427
44274428 pub const Store = struct {
4429 info: MemoryAccessInfo,
44284430 val: Value,
44294431 ptr: Value,
4432 };
4433
4434 pub const CmpXchg = struct {
44304435 info: MemoryAccessInfo,
4436 ptr: Value,
4437 cmp: Value,
4438 new: Value,
4439
4440 pub const Kind = enum { strong, weak };
4441 };
4442
4443 pub const AtomicRmw = struct {
4444 info: MemoryAccessInfo,
4445 ptr: Value,
4446 val: Value,
4447
4448 pub const Operation = enum(u5) {
4449 xchg,
4450 add,
4451 sub,
4452 @"and",
4453 nand,
4454 @"or",
4455 xor,
4456 max,
4457 min,
4458 umax,
4459 umin,
4460 fadd,
4461 fsub,
4462 fmax,
4463 fmin,
4464 none = std.math.maxInt(u5),
4465 };
44314466 };
44324467
44334468 pub const GetElementPtr = struct {
......@@ -5163,21 +5198,21 @@ pub const WipFunction = struct {
51635198
51645199 pub fn load(
51655200 self: *WipFunction,
5166 kind: MemoryAccessKind,
5201 access_kind: MemoryAccessKind,
51675202 ty: Type,
51685203 ptr: Value,
51695204 alignment: Alignment,
51705205 name: []const u8,
51715206 ) Allocator.Error!Value {
5172 return self.loadAtomic(kind, ty, ptr, .system, .none, alignment, name);
5207 return self.loadAtomic(access_kind, ty, ptr, .system, .none, alignment, name);
51735208 }
51745209
51755210 pub fn loadAtomic(
51765211 self: *WipFunction,
5177 kind: MemoryAccessKind,
5212 access_kind: MemoryAccessKind,
51785213 ty: Type,
51795214 ptr: Value,
5180 scope: SyncScope,
5215 sync_scope: SyncScope,
51815216 ordering: AtomicOrdering,
51825217 alignment: Alignment,
51835218 name: []const u8,
......@@ -5186,22 +5221,21 @@ pub const WipFunction = struct {
51865221 try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0);
51875222 const instruction = try self.addInst(name, .{
51885223 .tag = switch (ordering) {
5189 .none => switch (kind) {
5190 .normal => .load,
5191 .@"volatile" => .@"load volatile",
5192 },
5193 else => switch (kind) {
5194 .normal => .@"load atomic",
5195 .@"volatile" => .@"load atomic volatile",
5196 },
5224 .none => .load,
5225 else => .@"load atomic",
51975226 },
51985227 .data = self.addExtraAssumeCapacity(Instruction.Load{
5228 .info = .{
5229 .access_kind = access_kind,
5230 .sync_scope = switch (ordering) {
5231 .none => .system,
5232 else => sync_scope,
5233 },
5234 .success_ordering = ordering,
5235 .alignment = alignment,
5236 },
51995237 .type = ty,
52005238 .ptr = ptr,
5201 .info = .{ .scope = switch (ordering) {
5202 .none => .system,
5203 else => scope,
5204 }, .ordering = ordering, .alignment = alignment },
52055239 }),
52065240 });
52075241 if (self.builder.useLibLlvm()) {
......@@ -5210,6 +5244,7 @@ pub const WipFunction = struct {
52105244 ptr.toLlvm(self),
52115245 instruction.llvmName(self),
52125246 );
5247 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
52135248 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
52145249 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
52155250 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
......@@ -5229,10 +5264,10 @@ pub const WipFunction = struct {
52295264
52305265 pub fn storeAtomic(
52315266 self: *WipFunction,
5232 kind: MemoryAccessKind,
5267 access_kind: MemoryAccessKind,
52335268 val: Value,
52345269 ptr: Value,
5235 scope: SyncScope,
5270 sync_scope: SyncScope,
52365271 ordering: AtomicOrdering,
52375272 alignment: Alignment,
52385273 ) Allocator.Error!Instruction.Index {
......@@ -5240,30 +5275,26 @@ pub const WipFunction = struct {
52405275 try self.ensureUnusedExtraCapacity(1, Instruction.Store, 0);
52415276 const instruction = try self.addInst(null, .{
52425277 .tag = switch (ordering) {
5243 .none => switch (kind) {
5244 .normal => .store,
5245 .@"volatile" => .@"store volatile",
5246 },
5247 else => switch (kind) {
5248 .normal => .@"store atomic",
5249 .@"volatile" => .@"store atomic volatile",
5250 },
5278 .none => .store,
5279 else => .@"store atomic",
52515280 },
52525281 .data = self.addExtraAssumeCapacity(Instruction.Store{
5282 .info = .{
5283 .access_kind = access_kind,
5284 .sync_scope = switch (ordering) {
5285 .none => .system,
5286 else => sync_scope,
5287 },
5288 .success_ordering = ordering,
5289 .alignment = alignment,
5290 },
52535291 .val = val,
52545292 .ptr = ptr,
5255 .info = .{ .scope = switch (ordering) {
5256 .none => .system,
5257 else => scope,
5258 }, .ordering = ordering, .alignment = alignment },
52595293 }),
52605294 });
52615295 if (self.builder.useLibLlvm()) {
52625296 const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self));
5263 switch (kind) {
5264 .normal => {},
5265 .@"volatile" => llvm_instruction.setVolatile(.True),
5266 }
5297 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
52675298 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
52685299 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
52695300 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
......@@ -5273,7 +5304,7 @@ pub const WipFunction = struct {
52735304
52745305 pub fn fence(
52755306 self: *WipFunction,
5276 scope: SyncScope,
5307 sync_scope: SyncScope,
52775308 ordering: AtomicOrdering,
52785309 ) Allocator.Error!Instruction.Index {
52795310 assert(ordering != .none);
......@@ -5281,21 +5312,130 @@ pub const WipFunction = struct {
52815312 const instruction = try self.addInst(null, .{
52825313 .tag = .fence,
52835314 .data = @bitCast(MemoryAccessInfo{
5284 .scope = scope,
5285 .ordering = ordering,
5286 .alignment = undefined,
5315 .sync_scope = sync_scope,
5316 .success_ordering = ordering,
52875317 }),
52885318 });
52895319 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
52905320 self.llvm.builder.buildFence(
52915321 @enumFromInt(@intFromEnum(ordering)),
5292 llvm.Bool.fromBool(scope == .singlethread),
5322 llvm.Bool.fromBool(sync_scope == .singlethread),
52935323 "",
52945324 ),
52955325 );
52965326 return instruction;
52975327 }
52985328
5329 pub fn cmpxchg(
5330 self: *WipFunction,
5331 kind: Instruction.CmpXchg.Kind,
5332 access_kind: MemoryAccessKind,
5333 ptr: Value,
5334 cmp: Value,
5335 new: Value,
5336 sync_scope: SyncScope,
5337 success_ordering: AtomicOrdering,
5338 failure_ordering: AtomicOrdering,
5339 alignment: Alignment,
5340 name: []const u8,
5341 ) Allocator.Error!Value {
5342 assert(ptr.typeOfWip(self).isPointer(self.builder));
5343 const ty = cmp.typeOfWip(self);
5344 assert(ty == new.typeOfWip(self));
5345 assert(success_ordering != .none);
5346 assert(failure_ordering != .none);
5347
5348 _ = try self.builder.structType(.normal, &.{ ty, .i1 });
5349 try self.ensureUnusedExtraCapacity(1, Instruction.CmpXchg, 0);
5350 const instruction = try self.addInst(name, .{
5351 .tag = switch (kind) {
5352 .strong => .cmpxchg,
5353 .weak => .@"cmpxchg weak",
5354 },
5355 .data = self.addExtraAssumeCapacity(Instruction.CmpXchg{
5356 .info = .{
5357 .access_kind = access_kind,
5358 .sync_scope = sync_scope,
5359 .success_ordering = success_ordering,
5360 .failure_ordering = failure_ordering,
5361 .alignment = alignment,
5362 },
5363 .ptr = ptr,
5364 .cmp = cmp,
5365 .new = new,
5366 }),
5367 });
5368 if (self.builder.useLibLlvm()) {
5369 const llvm_instruction = self.llvm.builder.buildAtomicCmpXchg(
5370 ptr.toLlvm(self),
5371 cmp.toLlvm(self),
5372 new.toLlvm(self),
5373 @enumFromInt(@intFromEnum(success_ordering)),
5374 @enumFromInt(@intFromEnum(failure_ordering)),
5375 llvm.Bool.fromBool(sync_scope == .singlethread),
5376 );
5377 if (kind == .weak) llvm_instruction.setWeak(.True);
5378 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5379 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5380 const llvm_name = instruction.llvmName(self);
5381 if (llvm_name.len > 0) llvm_instruction.setValueName(
5382 llvm_name.ptr,
5383 @intCast(llvm_name.len),
5384 );
5385 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5386 }
5387 return instruction.toValue();
5388 }
5389
5390 pub fn atomicrmw(
5391 self: *WipFunction,
5392 access_kind: MemoryAccessKind,
5393 operation: Instruction.AtomicRmw.Operation,
5394 ptr: Value,
5395 val: Value,
5396 sync_scope: SyncScope,
5397 ordering: AtomicOrdering,
5398 alignment: Alignment,
5399 name: []const u8,
5400 ) Allocator.Error!Value {
5401 assert(ptr.typeOfWip(self).isPointer(self.builder));
5402 assert(ordering != .none);
5403
5404 try self.ensureUnusedExtraCapacity(1, Instruction.AtomicRmw, 0);
5405 const instruction = try self.addInst(name, .{
5406 .tag = .atomicrmw,
5407 .data = self.addExtraAssumeCapacity(Instruction.AtomicRmw{
5408 .info = .{
5409 .access_kind = access_kind,
5410 .atomic_rmw_operation = operation,
5411 .sync_scope = sync_scope,
5412 .success_ordering = ordering,
5413 .alignment = alignment,
5414 },
5415 .ptr = ptr,
5416 .val = val,
5417 }),
5418 });
5419 if (self.builder.useLibLlvm()) {
5420 const llvm_instruction = self.llvm.builder.buildAtomicRmw(
5421 @enumFromInt(@intFromEnum(operation)),
5422 ptr.toLlvm(self),
5423 val.toLlvm(self),
5424 @enumFromInt(@intFromEnum(ordering)),
5425 llvm.Bool.fromBool(sync_scope == .singlethread),
5426 );
5427 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5428 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5429 const llvm_name = instruction.llvmName(self);
5430 if (llvm_name.len > 0) llvm_instruction.setValueName(
5431 llvm_name.ptr,
5432 @intCast(llvm_name.len),
5433 );
5434 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5435 }
5436 return instruction.toValue();
5437 }
5438
52995439 pub fn gep(
53005440 self: *WipFunction,
53015441 kind: Instruction.GetElementPtr.Kind,
......@@ -5747,30 +5887,6 @@ pub const WipFunction = struct {
57475887 return instruction.toValue();
57485888 }
57495889
5750 pub const WipUnimplemented = struct {
5751 instruction: Instruction.Index,
5752
5753 pub fn finish(self: WipUnimplemented, val: *llvm.Value, wip: *WipFunction) Value {
5754 assert(wip.builder.useLibLlvm());
5755 wip.llvm.instructions.items[@intFromEnum(self.instruction)] = val;
5756 return self.instruction.toValue();
5757 }
5758 };
5759
5760 pub fn unimplemented(
5761 self: *WipFunction,
5762 ty: Type,
5763 name: []const u8,
5764 ) Allocator.Error!WipUnimplemented {
5765 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
5766 const instruction = try self.addInst(name, .{
5767 .tag = .unimplemented,
5768 .data = @intFromEnum(ty),
5769 });
5770 if (self.builder.useLibLlvm()) _ = self.llvm.instructions.addOneAssumeCapacity();
5771 return .{ .instruction = instruction };
5772 }
5773
57745890 pub fn finish(self: *WipFunction) Allocator.Error!void {
57755891 const gpa = self.builder.gpa;
57765892 const function = self.function.ptr(self.builder);
......@@ -6035,19 +6151,19 @@ pub const WipFunction = struct {
60356151 .arg,
60366152 .block,
60376153 => unreachable,
6154 .atomicrmw => {
6155 const extra = self.extraData(Instruction.AtomicRmw, instruction.data);
6156 instruction.data = wip_extra.addExtra(Instruction.AtomicRmw{
6157 .info = extra.info,
6158 .ptr = instructions.map(extra.ptr),
6159 .val = instructions.map(extra.val),
6160 });
6161 },
60386162 .br,
60396163 .fence,
60406164 .@"ret void",
6041 .unimplemented,
60426165 .@"unreachable",
60436166 => {},
6044 .extractelement => {
6045 const extra = self.extraData(Instruction.ExtractElement, instruction.data);
6046 instruction.data = wip_extra.addExtra(Instruction.ExtractElement{
6047 .val = instructions.map(extra.val),
6048 .index = instructions.map(extra.index),
6049 });
6050 },
60516167 .br_cond => {
60526168 const extra = self.extraData(Instruction.BrCond, instruction.data);
60536169 instruction.data = wip_extra.addExtra(Instruction.BrCond{
......@@ -6076,6 +6192,24 @@ pub const WipFunction = struct {
60766192 });
60776193 wip_extra.appendMappedValues(args, instructions);
60786194 },
6195 .cmpxchg,
6196 .@"cmpxchg weak",
6197 => {
6198 const extra = self.extraData(Instruction.CmpXchg, instruction.data);
6199 instruction.data = wip_extra.addExtra(Instruction.CmpXchg{
6200 .info = extra.info,
6201 .ptr = instructions.map(extra.ptr),
6202 .cmp = instructions.map(extra.cmp),
6203 .new = instructions.map(extra.new),
6204 });
6205 },
6206 .extractelement => {
6207 const extra = self.extraData(Instruction.ExtractElement, instruction.data);
6208 instruction.data = wip_extra.addExtra(Instruction.ExtractElement{
6209 .val = instructions.map(extra.val),
6210 .index = instructions.map(extra.index),
6211 });
6212 },
60796213 .extractvalue => {
60806214 var extra = self.extraDataTrail(Instruction.ExtractValue, instruction.data);
60816215 const indices = extra.trail.next(extra.data.indices_len, u32, self);
......@@ -6121,8 +6255,6 @@ pub const WipFunction = struct {
61216255 },
61226256 .load,
61236257 .@"load atomic",
6124 .@"load atomic volatile",
6125 .@"load volatile",
61266258 => {
61276259 const extra = self.extraData(Instruction.Load, instruction.data);
61286260 instruction.data = wip_extra.addExtra(Instruction.Load{
......@@ -6164,8 +6296,6 @@ pub const WipFunction = struct {
61646296 },
61656297 .store,
61666298 .@"store atomic",
6167 .@"store atomic volatile",
6168 .@"store volatile",
61696299 => {
61706300 const extra = self.extraData(Instruction.Store, instruction.data);
61716301 instruction.data = wip_extra.addExtra(Instruction.Store{
......@@ -6619,6 +6749,15 @@ pub const IntegerCondition = enum(u6) {
66196749pub const MemoryAccessKind = enum(u1) {
66206750 normal,
66216751 @"volatile",
6752
6753 pub fn format(
6754 self: MemoryAccessKind,
6755 comptime prefix: []const u8,
6756 _: std.fmt.FormatOptions,
6757 writer: anytype,
6758 ) @TypeOf(writer).Error!void {
6759 if (self != .normal) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
6760 }
66226761};
66236762
66246763pub const SyncScope = enum(u1) {
......@@ -6632,7 +6771,7 @@ pub const SyncScope = enum(u1) {
66326771 writer: anytype,
66336772 ) @TypeOf(writer).Error!void {
66346773 if (self != .system) try writer.print(
6635 \\{s} syncscope("{s}")
6774 \\{s}syncscope("{s}")
66366775 , .{ prefix, @tagName(self) });
66376776 }
66386777};
......@@ -6652,15 +6791,18 @@ pub const AtomicOrdering = enum(u3) {
66526791 _: std.fmt.FormatOptions,
66536792 writer: anytype,
66546793 ) @TypeOf(writer).Error!void {
6655 if (self != .none) try writer.print("{s} {s}", .{ prefix, @tagName(self) });
6794 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
66566795 }
66576796};
66586797
66596798const MemoryAccessInfo = packed struct(u32) {
6660 scope: SyncScope,
6661 ordering: AtomicOrdering,
6662 alignment: Alignment,
6663 _: u22 = undefined,
6799 access_kind: MemoryAccessKind = .normal,
6800 atomic_rmw_operation: Function.Instruction.AtomicRmw.Operation = .none,
6801 sync_scope: SyncScope,
6802 success_ordering: AtomicOrdering,
6803 failure_ordering: AtomicOrdering = .none,
6804 alignment: Alignment = .default,
6805 _: u13 = undefined,
66646806};
66656807
66666808pub const FastMath = packed struct(u32) {
......@@ -7542,7 +7684,7 @@ pub fn init(options: Options) InitError!Builder {
75427684 if (options.name.len > 0) self.source_filename = try self.string(options.name);
75437685 self.initializeLLVMTarget(options.target.cpu.arch);
75447686 if (self.useLibLlvm()) self.llvm.module = llvm.Module.createWithName(
7545 (self.source_filename.slice(&self) orelse "").ptr,
7687 (self.source_filename.slice(&self) orelse ""),
75467688 self.llvm.context,
75477689 );
75487690
......@@ -8983,6 +9125,21 @@ pub fn printUnbuffered(
89839125 });
89849126 },
89859127 .arg => unreachable,
9128 .atomicrmw => |tag| {
9129 const extra =
9130 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
9131 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{
9132 instruction_index.name(&function).fmt(self),
9133 @tagName(tag),
9134 extra.info.access_kind,
9135 @tagName(extra.info.atomic_rmw_operation),
9136 extra.ptr.fmt(function_index, self),
9137 extra.val.fmt(function_index, self),
9138 extra.info.sync_scope,
9139 extra.info.success_ordering,
9140 extra.info.alignment,
9141 });
9142 },
89869143 .block => {
89879144 block_incoming_len = instruction.data;
89889145 const name = instruction_index.name(&function);
......@@ -9056,6 +9213,24 @@ pub fn printUnbuffered(
90569213 });
90579214 try writer.writeByte('\n');
90589215 },
9216 .cmpxchg,
9217 .@"cmpxchg weak",
9218 => |tag| {
9219 const extra =
9220 function.extraData(Function.Instruction.CmpXchg, instruction.data);
9221 try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{
9222 instruction_index.name(&function).fmt(self),
9223 @tagName(tag),
9224 extra.info.access_kind,
9225 extra.ptr.fmt(function_index, self),
9226 extra.cmp.fmt(function_index, self),
9227 extra.new.fmt(function_index, self),
9228 extra.info.sync_scope,
9229 extra.info.success_ordering,
9230 extra.info.failure_ordering,
9231 extra.info.alignment,
9232 });
9233 },
90599234 .extractelement => |tag| {
90609235 const extra = function.extraData(
90619236 Function.Instruction.ExtractElement,
......@@ -9084,7 +9259,11 @@ pub fn printUnbuffered(
90849259 },
90859260 .fence => |tag| {
90869261 const info: MemoryAccessInfo = @bitCast(instruction.data);
9087 try writer.print(" {s}{}{}", .{ @tagName(tag), info.scope, info.ordering });
9262 try writer.print(" {s}{ }{ }", .{
9263 @tagName(tag),
9264 info.sync_scope,
9265 info.success_ordering,
9266 });
90889267 },
90899268 .fneg,
90909269 .@"fneg fast",
......@@ -9145,18 +9324,17 @@ pub fn printUnbuffered(
91459324 },
91469325 .load,
91479326 .@"load atomic",
9148 .@"load atomic volatile",
9149 .@"load volatile",
91509327 => |tag| {
91519328 const extra =
91529329 function.extraData(Function.Instruction.Load, instruction.data);
9153 try writer.print(" %{} = {s} {%}, {%}{}{}{, }\n", .{
9330 try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{
91549331 instruction_index.name(&function).fmt(self),
91559332 @tagName(tag),
9333 extra.info.access_kind,
91569334 extra.type.fmt(self),
91579335 extra.ptr.fmt(function_index, self),
9158 extra.info.scope,
9159 extra.info.ordering,
9336 extra.info.sync_scope,
9337 extra.info.success_ordering,
91609338 extra.info.alignment,
91619339 });
91629340 },
......@@ -9220,17 +9398,16 @@ pub fn printUnbuffered(
92209398 },
92219399 .store,
92229400 .@"store atomic",
9223 .@"store atomic volatile",
9224 .@"store volatile",
92259401 => |tag| {
92269402 const extra =
92279403 function.extraData(Function.Instruction.Store, instruction.data);
9228 try writer.print(" {s} {%}, {%}{}{}{, }\n", .{
9404 try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{
92299405 @tagName(tag),
9406 extra.info.access_kind,
92309407 extra.val.fmt(function_index, self),
92319408 extra.ptr.fmt(function_index, self),
9232 extra.info.scope,
9233 extra.info.ordering,
9409 extra.info.sync_scope,
9410 extra.info.success_ordering,
92349411 extra.info.alignment,
92359412 });
92369413 },
......@@ -9254,25 +9431,6 @@ pub fn printUnbuffered(
92549431 );
92559432 try writer.writeAll(" ]\n");
92569433 },
9257 .unimplemented => |tag| {
9258 const ty: Type = @enumFromInt(instruction.data);
9259 if (true) {
9260 try writer.writeAll(" ");
9261 switch (ty) {
9262 .none, .void => {},
9263 else => try writer.print("%{} = ", .{
9264 instruction_index.name(&function).fmt(self),
9265 }),
9266 }
9267 try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) });
9268 } else switch (ty) {
9269 .none, .void => {},
9270 else => try writer.print(" %{} = load {%}, ptr undef\n", .{
9271 instruction_index.name(&function).fmt(self),
9272 ty.fmt(self),
9273 }),
9274 }
9275 },
92769434 .va_arg => |tag| {
92779435 const extra =
92789436 function.extraData(Function.Instruction.VaArg, instruction.data);
src/codegen/llvm/bindings.zig+1-4
......@@ -330,10 +330,7 @@ pub const Value = opaque {
330330 pub const fnSetSubprogram = ZigLLVMFnSetSubprogram;
331331 extern fn ZigLLVMFnSetSubprogram(f: *Value, subprogram: *DISubprogram) void;
332332
333 pub const setValueName = LLVMSetValueName;
334 extern fn LLVMSetValueName(Val: *Value, Name: [*:0]const u8) void;
335
336 pub const setValueName2 = LLVMSetValueName2;
333 pub const setValueName = LLVMSetValueName2;
337334 extern fn LLVMSetValueName2(Val: *Value, Name: [*]const u8, NameLen: usize) void;
338335
339336 pub const getValueName = LLVMGetValueName;
src/zig_llvm.cpp+2-2
......@@ -1123,11 +1123,11 @@ void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) {
11231123}
11241124
11251125ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
1126 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
1126 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
11271127}
11281128
11291129void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
1130 unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression));
1130 unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression));
11311131}
11321132
11331133static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");