| ... | ... | @@ -2177,7 +2177,7 @@ pub const Global = struct { |
| 2177 | 2177 | if (!builder.useLibLlvm()) return; |
| 2178 | 2178 | const index = @intFromEnum(self.unwrap(builder)); |
| 2179 | 2179 | 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); |
| 2181 | 2181 | } |
| 2182 | 2182 | |
| 2183 | 2183 | fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void { |
| ... | ... | @@ -3759,12 +3759,15 @@ pub const Function = struct { |
| 3759 | 3759 | arg, |
| 3760 | 3760 | ashr, |
| 3761 | 3761 | @"ashr exact", |
| 3762 | atomicrmw, |
| 3762 | 3763 | bitcast, |
| 3763 | 3764 | block, |
| 3764 | 3765 | br, |
| 3765 | 3766 | br_cond, |
| 3766 | 3767 | call, |
| 3767 | 3768 | @"call fast", |
| 3769 | cmpxchg, |
| 3770 | @"cmpxchg weak", |
| 3768 | 3771 | extractelement, |
| 3769 | 3772 | extractvalue, |
| 3770 | 3773 | fadd, |
| ... | ... | @@ -3833,8 +3836,6 @@ pub const Function = struct { |
| 3833 | 3836 | inttoptr, |
| 3834 | 3837 | load, |
| 3835 | 3838 | @"load atomic", |
| 3836 | | @"load atomic volatile", |
| 3837 | | @"load volatile", |
| 3838 | 3839 | lshr, |
| 3839 | 3840 | @"lshr exact", |
| 3840 | 3841 | mul, |
| ... | ... | @@ -3865,8 +3866,6 @@ pub const Function = struct { |
| 3865 | 3866 | srem, |
| 3866 | 3867 | store, |
| 3867 | 3868 | @"store atomic", |
| 3868 | | @"store atomic volatile", |
| 3869 | | @"store volatile", |
| 3870 | 3869 | sub, |
| 3871 | 3870 | @"sub nsw", |
| 3872 | 3871 | @"sub nuw", |
| ... | ... | @@ -3879,7 +3878,6 @@ pub const Function = struct { |
| 3879 | 3878 | @"udiv exact", |
| 3880 | 3879 | urem, |
| 3881 | 3880 | uitofp, |
| 3882 | | unimplemented, |
| 3883 | 3881 | @"unreachable", |
| 3884 | 3882 | va_arg, |
| 3885 | 3883 | xor, |
| ... | ... | @@ -3920,8 +3918,6 @@ pub const Function = struct { |
| 3920 | 3918 | .@"ret void", |
| 3921 | 3919 | .store, |
| 3922 | 3920 | .@"store atomic", |
| 3923 | | .@"store atomic volatile", |
| 3924 | | .@"store volatile", |
| 3925 | 3921 | .@"switch", |
| 3926 | 3922 | .@"unreachable", |
| 3927 | 3923 | => false, |
| ... | ... | @@ -3933,7 +3929,6 @@ pub const Function = struct { |
| 3933 | 3929 | .@"notail call fast", |
| 3934 | 3930 | .@"tail call", |
| 3935 | 3931 | .@"tail call fast", |
| 3936 | | .unimplemented, |
| 3937 | 3932 | => self.typeOfWip(wip) != .void, |
| 3938 | 3933 | else => true, |
| 3939 | 3934 | }; |
| ... | ... | @@ -4003,6 +3998,7 @@ pub const Function = struct { |
| 4003 | 3998 | ), |
| 4004 | 3999 | .arg => wip.function.typeOf(wip.builder) |
| 4005 | 4000 | .functionParameters(wip.builder)[instruction.data], |
| 4001 | .atomicrmw => wip.extraData(AtomicRmw, instruction.data).val.typeOfWip(wip), |
| 4006 | 4002 | .block => .label, |
| 4007 | 4003 | .br, |
| 4008 | 4004 | .br_cond, |
| ... | ... | @@ -4011,8 +4007,6 @@ pub const Function = struct { |
| 4011 | 4007 | .@"ret void", |
| 4012 | 4008 | .store, |
| 4013 | 4009 | .@"store atomic", |
| 4014 | | .@"store atomic volatile", |
| 4015 | | .@"store volatile", |
| 4016 | 4010 | .@"switch", |
| 4017 | 4011 | .@"unreachable", |
| 4018 | 4012 | => .none, |
| ... | ... | @@ -4025,6 +4019,12 @@ pub const Function = struct { |
| 4025 | 4019 | .@"tail call", |
| 4026 | 4020 | .@"tail call fast", |
| 4027 | 4021 | => 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, |
| 4028 | 4028 | .extractelement => wip.extraData(ExtractElement, instruction.data) |
| 4029 | 4029 | .val.typeOfWip(wip).childType(wip.builder), |
| 4030 | 4030 | .extractvalue => { |
| ... | ... | @@ -4096,8 +4096,6 @@ pub const Function = struct { |
| 4096 | 4096 | .insertvalue => wip.extraData(InsertValue, instruction.data).val.typeOfWip(wip), |
| 4097 | 4097 | .load, |
| 4098 | 4098 | .@"load atomic", |
| 4099 | | .@"load atomic volatile", |
| 4100 | | .@"load volatile", |
| 4101 | 4099 | => wip.extraData(Load, instruction.data).type, |
| 4102 | 4100 | .phi, |
| 4103 | 4101 | .@"phi fast", |
| ... | ... | @@ -4112,7 +4110,6 @@ pub const Function = struct { |
| 4112 | 4110 | wip.builder, |
| 4113 | 4111 | ); |
| 4114 | 4112 | }, |
| 4115 | | .unimplemented => @enumFromInt(instruction.data), |
| 4116 | 4113 | .va_arg => wip.extraData(VaArg, instruction.data).type, |
| 4117 | 4114 | }; |
| 4118 | 4115 | } |
| ... | ... | @@ -4186,6 +4183,8 @@ pub const Function = struct { |
| 4186 | 4183 | ), |
| 4187 | 4184 | .arg => function.global.typeOf(builder) |
| 4188 | 4185 | .functionParameters(builder)[instruction.data], |
| 4186 | .atomicrmw => function.extraData(AtomicRmw, instruction.data) |
| 4187 | .val.typeOf(function_index, builder), |
| 4189 | 4188 | .block => .label, |
| 4190 | 4189 | .br, |
| 4191 | 4190 | .br_cond, |
| ... | ... | @@ -4194,8 +4193,6 @@ pub const Function = struct { |
| 4194 | 4193 | .@"ret void", |
| 4195 | 4194 | .store, |
| 4196 | 4195 | .@"store atomic", |
| 4197 | | .@"store atomic volatile", |
| 4198 | | .@"store volatile", |
| 4199 | 4196 | .@"switch", |
| 4200 | 4197 | .@"unreachable", |
| 4201 | 4198 | => .none, |
| ... | ... | @@ -4208,6 +4205,13 @@ pub const Function = struct { |
| 4208 | 4205 | .@"tail call", |
| 4209 | 4206 | .@"tail call fast", |
| 4210 | 4207 | => 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, |
| 4211 | 4215 | .extractelement => function.extraData(ExtractElement, instruction.data) |
| 4212 | 4216 | .val.typeOf(function_index, builder).childType(builder), |
| 4213 | 4217 | .extractvalue => { |
| ... | ... | @@ -4282,8 +4286,6 @@ pub const Function = struct { |
| 4282 | 4286 | .val.typeOf(function_index, builder), |
| 4283 | 4287 | .load, |
| 4284 | 4288 | .@"load atomic", |
| 4285 | | .@"load atomic volatile", |
| 4286 | | .@"load volatile", |
| 4287 | 4289 | => function.extraData(Load, instruction.data).type, |
| 4288 | 4290 | .phi, |
| 4289 | 4291 | .@"phi fast", |
| ... | ... | @@ -4298,7 +4300,6 @@ pub const Function = struct { |
| 4298 | 4300 | builder, |
| 4299 | 4301 | ); |
| 4300 | 4302 | }, |
| 4301 | | .unimplemented => @enumFromInt(instruction.data), |
| 4302 | 4303 | .va_arg => function.extraData(VaArg, instruction.data).type, |
| 4303 | 4304 | }; |
| 4304 | 4305 | } |
| ... | ... | @@ -4346,7 +4347,7 @@ pub const Function = struct { |
| 4346 | 4347 | return wip.llvm.instructions.items[@intFromEnum(self)]; |
| 4347 | 4348 | } |
| 4348 | 4349 | |
| 4349 | | fn llvmName(self: Instruction.Index, wip: *const WipFunction) [*:0]const u8 { |
| 4350 | fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 { |
| 4350 | 4351 | return if (wip.builder.strip) |
| 4351 | 4352 | "" |
| 4352 | 4353 | else |
| ... | ... | @@ -4419,15 +4420,49 @@ pub const Function = struct { |
| 4419 | 4420 | }; |
| 4420 | 4421 | |
| 4421 | 4422 | pub const Load = struct { |
| 4423 | info: MemoryAccessInfo, |
| 4422 | 4424 | type: Type, |
| 4423 | 4425 | ptr: Value, |
| 4424 | | info: MemoryAccessInfo, |
| 4425 | 4426 | }; |
| 4426 | 4427 | |
| 4427 | 4428 | pub const Store = struct { |
| 4429 | info: MemoryAccessInfo, |
| 4428 | 4430 | val: Value, |
| 4429 | 4431 | ptr: Value, |
| 4432 | }; |
| 4433 | |
| 4434 | pub const CmpXchg = struct { |
| 4430 | 4435 | 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 | }; |
| 4431 | 4466 | }; |
| 4432 | 4467 | |
| 4433 | 4468 | pub const GetElementPtr = struct { |
| ... | ... | @@ -5163,21 +5198,21 @@ pub const WipFunction = struct { |
| 5163 | 5198 | |
| 5164 | 5199 | pub fn load( |
| 5165 | 5200 | self: *WipFunction, |
| 5166 | | kind: MemoryAccessKind, |
| 5201 | access_kind: MemoryAccessKind, |
| 5167 | 5202 | ty: Type, |
| 5168 | 5203 | ptr: Value, |
| 5169 | 5204 | alignment: Alignment, |
| 5170 | 5205 | name: []const u8, |
| 5171 | 5206 | ) 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); |
| 5173 | 5208 | } |
| 5174 | 5209 | |
| 5175 | 5210 | pub fn loadAtomic( |
| 5176 | 5211 | self: *WipFunction, |
| 5177 | | kind: MemoryAccessKind, |
| 5212 | access_kind: MemoryAccessKind, |
| 5178 | 5213 | ty: Type, |
| 5179 | 5214 | ptr: Value, |
| 5180 | | scope: SyncScope, |
| 5215 | sync_scope: SyncScope, |
| 5181 | 5216 | ordering: AtomicOrdering, |
| 5182 | 5217 | alignment: Alignment, |
| 5183 | 5218 | name: []const u8, |
| ... | ... | @@ -5186,22 +5221,21 @@ pub const WipFunction = struct { |
| 5186 | 5221 | try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0); |
| 5187 | 5222 | const instruction = try self.addInst(name, .{ |
| 5188 | 5223 | .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", |
| 5197 | 5226 | }, |
| 5198 | 5227 | .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 | }, |
| 5199 | 5237 | .type = ty, |
| 5200 | 5238 | .ptr = ptr, |
| 5201 | | .info = .{ .scope = switch (ordering) { |
| 5202 | | .none => .system, |
| 5203 | | else => scope, |
| 5204 | | }, .ordering = ordering, .alignment = alignment }, |
| 5205 | 5239 | }), |
| 5206 | 5240 | }); |
| 5207 | 5241 | if (self.builder.useLibLlvm()) { |
| ... | ... | @@ -5210,6 +5244,7 @@ pub const WipFunction = struct { |
| 5210 | 5244 | ptr.toLlvm(self), |
| 5211 | 5245 | instruction.llvmName(self), |
| 5212 | 5246 | ); |
| 5247 | if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True); |
| 5213 | 5248 | if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering))); |
| 5214 | 5249 | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); |
| 5215 | 5250 | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| ... | ... | @@ -5229,10 +5264,10 @@ pub const WipFunction = struct { |
| 5229 | 5264 | |
| 5230 | 5265 | pub fn storeAtomic( |
| 5231 | 5266 | self: *WipFunction, |
| 5232 | | kind: MemoryAccessKind, |
| 5267 | access_kind: MemoryAccessKind, |
| 5233 | 5268 | val: Value, |
| 5234 | 5269 | ptr: Value, |
| 5235 | | scope: SyncScope, |
| 5270 | sync_scope: SyncScope, |
| 5236 | 5271 | ordering: AtomicOrdering, |
| 5237 | 5272 | alignment: Alignment, |
| 5238 | 5273 | ) Allocator.Error!Instruction.Index { |
| ... | ... | @@ -5240,30 +5275,26 @@ pub const WipFunction = struct { |
| 5240 | 5275 | try self.ensureUnusedExtraCapacity(1, Instruction.Store, 0); |
| 5241 | 5276 | const instruction = try self.addInst(null, .{ |
| 5242 | 5277 | .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", |
| 5251 | 5280 | }, |
| 5252 | 5281 | .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 | }, |
| 5253 | 5291 | .val = val, |
| 5254 | 5292 | .ptr = ptr, |
| 5255 | | .info = .{ .scope = switch (ordering) { |
| 5256 | | .none => .system, |
| 5257 | | else => scope, |
| 5258 | | }, .ordering = ordering, .alignment = alignment }, |
| 5259 | 5293 | }), |
| 5260 | 5294 | }); |
| 5261 | 5295 | if (self.builder.useLibLlvm()) { |
| 5262 | 5296 | 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); |
| 5267 | 5298 | if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering))); |
| 5268 | 5299 | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); |
| 5269 | 5300 | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| ... | ... | @@ -5273,7 +5304,7 @@ pub const WipFunction = struct { |
| 5273 | 5304 | |
| 5274 | 5305 | pub fn fence( |
| 5275 | 5306 | self: *WipFunction, |
| 5276 | | scope: SyncScope, |
| 5307 | sync_scope: SyncScope, |
| 5277 | 5308 | ordering: AtomicOrdering, |
| 5278 | 5309 | ) Allocator.Error!Instruction.Index { |
| 5279 | 5310 | assert(ordering != .none); |
| ... | ... | @@ -5281,21 +5312,130 @@ pub const WipFunction = struct { |
| 5281 | 5312 | const instruction = try self.addInst(null, .{ |
| 5282 | 5313 | .tag = .fence, |
| 5283 | 5314 | .data = @bitCast(MemoryAccessInfo{ |
| 5284 | | .scope = scope, |
| 5285 | | .ordering = ordering, |
| 5286 | | .alignment = undefined, |
| 5315 | .sync_scope = sync_scope, |
| 5316 | .success_ordering = ordering, |
| 5287 | 5317 | }), |
| 5288 | 5318 | }); |
| 5289 | 5319 | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 5290 | 5320 | self.llvm.builder.buildFence( |
| 5291 | 5321 | @enumFromInt(@intFromEnum(ordering)), |
| 5292 | | llvm.Bool.fromBool(scope == .singlethread), |
| 5322 | llvm.Bool.fromBool(sync_scope == .singlethread), |
| 5293 | 5323 | "", |
| 5294 | 5324 | ), |
| 5295 | 5325 | ); |
| 5296 | 5326 | return instruction; |
| 5297 | 5327 | } |
| 5298 | 5328 | |
| 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 | |
| 5299 | 5439 | pub fn gep( |
| 5300 | 5440 | self: *WipFunction, |
| 5301 | 5441 | kind: Instruction.GetElementPtr.Kind, |
| ... | ... | @@ -5747,30 +5887,6 @@ pub const WipFunction = struct { |
| 5747 | 5887 | return instruction.toValue(); |
| 5748 | 5888 | } |
| 5749 | 5889 | |
| 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 | | |
| 5774 | 5890 | pub fn finish(self: *WipFunction) Allocator.Error!void { |
| 5775 | 5891 | const gpa = self.builder.gpa; |
| 5776 | 5892 | const function = self.function.ptr(self.builder); |
| ... | ... | @@ -6035,19 +6151,19 @@ pub const WipFunction = struct { |
| 6035 | 6151 | .arg, |
| 6036 | 6152 | .block, |
| 6037 | 6153 | => 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 | }, |
| 6038 | 6162 | .br, |
| 6039 | 6163 | .fence, |
| 6040 | 6164 | .@"ret void", |
| 6041 | | .unimplemented, |
| 6042 | 6165 | .@"unreachable", |
| 6043 | 6166 | => {}, |
| 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 | | }, |
| 6051 | 6167 | .br_cond => { |
| 6052 | 6168 | const extra = self.extraData(Instruction.BrCond, instruction.data); |
| 6053 | 6169 | instruction.data = wip_extra.addExtra(Instruction.BrCond{ |
| ... | ... | @@ -6076,6 +6192,24 @@ pub const WipFunction = struct { |
| 6076 | 6192 | }); |
| 6077 | 6193 | wip_extra.appendMappedValues(args, instructions); |
| 6078 | 6194 | }, |
| 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 | }, |
| 6079 | 6213 | .extractvalue => { |
| 6080 | 6214 | var extra = self.extraDataTrail(Instruction.ExtractValue, instruction.data); |
| 6081 | 6215 | const indices = extra.trail.next(extra.data.indices_len, u32, self); |
| ... | ... | @@ -6121,8 +6255,6 @@ pub const WipFunction = struct { |
| 6121 | 6255 | }, |
| 6122 | 6256 | .load, |
| 6123 | 6257 | .@"load atomic", |
| 6124 | | .@"load atomic volatile", |
| 6125 | | .@"load volatile", |
| 6126 | 6258 | => { |
| 6127 | 6259 | const extra = self.extraData(Instruction.Load, instruction.data); |
| 6128 | 6260 | instruction.data = wip_extra.addExtra(Instruction.Load{ |
| ... | ... | @@ -6164,8 +6296,6 @@ pub const WipFunction = struct { |
| 6164 | 6296 | }, |
| 6165 | 6297 | .store, |
| 6166 | 6298 | .@"store atomic", |
| 6167 | | .@"store atomic volatile", |
| 6168 | | .@"store volatile", |
| 6169 | 6299 | => { |
| 6170 | 6300 | const extra = self.extraData(Instruction.Store, instruction.data); |
| 6171 | 6301 | instruction.data = wip_extra.addExtra(Instruction.Store{ |
| ... | ... | @@ -6619,6 +6749,15 @@ pub const IntegerCondition = enum(u6) { |
| 6619 | 6749 | pub const MemoryAccessKind = enum(u1) { |
| 6620 | 6750 | normal, |
| 6621 | 6751 | @"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 | } |
| 6622 | 6761 | }; |
| 6623 | 6762 | |
| 6624 | 6763 | pub const SyncScope = enum(u1) { |
| ... | ... | @@ -6632,7 +6771,7 @@ pub const SyncScope = enum(u1) { |
| 6632 | 6771 | writer: anytype, |
| 6633 | 6772 | ) @TypeOf(writer).Error!void { |
| 6634 | 6773 | if (self != .system) try writer.print( |
| 6635 | | \\{s} syncscope("{s}") |
| 6774 | \\{s}syncscope("{s}") |
| 6636 | 6775 | , .{ prefix, @tagName(self) }); |
| 6637 | 6776 | } |
| 6638 | 6777 | }; |
| ... | ... | @@ -6652,15 +6791,18 @@ pub const AtomicOrdering = enum(u3) { |
| 6652 | 6791 | _: std.fmt.FormatOptions, |
| 6653 | 6792 | writer: anytype, |
| 6654 | 6793 | ) @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) }); |
| 6656 | 6795 | } |
| 6657 | 6796 | }; |
| 6658 | 6797 | |
| 6659 | 6798 | const 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, |
| 6664 | 6806 | }; |
| 6665 | 6807 | |
| 6666 | 6808 | pub const FastMath = packed struct(u32) { |
| ... | ... | @@ -7542,7 +7684,7 @@ pub fn init(options: Options) InitError!Builder { |
| 7542 | 7684 | if (options.name.len > 0) self.source_filename = try self.string(options.name); |
| 7543 | 7685 | self.initializeLLVMTarget(options.target.cpu.arch); |
| 7544 | 7686 | if (self.useLibLlvm()) self.llvm.module = llvm.Module.createWithName( |
| 7545 | | (self.source_filename.slice(&self) orelse "").ptr, |
| 7687 | (self.source_filename.slice(&self) orelse ""), |
| 7546 | 7688 | self.llvm.context, |
| 7547 | 7689 | ); |
| 7548 | 7690 | |
| ... | ... | @@ -8983,6 +9125,21 @@ pub fn printUnbuffered( |
| 8983 | 9125 | }); |
| 8984 | 9126 | }, |
| 8985 | 9127 | .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 | }, |
| 8986 | 9143 | .block => { |
| 8987 | 9144 | block_incoming_len = instruction.data; |
| 8988 | 9145 | const name = instruction_index.name(&function); |
| ... | ... | @@ -9056,6 +9213,24 @@ pub fn printUnbuffered( |
| 9056 | 9213 | }); |
| 9057 | 9214 | try writer.writeByte('\n'); |
| 9058 | 9215 | }, |
| 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 | }, |
| 9059 | 9234 | .extractelement => |tag| { |
| 9060 | 9235 | const extra = function.extraData( |
| 9061 | 9236 | Function.Instruction.ExtractElement, |
| ... | ... | @@ -9084,7 +9259,11 @@ pub fn printUnbuffered( |
| 9084 | 9259 | }, |
| 9085 | 9260 | .fence => |tag| { |
| 9086 | 9261 | 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 | }); |
| 9088 | 9267 | }, |
| 9089 | 9268 | .fneg, |
| 9090 | 9269 | .@"fneg fast", |
| ... | ... | @@ -9145,18 +9324,17 @@ pub fn printUnbuffered( |
| 9145 | 9324 | }, |
| 9146 | 9325 | .load, |
| 9147 | 9326 | .@"load atomic", |
| 9148 | | .@"load atomic volatile", |
| 9149 | | .@"load volatile", |
| 9150 | 9327 | => |tag| { |
| 9151 | 9328 | const extra = |
| 9152 | 9329 | function.extraData(Function.Instruction.Load, instruction.data); |
| 9153 | | try writer.print(" %{} = {s} {%}, {%}{}{}{, }\n", .{ |
| 9330 | try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{ |
| 9154 | 9331 | instruction_index.name(&function).fmt(self), |
| 9155 | 9332 | @tagName(tag), |
| 9333 | extra.info.access_kind, |
| 9156 | 9334 | extra.type.fmt(self), |
| 9157 | 9335 | extra.ptr.fmt(function_index, self), |
| 9158 | | extra.info.scope, |
| 9159 | | extra.info.ordering, |
| 9336 | extra.info.sync_scope, |
| 9337 | extra.info.success_ordering, |
| 9160 | 9338 | extra.info.alignment, |
| 9161 | 9339 | }); |
| 9162 | 9340 | }, |
| ... | ... | @@ -9220,17 +9398,16 @@ pub fn printUnbuffered( |
| 9220 | 9398 | }, |
| 9221 | 9399 | .store, |
| 9222 | 9400 | .@"store atomic", |
| 9223 | | .@"store atomic volatile", |
| 9224 | | .@"store volatile", |
| 9225 | 9401 | => |tag| { |
| 9226 | 9402 | const extra = |
| 9227 | 9403 | function.extraData(Function.Instruction.Store, instruction.data); |
| 9228 | | try writer.print(" {s} {%}, {%}{}{}{, }\n", .{ |
| 9404 | try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{ |
| 9229 | 9405 | @tagName(tag), |
| 9406 | extra.info.access_kind, |
| 9230 | 9407 | extra.val.fmt(function_index, self), |
| 9231 | 9408 | extra.ptr.fmt(function_index, self), |
| 9232 | | extra.info.scope, |
| 9233 | | extra.info.ordering, |
| 9409 | extra.info.sync_scope, |
| 9410 | extra.info.success_ordering, |
| 9234 | 9411 | extra.info.alignment, |
| 9235 | 9412 | }); |
| 9236 | 9413 | }, |
| ... | ... | @@ -9254,25 +9431,6 @@ pub fn printUnbuffered( |
| 9254 | 9431 | ); |
| 9255 | 9432 | try writer.writeAll(" ]\n"); |
| 9256 | 9433 | }, |
| 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 | | }, |
| 9276 | 9434 | .va_arg => |tag| { |
| 9277 | 9435 | const extra = |
| 9278 | 9436 | function.extraData(Function.Instruction.VaArg, instruction.data); |