authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-09 03:16:55-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-08-09 03:16:55-04:00
logcd7998096b624b326dddcbb2752fe4bcdac8df9f
tree3a67b92da2378f614bc52bf23133bcf22b5a5c4b
parentd34201c8491007c5a24b4175a5170a5b6cc3d55e
parent3e1dd93bb2ac7e9d99fb340f1f4ca6868a52cb6b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #16708 from jacobly0/llvm-builder

llvm: convert more things to use Builder * finish converting intrinsics * finish converting attributes * finish converting instructions * finish converting globals * pass behavior tests with no dependence on the llvm api (`-fno-libllvm`)

6 files changed, 4018 insertions(+), 3498 deletions(-)

src/codegen/llvm.zig+927-1583
......@@ -764,7 +764,6 @@ pub const Object = struct {
764764 builder: Builder,
765765
766766 module: *Module,
767 llvm_module: *llvm.Module,
768767 di_builder: ?*llvm.DIBuilder,
769768 /// One of these mappings:
770769 /// - *Module.File => *DIFile
......@@ -824,7 +823,7 @@ pub const Object = struct {
824823 var builder = try Builder.init(.{
825824 .allocator = gpa,
826825 .use_lib_llvm = options.use_lib_llvm,
827 .strip = options.strip,
826 .strip = options.strip or !options.use_lib_llvm, // TODO
828827 .name = options.root_name,
829828 .target = options.target,
830829 .triple = llvm_target_triple,
......@@ -945,9 +944,8 @@ pub const Object = struct {
945944 .gpa = gpa,
946945 .builder = builder,
947946 .module = options.module.?,
948 .llvm_module = builder.llvm.module.?,
949947 .di_map = .{},
950 .di_builder = builder.llvm.di_builder,
948 .di_builder = if (builder.useLibLlvm()) builder.llvm.di_builder else null, // TODO
951949 .di_compile_unit = builder.llvm.di_compile_unit,
952950 .target_machine = target_machine,
953951 .target_data = target_data,
......@@ -963,14 +961,17 @@ pub const Object = struct {
963961 }
964962
965963 pub fn deinit(self: *Object, gpa: Allocator) void {
966 self.di_map.deinit(gpa);
967 self.di_type_map.deinit(gpa);
968 self.target_data.dispose();
969 self.target_machine.dispose();
964 if (self.builder.useLibLlvm()) {
965 self.di_map.deinit(gpa);
966 self.di_type_map.deinit(gpa);
967 self.target_data.dispose();
968 self.target_machine.dispose();
969 }
970970 self.decl_map.deinit(gpa);
971971 self.named_enum_map.deinit(gpa);
972972 self.type_map.deinit(gpa);
973973 self.extern_collisions.deinit(gpa);
974 self.builder.deinit();
974975 self.* = undefined;
975976 }
976977
......@@ -991,9 +992,8 @@ pub const Object = struct {
991992 }
992993
993994 fn genErrorNameTable(o: *Object) Allocator.Error!void {
994 // If o.error_name_table is null, there was no instruction that actually referenced the error table.
995 const error_name_table_ptr_global = o.error_name_table;
996 if (error_name_table_ptr_global == .none) return;
995 // If o.error_name_table is null, then it was not referenced by any instructions.
996 if (o.error_name_table == .none) return;
997997
998998 const mod = o.module;
999999
......@@ -1003,72 +1003,42 @@ pub const Object = struct {
10031003
10041004 // TODO: Address space
10051005 const slice_ty = Type.slice_const_u8_sentinel_0;
1006 const slice_alignment = slice_ty.abiAlignment(mod);
10071006 const llvm_usize_ty = try o.lowerType(Type.usize);
10081007 const llvm_slice_ty = try o.lowerType(slice_ty);
10091008 const llvm_table_ty = try o.builder.arrayType(error_name_list.len, llvm_slice_ty);
10101009
10111010 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
1012 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name_nts| {
1013 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_nts));
1014 const str_init = try o.builder.stringNullConst(name);
1015 const str_ty = str_init.typeOf(&o.builder);
1016 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");
1017 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));
1018 str_llvm_global.setLinkage(.Private);
1019 str_llvm_global.setGlobalConstant(.True);
1020 str_llvm_global.setUnnamedAddr(.True);
1021 str_llvm_global.setAlignment(1);
1022
1023 var str_global = Builder.Global{
1024 .linkage = .private,
1025 .unnamed_addr = .unnamed_addr,
1026 .type = str_ty,
1027 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
1028 };
1029 var str_variable = Builder.Variable{
1030 .global = @enumFromInt(o.builder.globals.count()),
1031 .mutability = .constant,
1032 .init = str_init,
1033 .alignment = comptime Builder.Alignment.fromByteUnits(1),
1034 };
1035 try o.builder.llvm.globals.append(o.gpa, str_llvm_global);
1036 const global_index = try o.builder.addGlobal(.empty, str_global);
1037 try o.builder.variables.append(o.gpa, str_variable);
1011 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {
1012 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
1013 const name_init = try o.builder.stringNullConst(name_string);
1014 const name_variable_index =
1015 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
1016 try name_variable_index.setInitializer(name_init, &o.builder);
1017 name_variable_index.setLinkage(.private, &o.builder);
1018 name_variable_index.setMutability(.constant, &o.builder);
1019 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
1020 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
10381021
10391022 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
1040 global_index.toConst(),
1041 try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len),
1023 name_variable_index.toConst(&o.builder),
1024 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len),
10421025 });
10431026 }
10441027
1045 const error_name_table_init = try o.builder.arrayConst(llvm_table_ty, llvm_errors);
1046 const error_name_table_global = o.llvm_module.addGlobal(llvm_table_ty.toLlvm(&o.builder), "");
1047 error_name_table_global.setInitializer(error_name_table_init.toLlvm(&o.builder));
1048 error_name_table_global.setLinkage(.Private);
1049 error_name_table_global.setGlobalConstant(.True);
1050 error_name_table_global.setUnnamedAddr(.True);
1051 error_name_table_global.setAlignment(slice_alignment); // TODO: Dont hardcode
1052
1053 var global = Builder.Global{
1054 .linkage = .private,
1055 .unnamed_addr = .unnamed_addr,
1056 .type = llvm_table_ty,
1057 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
1058 };
1059 var variable = Builder.Variable{
1060 .global = @enumFromInt(o.builder.globals.count()),
1061 .mutability = .constant,
1062 .init = error_name_table_init,
1063 .alignment = Builder.Alignment.fromByteUnits(slice_alignment),
1064 };
1065 try o.builder.llvm.globals.append(o.gpa, error_name_table_global);
1066 _ = try o.builder.addGlobal(.empty, global);
1067 try o.builder.variables.append(o.gpa, variable);
1028 const table_variable_index = try o.builder.addVariable(.empty, llvm_table_ty, .default);
1029 try table_variable_index.setInitializer(
1030 try o.builder.arrayConst(llvm_table_ty, llvm_errors),
1031 &o.builder,
1032 );
1033 table_variable_index.setLinkage(.private, &o.builder);
1034 table_variable_index.setMutability(.constant, &o.builder);
1035 table_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
1036 table_variable_index.setAlignment(
1037 Builder.Alignment.fromByteUnits(slice_ty.abiAlignment(mod)),
1038 &o.builder,
1039 );
10681040
1069 const error_name_table_ptr = error_name_table_global;
1070 error_name_table_ptr_global.ptr(&o.builder).init = variable.global.toConst();
1071 error_name_table_ptr_global.toLlvm(&o.builder).setInitializer(error_name_table_ptr);
1041 try o.error_name_table.setInitializer(table_variable_index.toConst(&o.builder), &o.builder);
10721042 }
10731043
10741044 fn genCmpLtErrorsLenFunction(o: *Object) !void {
......@@ -1112,7 +1082,8 @@ pub const Object = struct {
11121082 // Same logic as below but for externs instead of exports.
11131083 const decl_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue;
11141084 const other_global = object.builder.getGlobal(decl_name) orelse continue;
1115 if (other_global.eql(global, &object.builder)) continue;
1085 if (other_global.toConst().getBase(&object.builder) ==
1086 global.toConst().getBase(&object.builder)) continue;
11161087
11171088 try global.replace(other_global, &object.builder);
11181089 }
......@@ -1120,13 +1091,14 @@ pub const Object = struct {
11201091
11211092 for (mod.decl_exports.keys(), mod.decl_exports.values()) |decl_index, export_list| {
11221093 const global = object.decl_map.get(decl_index) orelse continue;
1094 const global_base = global.toConst().getBase(&object.builder);
11231095 for (export_list.items) |exp| {
11241096 // Detect if the LLVM global has already been created as an extern. In such
11251097 // case, we need to replace all uses of it with this exported global.
11261098 const exp_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue;
11271099
11281100 const other_global = object.builder.getGlobal(exp_name) orelse continue;
1129 if (other_global.eql(global, &object.builder)) continue;
1101 if (other_global.toConst().getBase(&object.builder) == global_base) continue;
11301102
11311103 try global.takeName(other_global, &object.builder);
11321104 try other_global.replace(global, &object.builder);
......@@ -1181,17 +1153,7 @@ pub const Object = struct {
11811153 }
11821154 }
11831155
1184 if (comp.verbose_llvm_bc) |path| {
1185 const path_z = try comp.gpa.dupeZ(u8, path);
1186 defer comp.gpa.free(path_z);
1187
1188 const error_code = self.llvm_module.writeBitcodeToFile(path_z);
1189 if (error_code != 0) {
1190 log.err("dump LLVM module failed bc={s}: {d}", .{
1191 path, error_code,
1192 });
1193 }
1194 }
1156 if (comp.verbose_llvm_bc) |path| _ = try self.builder.writeBitcodeToFile(path);
11951157
11961158 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
11971159 defer arena_allocator.deinit();
......@@ -1200,20 +1162,10 @@ pub const Object = struct {
12001162 const mod = comp.bin_file.options.module.?;
12011163 const cache_dir = mod.zig_cache_artifact_directory;
12021164
1203 if (std.debug.runtime_safety) {
1204 var error_message: [*:0]const u8 = undefined;
1205 // verifyModule always allocs the error_message even if there is no error
1206 defer llvm.disposeMessage(error_message);
1207
1208 if (self.llvm_module.verify(.ReturnStatus, &error_message).toBool()) {
1209 std.debug.print("\n{s}\n", .{error_message});
1210
1211 if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| {
1212 _ = self.llvm_module.printModuleToFile(emit_llvm_ir_path, &error_message);
1213 }
1214
1215 @panic("LLVM module verification failed");
1216 }
1165 if (std.debug.runtime_safety and !try self.builder.verify()) {
1166 if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path|
1167 _ = self.builder.printToFileZ(emit_llvm_ir_path);
1168 @panic("LLVM module verification failed");
12171169 }
12181170
12191171 var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|
......@@ -1233,12 +1185,20 @@ pub const Object = struct {
12331185 emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,
12341186 });
12351187
1188 if (emit_asm_path == null and emit_bin_path == null and
1189 emit_llvm_ir_path == null and emit_llvm_bc_path == null) return;
1190
1191 if (!self.builder.useLibLlvm()) {
1192 log.err("emitting without libllvm not implemented", .{});
1193 return error.FailedToEmit;
1194 }
1195
12361196 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
12371197 // So we call the entire pipeline multiple times if this is requested.
12381198 var error_message: [*:0]const u8 = undefined;
12391199 if (emit_asm_path != null and emit_bin_path != null) {
12401200 if (self.target_machine.emitToFile(
1241 self.llvm_module,
1201 self.builder.llvm.module.?,
12421202 &error_message,
12431203 comp.bin_file.options.optimize_mode == .Debug,
12441204 comp.bin_file.options.optimize_mode == .ReleaseSmall,
......@@ -1262,7 +1222,7 @@ pub const Object = struct {
12621222 }
12631223
12641224 if (self.target_machine.emitToFile(
1265 self.llvm_module,
1225 self.builder.llvm.module.?,
12661226 &error_message,
12671227 comp.bin_file.options.optimize_mode == .Debug,
12681228 comp.bin_file.options.optimize_mode == .ReleaseSmall,
......@@ -1305,37 +1265,28 @@ pub const Object = struct {
13051265 .err_msg = null,
13061266 };
13071267
1308 const function = try o.resolveLlvmFunction(decl_index);
1309 const global = function.ptrConst(&o.builder).global;
1310 const llvm_func = global.toLlvm(&o.builder);
1268 const function_index = try o.resolveLlvmFunction(decl_index);
13111269
1312 var attributes = try function.ptrConst(&o.builder).attributes.toWip(&o.builder);
1270 var attributes = try function_index.ptrConst(&o.builder).attributes.toWip(&o.builder);
13131271 defer attributes.deinit(&o.builder);
13141272
13151273 if (func.analysis(ip).is_noinline) {
13161274 try attributes.addFnAttr(.@"noinline", &o.builder);
1317 o.addFnAttr(llvm_func, "noinline");
13181275 } else {
13191276 _ = try attributes.removeFnAttr(.@"noinline");
1320 Object.removeFnAttr(llvm_func, "noinline");
13211277 }
13221278
13231279 if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {
13241280 try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder);
13251281 try attributes.addFnAttr(.@"noinline", &o.builder);
1326 o.addFnAttrInt(llvm_func, "alignstack", alignment);
1327 o.addFnAttr(llvm_func, "noinline");
13281282 } else {
13291283 _ = try attributes.removeFnAttr(.alignstack);
1330 Object.removeFnAttr(llvm_func, "alignstack");
13311284 }
13321285
13331286 if (func.analysis(ip).is_cold) {
13341287 try attributes.addFnAttr(.cold, &o.builder);
1335 o.addFnAttr(llvm_func, "cold");
13361288 } else {
13371289 _ = try attributes.removeFnAttr(.cold);
1338 Object.removeFnAttr(llvm_func, "cold");
13391290 }
13401291
13411292 // TODO: disable this if safety is off for the function scope
......@@ -1346,10 +1297,6 @@ pub const Object = struct {
13461297 .kind = try o.builder.string("stack-protector-buffer-size"),
13471298 .value = try o.builder.fmt("{d}", .{ssp_buf_size}),
13481299 } }, &o.builder);
1349 var buf: [12]u8 = undefined;
1350 const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable;
1351 o.addFnAttr(llvm_func, "sspstrong");
1352 o.addFnAttrString(llvm_func, "stack-protector-buffer-size", arg);
13531300 }
13541301
13551302 // TODO: disable this if safety is off for the function scope
......@@ -1358,26 +1305,21 @@ pub const Object = struct {
13581305 .kind = try o.builder.string("probe-stack"),
13591306 .value = try o.builder.string("__zig_probe_stack"),
13601307 } }, &o.builder);
1361 o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack");
13621308 } else if (target.os.tag == .uefi) {
13631309 try attributes.addFnAttr(.{ .string = .{
13641310 .kind = try o.builder.string("no-stack-arg-probe"),
13651311 .value = .empty,
13661312 } }, &o.builder);
1367 o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
13681313 }
13691314
1370 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| {
1371 function.ptr(&o.builder).section = try o.builder.string(section);
1372 llvm_func.setSection(section);
1373 }
1315 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
1316 function_index.setSection(try o.builder.string(section), &o.builder);
13741317
13751318 var deinit_wip = true;
1376 var wip = try Builder.WipFunction.init(&o.builder, function);
1319 var wip = try Builder.WipFunction.init(&o.builder, function_index);
13771320 defer if (deinit_wip) wip.deinit();
13781321 wip.cursor = .{ .block = try wip.block(0, "Entry") };
13791322
1380 const builder = wip.llvm.builder;
13811323 var llvm_arg_i: u32 = 0;
13821324
13831325 // This gets the LLVM values from the function and stores them in `dg.args`.
......@@ -1389,14 +1331,8 @@ pub const Object = struct {
13891331 } else .none;
13901332
13911333 if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) {
1392 .signed => {
1393 try attributes.addRetAttr(.signext, &o.builder);
1394 o.addAttr(llvm_func, 0, "signext");
1395 },
1396 .unsigned => {
1397 try attributes.addRetAttr(.zeroext, &o.builder);
1398 o.addAttr(llvm_func, 0, "zeroext");
1399 },
1334 .signed => try attributes.addRetAttr(.signext, &o.builder),
1335 .unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
14001336 };
14011337
14021338 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
......@@ -1437,7 +1373,7 @@ pub const Object = struct {
14371373 } else {
14381374 args.appendAssumeCapacity(param);
14391375
1440 try o.addByValParamAttrsOld(&attributes, llvm_func, param_ty, param_index, fn_info, llvm_arg_i);
1376 try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, llvm_arg_i);
14411377 }
14421378 llvm_arg_i += 1;
14431379 },
......@@ -1447,7 +1383,7 @@ pub const Object = struct {
14471383 const param = wip.arg(llvm_arg_i);
14481384 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
14491385
1450 try o.addByRefParamAttrsOld(&attributes, llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty);
1386 try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty);
14511387 llvm_arg_i += 1;
14521388
14531389 if (isByRef(param_ty, mod)) {
......@@ -1463,7 +1399,6 @@ pub const Object = struct {
14631399 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
14641400
14651401 try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);
1466 o.addArgAttr(llvm_func, llvm_arg_i, "noundef");
14671402 llvm_arg_i += 1;
14681403
14691404 if (isByRef(param_ty, mod)) {
......@@ -1479,11 +1414,7 @@ pub const Object = struct {
14791414 llvm_arg_i += 1;
14801415
14811416 const param_llvm_ty = try o.lowerType(param_ty);
1482 const int_llvm_ty = try o.builder.intType(@intCast(param_ty.abiSize(mod) * 8));
1483 const alignment = Builder.Alignment.fromByteUnits(@max(
1484 param_ty.abiAlignment(mod),
1485 o.target_data.abiAlignmentOfType(int_llvm_ty.toLlvm(&o.builder)),
1486 ));
1417 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
14871418 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
14881419 _ = try wip.store(.normal, param, arg_ptr, alignment);
14891420
......@@ -1500,23 +1431,19 @@ pub const Object = struct {
15001431 if (math.cast(u5, it.zig_index - 1)) |i| {
15011432 if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
15021433 try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
1503 o.addArgAttr(llvm_func, llvm_arg_i, "noalias");
15041434 }
15051435 }
15061436 if (param_ty.zigTypeTag(mod) != .Optional) {
15071437 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
1508 o.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
15091438 }
15101439 if (ptr_info.flags.is_const) {
15111440 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
1512 o.addArgAttr(llvm_func, llvm_arg_i, "readonly");
15131441 }
15141442 const elem_align = Builder.Alignment.fromByteUnits(
15151443 ptr_info.flags.alignment.toByteUnitsOptional() orelse
15161444 @max(ptr_info.child.toType().abiAlignment(mod), 1),
15171445 );
15181446 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder);
1519 o.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0);
15201447 const ptr_param = wip.arg(llvm_arg_i);
15211448 llvm_arg_i += 1;
15221449 const len_param = wip.arg(llvm_arg_i);
......@@ -1590,7 +1517,7 @@ pub const Object = struct {
15901517 }
15911518 }
15921519
1593 function.ptr(&o.builder).attributes = try attributes.finish(&o.builder);
1520 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
15941521
15951522 var di_file: ?*llvm.DIFile = null;
15961523 var di_scope: ?*llvm.DIScope = null;
......@@ -1609,7 +1536,7 @@ pub const Object = struct {
16091536 const subprogram = dib.createFunction(
16101537 di_file.?.toScope(),
16111538 ip.stringToSlice(decl.name),
1612 llvm_func.getValueName(),
1539 function_index.name(&o.builder).slice(&o.builder).?,
16131540 di_file.?,
16141541 line_number,
16151542 decl_di_ty,
......@@ -1622,7 +1549,7 @@ pub const Object = struct {
16221549 );
16231550 try o.di_map.put(gpa, decl, subprogram.toNode());
16241551
1625 llvm_func.fnSetSubprogram(subprogram);
1552 function_index.toLlvm(&o.builder).fnSetSubprogram(subprogram);
16261553
16271554 di_scope = subprogram.toScope();
16281555 }
......@@ -1633,7 +1560,6 @@ pub const Object = struct {
16331560 .liveness = liveness,
16341561 .dg = &dg,
16351562 .wip = wip,
1636 .builder = builder,
16371563 .ret_ptr = ret_ptr,
16381564 .args = args.items,
16391565 .arg_index = 0,
......@@ -1694,8 +1620,7 @@ pub const Object = struct {
16941620 const gpa = mod.gpa;
16951621 // If the module does not already have the function, we ignore this function call
16961622 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
1697 const global = self.decl_map.get(decl_index) orelse return;
1698 const llvm_global = global.toLlvm(&self.builder);
1623 const global_index = self.decl_map.get(decl_index) orelse return;
16991624 const decl = mod.declPtr(decl_index);
17001625 if (decl.isExtern(mod)) {
17011626 const decl_name = decl_name: {
......@@ -1713,114 +1638,91 @@ pub const Object = struct {
17131638 };
17141639
17151640 if (self.builder.getGlobal(decl_name)) |other_global| {
1716 if (other_global.toLlvm(&self.builder) != llvm_global) {
1641 if (other_global != global_index) {
17171642 try self.extern_collisions.put(gpa, decl_index, {});
17181643 }
17191644 }
17201645
1721 try global.rename(decl_name, &self.builder);
1722 global.ptr(&self.builder).unnamed_addr = .default;
1723 llvm_global.setUnnamedAddr(.False);
1724 global.ptr(&self.builder).linkage = .external;
1725 llvm_global.setLinkage(.External);
1726 if (mod.wantDllExports()) {
1727 global.ptr(&self.builder).dll_storage_class = .default;
1728 llvm_global.setDLLStorageClass(.Default);
1729 }
1646 try global_index.rename(decl_name, &self.builder);
1647 global_index.setLinkage(.external, &self.builder);
1648 global_index.setUnnamedAddr(.default, &self.builder);
1649 if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder);
17301650 if (self.di_map.get(decl)) |di_node| {
17311651 const decl_name_slice = decl_name.slice(&self.builder).?;
17321652 if (try decl.isFunction(mod)) {
17331653 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
1734 const linkage_name = llvm.MDString.get(self.builder.llvm.context, decl_name_slice.ptr, decl_name_slice.len);
1654 const linkage_name = llvm.MDString.get(
1655 self.builder.llvm.context,
1656 decl_name_slice.ptr,
1657 decl_name_slice.len,
1658 );
17351659 di_func.replaceLinkageName(linkage_name);
17361660 } else {
17371661 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
1738 const linkage_name = llvm.MDString.get(self.builder.llvm.context, decl_name_slice.ptr, decl_name_slice.len);
1662 const linkage_name = llvm.MDString.get(
1663 self.builder.llvm.context,
1664 decl_name_slice.ptr,
1665 decl_name_slice.len,
1666 );
17391667 di_global.replaceLinkageName(linkage_name);
17401668 }
17411669 }
17421670 if (decl.val.getVariable(mod)) |decl_var| {
1743 if (decl_var.is_threadlocal) {
1744 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1745 .generaldynamic;
1746 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1747 } else {
1748 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1749 .default;
1750 llvm_global.setThreadLocalMode(.NotThreadLocal);
1751 }
1752 if (decl_var.is_weak_linkage) {
1753 global.ptr(&self.builder).linkage = .extern_weak;
1754 llvm_global.setLinkage(.ExternalWeak);
1755 }
1671 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1672 if (decl_var.is_threadlocal) .generaldynamic else .default,
1673 &self.builder,
1674 );
1675 if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder);
17561676 }
1757 global.ptr(&self.builder).updateAttributes();
17581677 } else if (exports.len != 0) {
1759 const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exports[0].opts.name));
1760 try global.rename(exp_name, &self.builder);
1761 global.ptr(&self.builder).unnamed_addr = .default;
1762 llvm_global.setUnnamedAddr(.False);
1763 if (mod.wantDllExports()) {
1764 global.ptr(&self.builder).dll_storage_class = .dllexport;
1765 llvm_global.setDLLStorageClass(.DLLExport);
1766 }
1678 const main_exp_name = try self.builder.string(
1679 mod.intern_pool.stringToSlice(exports[0].opts.name),
1680 );
1681 try global_index.rename(main_exp_name, &self.builder);
1682 global_index.setUnnamedAddr(.default, &self.builder);
1683 if (mod.wantDllExports()) global_index.setDllStorageClass(.dllexport, &self.builder);
17671684 if (self.di_map.get(decl)) |di_node| {
1768 const exp_name_slice = exp_name.slice(&self.builder).?;
1685 const main_exp_name_slice = main_exp_name.slice(&self.builder).?;
17691686 if (try decl.isFunction(mod)) {
17701687 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
1771 const linkage_name = llvm.MDString.get(self.builder.llvm.context, exp_name_slice.ptr, exp_name_slice.len);
1688 const linkage_name = llvm.MDString.get(
1689 self.builder.llvm.context,
1690 main_exp_name_slice.ptr,
1691 main_exp_name_slice.len,
1692 );
17721693 di_func.replaceLinkageName(linkage_name);
17731694 } else {
17741695 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
1775 const linkage_name = llvm.MDString.get(self.builder.llvm.context, exp_name_slice.ptr, exp_name_slice.len);
1696 const linkage_name = llvm.MDString.get(
1697 self.builder.llvm.context,
1698 main_exp_name_slice.ptr,
1699 main_exp_name_slice.len,
1700 );
17761701 di_global.replaceLinkageName(linkage_name);
17771702 }
17781703 }
1779 switch (exports[0].opts.linkage) {
1704 global_index.setLinkage(switch (exports[0].opts.linkage) {
17801705 .Internal => unreachable,
1781 .Strong => {
1782 global.ptr(&self.builder).linkage = .external;
1783 llvm_global.setLinkage(.External);
1784 },
1785 .Weak => {
1786 global.ptr(&self.builder).linkage = .weak_odr;
1787 llvm_global.setLinkage(.WeakODR);
1788 },
1789 .LinkOnce => {
1790 global.ptr(&self.builder).linkage = .linkonce_odr;
1791 llvm_global.setLinkage(.LinkOnceODR);
1792 },
1793 }
1794 switch (exports[0].opts.visibility) {
1795 .default => {
1796 global.ptr(&self.builder).visibility = .default;
1797 llvm_global.setVisibility(.Default);
1798 },
1799 .hidden => {
1800 global.ptr(&self.builder).visibility = .hidden;
1801 llvm_global.setVisibility(.Hidden);
1802 },
1803 .protected => {
1804 global.ptr(&self.builder).visibility = .protected;
1805 llvm_global.setVisibility(.Protected);
1806 },
1807 }
1808 if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section| {
1809 switch (global.ptrConst(&self.builder).kind) {
1810 inline .variable, .function => |impl_index| impl_index.ptr(&self.builder).section =
1706 .Strong => .external,
1707 .Weak => .weak_odr,
1708 .LinkOnce => .linkonce_odr,
1709 }, &self.builder);
1710 global_index.setVisibility(switch (exports[0].opts.visibility) {
1711 .default => .default,
1712 .hidden => .hidden,
1713 .protected => .protected,
1714 }, &self.builder);
1715 if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section|
1716 switch (global_index.ptrConst(&self.builder).kind) {
1717 inline .variable, .function => |impl_index| impl_index.setSection(
18111718 try self.builder.string(section),
1812 else => unreachable,
1813 }
1814 llvm_global.setSection(section);
1815 }
1816 if (decl.val.getVariable(mod)) |decl_var| {
1817 if (decl_var.is_threadlocal) {
1818 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1819 .generaldynamic;
1820 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1821 }
1822 }
1823 global.ptr(&self.builder).updateAttributes();
1719 &self.builder,
1720 ),
1721 .alias, .replaced => unreachable,
1722 };
1723 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
1724 global_index.ptrConst(&self.builder).kind
1725 .variable.setThreadLocal(.generaldynamic, &self.builder);
18241726
18251727 // If a Decl is exported more than one time (which is rare),
18261728 // we add aliases for all but the first export.
......@@ -1829,49 +1731,48 @@ pub const Object = struct {
18291731 // Until then we iterate over existing aliases and make them point
18301732 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.
18311733 for (exports[1..]) |exp| {
1832 const exp_name_z = mod.intern_pool.stringToSlice(exp.opts.name);
1833
1834 if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| {
1835 alias.setAliasee(llvm_global);
1836 } else {
1837 _ = self.llvm_module.addAlias(
1838 global.ptrConst(&self.builder).type.toLlvm(&self.builder),
1839 0,
1840 llvm_global,
1841 exp_name_z,
1842 );
1734 const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exp.opts.name));
1735 if (self.builder.getGlobal(exp_name)) |global| {
1736 switch (global.ptrConst(&self.builder).kind) {
1737 .alias => |alias| {
1738 alias.setAliasee(global_index.toConst(), &self.builder);
1739 continue;
1740 },
1741 .variable, .function => {},
1742 .replaced => unreachable,
1743 }
18431744 }
1745 const alias_index = try self.builder.addAlias(
1746 .empty,
1747 global_index.typeOf(&self.builder),
1748 .default,
1749 global_index.toConst(),
1750 );
1751 try alias_index.rename(exp_name, &self.builder);
18441752 }
18451753 } else {
1846 const fqn = try self.builder.string(mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)));
1847 try global.rename(fqn, &self.builder);
1848 global.ptr(&self.builder).linkage = .internal;
1849 llvm_global.setLinkage(.Internal);
1850 if (mod.wantDllExports()) {
1851 global.ptr(&self.builder).dll_storage_class = .default;
1852 llvm_global.setDLLStorageClass(.Default);
1853 }
1854 global.ptr(&self.builder).unnamed_addr = .unnamed_addr;
1855 llvm_global.setUnnamedAddr(.True);
1754 const fqn = try self.builder.string(
1755 mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)),
1756 );
1757 try global_index.rename(fqn, &self.builder);
1758 global_index.setLinkage(.internal, &self.builder);
1759 if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder);
1760 global_index.setUnnamedAddr(.unnamed_addr, &self.builder);
18561761 if (decl.val.getVariable(mod)) |decl_var| {
1857 const single_threaded = mod.comp.bin_file.options.single_threaded;
1858 if (decl_var.is_threadlocal and !single_threaded) {
1859 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1860 .generaldynamic;
1861 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1862 } else {
1863 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1864 .default;
1865 llvm_global.setThreadLocalMode(.NotThreadLocal);
1866 }
1762 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1763 if (decl_var.is_threadlocal and !mod.comp.bin_file.options.single_threaded)
1764 .generaldynamic
1765 else
1766 .default,
1767 &self.builder,
1768 );
18671769 }
1868 global.ptr(&self.builder).updateAttributes();
18691770 }
18701771 }
18711772
18721773 pub fn freeDecl(self: *Object, decl_index: Module.Decl.Index) void {
18731774 const global = self.decl_map.get(decl_index) orelse return;
1874 global.toLlvm(&self.builder).deleteGlobal();
1775 global.delete(&self.builder);
18751776 }
18761777
18771778 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {
......@@ -2907,8 +2808,12 @@ pub const Object = struct {
29072808 /// If the llvm function does not exist, create it.
29082809 /// Note that this can be called before the function's semantic analysis has
29092810 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.
2910 fn resolveLlvmFunction(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Function.Index {
2811 fn resolveLlvmFunction(
2812 o: *Object,
2813 decl_index: Module.Decl.Index,
2814 ) Allocator.Error!Builder.Function.Index {
29112815 const mod = o.module;
2816 const ip = &mod.intern_pool;
29122817 const gpa = o.gpa;
29132818 const decl = mod.declPtr(decl_index);
29142819 const zig_fn_type = decl.ty;
......@@ -2920,46 +2825,31 @@ pub const Object = struct {
29202825 const target = mod.getTarget();
29212826 const sret = firstParamSRet(fn_info, mod);
29222827
2923 const fn_type = try o.lowerType(zig_fn_type);
2924
2925 const ip = &mod.intern_pool;
2926 const fqn = try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod)));
2927
2928 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
2929 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(fqn.slice(&o.builder).?, fn_type.toLlvm(&o.builder), @intFromEnum(llvm_addrspace));
2930
2931 var global = Builder.Global{
2932 .type = fn_type,
2933 .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
2934 };
2935 var function = Builder.Function{
2936 .global = @enumFromInt(o.builder.globals.count()),
2937 };
2828 const function_index = try o.builder.addFunction(
2829 try o.lowerType(zig_fn_type),
2830 try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))),
2831 toLlvmAddressSpace(decl.@"addrspace", target),
2832 );
2833 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
29382834
29392835 var attributes: Builder.FunctionAttributes.Wip = .{};
29402836 defer attributes.deinit(&o.builder);
29412837
29422838 const is_extern = decl.isExtern(mod);
29432839 if (!is_extern) {
2944 global.linkage = .internal;
2945 llvm_fn.setLinkage(.Internal);
2946 global.unnamed_addr = .unnamed_addr;
2947 llvm_fn.setUnnamedAddr(.True);
2840 function_index.setLinkage(.internal, &o.builder);
2841 function_index.setUnnamedAddr(.unnamed_addr, &o.builder);
29482842 } else {
29492843 if (target.isWasm()) {
29502844 try attributes.addFnAttr(.{ .string = .{
29512845 .kind = try o.builder.string("wasm-import-name"),
29522846 .value = try o.builder.string(ip.stringToSlice(decl.name)),
29532847 } }, &o.builder);
2954 o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
29552848 if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
2956 if (!std.mem.eql(u8, lib_name, "c")) {
2957 try attributes.addFnAttr(.{ .string = .{
2958 .kind = try o.builder.string("wasm-import-module"),
2959 .value = try o.builder.string(lib_name),
2960 } }, &o.builder);
2961 o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
2962 }
2849 if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{
2850 .kind = try o.builder.string("wasm-import-module"),
2851 .value = try o.builder.string(lib_name),
2852 } }, &o.builder);
29632853 }
29642854 }
29652855 }
......@@ -2969,12 +2859,9 @@ pub const Object = struct {
29692859 // Sret pointers must not be address 0
29702860 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
29712861 try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
2972 o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); // Sret pointers must not be address 0
2973 o.addArgAttr(llvm_fn, llvm_arg_i, "noalias");
29742862
29752863 const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType());
29762864 try attributes.addParamAttr(llvm_arg_i, .{ .sret = raw_llvm_ret_ty }, &o.builder);
2977 llvm_fn.addSretAttr(raw_llvm_ret_ty.toLlvm(&o.builder));
29782865
29792866 llvm_arg_i += 1;
29802867 }
......@@ -2984,42 +2871,26 @@ pub const Object = struct {
29842871
29852872 if (err_return_tracing) {
29862873 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
2987 o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
29882874 llvm_arg_i += 1;
29892875 }
29902876
29912877 switch (fn_info.cc) {
2992 .Unspecified, .Inline => {
2993 function.call_conv = .fastcc;
2994 llvm_fn.setFunctionCallConv(.Fast);
2995 },
2996 .Naked => {
2997 try attributes.addFnAttr(.naked, &o.builder);
2998 o.addFnAttr(llvm_fn, "naked");
2999 },
2878 .Unspecified, .Inline => function_index.setCallConv(.fastcc, &o.builder),
2879 .Naked => try attributes.addFnAttr(.naked, &o.builder),
30002880 .Async => {
3001 function.call_conv = .fastcc;
3002 llvm_fn.setFunctionCallConv(.Fast);
2881 function_index.setCallConv(.fastcc, &o.builder);
30032882 @panic("TODO: LLVM backend lower async function");
30042883 },
3005 else => {
3006 function.call_conv = toLlvmCallConv(fn_info.cc, target);
3007 llvm_fn.setFunctionCallConv(@enumFromInt(@intFromEnum(function.call_conv)));
3008 },
2884 else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),
30092885 }
30102886
3011 if (fn_info.alignment.toByteUnitsOptional()) |a| {
3012 function.alignment = Builder.Alignment.fromByteUnits(a);
3013 llvm_fn.setAlignment(@intCast(a));
3014 }
2887 if (fn_info.alignment.toByteUnitsOptional()) |alignment|
2888 function_index.setAlignment(Builder.Alignment.fromByteUnits(alignment), &o.builder);
30152889
30162890 // Function attributes that are independent of analysis results of the function body.
3017 try o.addCommonFnAttributes(&attributes, llvm_fn);
2891 try o.addCommonFnAttributes(&attributes);
30182892
3019 if (fn_info.return_type == .noreturn_type) {
3020 try attributes.addFnAttr(.noreturn, &o.builder);
3021 o.addFnAttr(llvm_fn, "noreturn");
3022 }
2893 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
30232894
30242895 // Add parameter attributes. We handle only the case of extern functions (no body)
30252896 // because functions with bodies are handled in `updateFunc`.
......@@ -3031,7 +2902,7 @@ pub const Object = struct {
30312902 const param_index = it.zig_index - 1;
30322903 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
30332904 if (!isByRef(param_ty, mod)) {
3034 try o.addByValParamAttrsOld(&attributes, llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
2905 try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
30352906 }
30362907 },
30372908 .byref => {
......@@ -3039,12 +2910,9 @@ pub const Object = struct {
30392910 const param_llvm_ty = try o.lowerType(param_ty.toType());
30402911 const alignment =
30412912 Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod));
3042 try o.addByRefParamAttrsOld(&attributes, llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
3043 },
3044 .byref_mut => {
3045 try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder);
3046 o.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef");
2913 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
30472914 },
2915 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
30482916 // No attributes needed for these.
30492917 .no_bits,
30502918 .abi_sized_int,
......@@ -3060,43 +2928,33 @@ pub const Object = struct {
30602928 };
30612929 }
30622930
3063 function.attributes = try attributes.finish(&o.builder);
3064
3065 try o.builder.llvm.globals.append(o.gpa, llvm_fn);
3066 gop.value_ptr.* = try o.builder.addGlobal(fqn, global);
3067 try o.builder.functions.append(o.gpa, function);
3068 return global.kind.function;
2931 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
2932 return function_index;
30692933 }
30702934
30712935 fn addCommonFnAttributes(
30722936 o: *Object,
30732937 attributes: *Builder.FunctionAttributes.Wip,
3074 llvm_fn: *llvm.Value,
30752938 ) Allocator.Error!void {
30762939 const comp = o.module.comp;
30772940
30782941 if (!comp.bin_file.options.red_zone) {
30792942 try attributes.addFnAttr(.noredzone, &o.builder);
3080 o.addFnAttr(llvm_fn, "noredzone");
30812943 }
30822944 if (comp.bin_file.options.omit_frame_pointer) {
30832945 try attributes.addFnAttr(.{ .string = .{
30842946 .kind = try o.builder.string("frame-pointer"),
30852947 .value = try o.builder.string("none"),
30862948 } }, &o.builder);
3087 o.addFnAttrString(llvm_fn, "frame-pointer", "none");
30882949 } else {
30892950 try attributes.addFnAttr(.{ .string = .{
30902951 .kind = try o.builder.string("frame-pointer"),
30912952 .value = try o.builder.string("all"),
30922953 } }, &o.builder);
3093 o.addFnAttrString(llvm_fn, "frame-pointer", "all");
30942954 }
30952955 try attributes.addFnAttr(.nounwind, &o.builder);
3096 o.addFnAttr(llvm_fn, "nounwind");
30972956 if (comp.unwind_tables) {
30982957 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
3099 o.addFnAttrInt(llvm_fn, "uwtable", 2);
31002958 }
31012959 if (comp.bin_file.options.skip_linker_dependencies or
31022960 comp.bin_file.options.no_builtin)
......@@ -3107,111 +2965,78 @@ pub const Object = struct {
31072965 // body of memcpy with a call to memcpy, which would then cause a stack
31082966 // overflow instead of performing memcpy.
31092967 try attributes.addFnAttr(.nobuiltin, &o.builder);
3110 o.addFnAttr(llvm_fn, "nobuiltin");
31112968 }
31122969 if (comp.bin_file.options.optimize_mode == .ReleaseSmall) {
31132970 try attributes.addFnAttr(.minsize, &o.builder);
31142971 try attributes.addFnAttr(.optsize, &o.builder);
3115 o.addFnAttr(llvm_fn, "minsize");
3116 o.addFnAttr(llvm_fn, "optsize");
31172972 }
31182973 if (comp.bin_file.options.tsan) {
31192974 try attributes.addFnAttr(.sanitize_thread, &o.builder);
3120 o.addFnAttr(llvm_fn, "sanitize_thread");
31212975 }
31222976 if (comp.getTarget().cpu.model.llvm_name) |s| {
31232977 try attributes.addFnAttr(.{ .string = .{
31242978 .kind = try o.builder.string("target-cpu"),
31252979 .value = try o.builder.string(s),
31262980 } }, &o.builder);
3127 llvm_fn.addFunctionAttr("target-cpu", s);
31282981 }
31292982 if (comp.bin_file.options.llvm_cpu_features) |s| {
31302983 try attributes.addFnAttr(.{ .string = .{
31312984 .kind = try o.builder.string("target-features"),
31322985 .value = try o.builder.string(std.mem.span(s)),
31332986 } }, &o.builder);
3134 llvm_fn.addFunctionAttr("target-features", s);
31352987 }
31362988 if (comp.getTarget().cpu.arch.isBpf()) {
31372989 try attributes.addFnAttr(.{ .string = .{
31382990 .kind = try o.builder.string("no-builtins"),
31392991 .value = .empty,
31402992 } }, &o.builder);
3141 llvm_fn.addFunctionAttr("no-builtins", "");
31422993 }
31432994 }
31442995
3145 fn resolveGlobalDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Variable.Index {
2996 fn resolveGlobalDecl(
2997 o: *Object,
2998 decl_index: Module.Decl.Index,
2999 ) Allocator.Error!Builder.Variable.Index {
31463000 const gop = try o.decl_map.getOrPut(o.gpa, decl_index);
31473001 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;
31483002 errdefer assert(o.decl_map.remove(decl_index));
31493003
31503004 const mod = o.module;
31513005 const decl = mod.declPtr(decl_index);
3152 const fqn = try o.builder.string(mod.intern_pool.stringToSlice(
3153 try decl.getFullyQualifiedName(mod),
3154 ));
3155
3156 const target = mod.getTarget();
3157
3158 var global = Builder.Global{
3159 .addr_space = toLlvmGlobalAddressSpace(decl.@"addrspace", target),
3160 .type = try o.lowerType(decl.ty),
3161 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
3162 };
3163 var variable = Builder.Variable{
3164 .global = @enumFromInt(o.builder.globals.count()),
3165 };
3166
31673006 const is_extern = decl.isExtern(mod);
3168 const name = if (is_extern)
3169 try o.builder.string(mod.intern_pool.stringToSlice(decl.name))
3170 else
3171 fqn;
3172 const llvm_global = o.llvm_module.addGlobalInAddressSpace(
3173 global.type.toLlvm(&o.builder),
3174 fqn.slice(&o.builder).?,
3175 @intFromEnum(global.addr_space),
3007
3008 const variable_index = try o.builder.addVariable(
3009 try o.builder.string(mod.intern_pool.stringToSlice(
3010 if (is_extern) decl.name else try decl.getFullyQualifiedName(mod),
3011 )),
3012 try o.lowerType(decl.ty),
3013 toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()),
31763014 );
3015 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
31773016
31783017 // This is needed for declarations created by `@extern`.
31793018 if (is_extern) {
3180 global.unnamed_addr = .default;
3181 llvm_global.setUnnamedAddr(.False);
3182 global.linkage = .external;
3183 llvm_global.setLinkage(.External);
3019 variable_index.setLinkage(.external, &o.builder);
3020 variable_index.setUnnamedAddr(.default, &o.builder);
31843021 if (decl.val.getVariable(mod)) |decl_var| {
31853022 const single_threaded = mod.comp.bin_file.options.single_threaded;
3186 if (decl_var.is_threadlocal and !single_threaded) {
3187 variable.thread_local = .generaldynamic;
3188 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
3189 } else {
3190 variable.thread_local = .default;
3191 llvm_global.setThreadLocalMode(.NotThreadLocal);
3192 }
3193 if (decl_var.is_weak_linkage) {
3194 global.linkage = .extern_weak;
3195 llvm_global.setLinkage(.ExternalWeak);
3196 }
3023 variable_index.setThreadLocal(
3024 if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default,
3025 &o.builder,
3026 );
3027 if (decl_var.is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder);
31973028 }
31983029 } else {
3199 global.linkage = .internal;
3200 llvm_global.setLinkage(.Internal);
3201 global.unnamed_addr = .unnamed_addr;
3202 llvm_global.setUnnamedAddr(.True);
3030 variable_index.setLinkage(.internal, &o.builder);
3031 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
32033032 }
3204
3205 try o.builder.llvm.globals.append(o.gpa, llvm_global);
3206 gop.value_ptr.* = try o.builder.addGlobal(name, global);
3207 try o.builder.variables.append(o.gpa, variable);
3208 return global.kind.variable;
3033 return variable_index;
32093034 }
32103035
32113036 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
32123037 const ty = try o.lowerTypeInner(t);
32133038 const mod = o.module;
3214 if (std.debug.runtime_safety and false) check: {
3039 if (std.debug.runtime_safety and o.builder.useLibLlvm() and false) check: {
32153040 const llvm_ty = ty.toLlvm(&o.builder);
32163041 if (t.zigTypeTag(mod) == .Opaque) break :check;
32173042 if (!t.hasRuntimeBits(mod)) break :check;
......@@ -4483,69 +4308,6 @@ pub const Object = struct {
44834308 return o.builder.castConst(.inttoptr, try o.builder.intConst(llvm_usize, int), llvm_ptr_ty);
44844309 }
44854310
4486 fn addAttr(o: *Object, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void {
4487 return o.addAttrInt(val, index, name, 0);
4488 }
4489
4490 fn addArgAttr(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8) void {
4491 return o.addAttr(fn_val, param_index + 1, attr_name);
4492 }
4493
4494 fn addArgAttrInt(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8, int: u64) void {
4495 return o.addAttrInt(fn_val, param_index + 1, attr_name, int);
4496 }
4497
4498 fn removeAttr(val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void {
4499 const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len);
4500 assert(kind_id != 0);
4501 val.removeEnumAttributeAtIndex(index, kind_id);
4502 }
4503
4504 fn addAttrInt(
4505 o: *Object,
4506 val: *llvm.Value,
4507 index: llvm.AttributeIndex,
4508 name: []const u8,
4509 int: u64,
4510 ) void {
4511 const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len);
4512 assert(kind_id != 0);
4513 const llvm_attr = o.builder.llvm.context.createEnumAttribute(kind_id, int);
4514 val.addAttributeAtIndex(index, llvm_attr);
4515 }
4516
4517 fn addAttrString(
4518 o: *Object,
4519 val: *llvm.Value,
4520 index: llvm.AttributeIndex,
4521 name: []const u8,
4522 value: []const u8,
4523 ) void {
4524 const llvm_attr = o.builder.llvm.context.createStringAttribute(
4525 name.ptr,
4526 @intCast(name.len),
4527 value.ptr,
4528 @intCast(value.len),
4529 );
4530 val.addAttributeAtIndex(index, llvm_attr);
4531 }
4532
4533 fn addFnAttr(o: *Object, val: *llvm.Value, name: []const u8) void {
4534 o.addAttr(val, std.math.maxInt(llvm.AttributeIndex), name);
4535 }
4536
4537 fn addFnAttrString(o: *Object, val: *llvm.Value, name: []const u8, value: []const u8) void {
4538 o.addAttrString(val, std.math.maxInt(llvm.AttributeIndex), name, value);
4539 }
4540
4541 fn removeFnAttr(fn_val: *llvm.Value, name: []const u8) void {
4542 removeAttr(fn_val, std.math.maxInt(llvm.AttributeIndex), name);
4543 }
4544
4545 fn addFnAttrInt(o: *Object, fn_val: *llvm.Value, name: []const u8, int: u64) void {
4546 return o.addAttrInt(fn_val, std.math.maxInt(llvm.AttributeIndex), name, int);
4547 }
4548
45494311 /// If the operand type of an atomic operation is not byte sized we need to
45504312 /// widen it before using it and then truncate the result.
45514313 /// RMW exchange of floating-point values is bitcasted to same-sized integer
......@@ -4608,80 +4370,13 @@ pub const Object = struct {
46084370 attributes: *Builder.FunctionAttributes.Wip,
46094371 llvm_arg_i: u32,
46104372 alignment: Builder.Alignment,
4611 byval_attr: bool,
4612 param_llvm_ty: Builder.Type,
4613 ) Allocator.Error!void {
4614 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4615 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
4616 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder);
4617 if (byval_attr) {
4618 try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder);
4619 }
4620 }
4621
4622 fn addByValParamAttrsOld(
4623 o: *Object,
4624 attributes: *Builder.FunctionAttributes.Wip,
4625 llvm_fn: *llvm.Value,
4626 param_ty: Type,
4627 param_index: u32,
4628 fn_info: InternPool.Key.FuncType,
4629 llvm_arg_i: u32,
4630 ) Allocator.Error!void {
4631 const mod = o.module;
4632 if (param_ty.isPtrAtRuntime(mod)) {
4633 const ptr_info = param_ty.ptrInfo(mod);
4634 if (math.cast(u5, param_index)) |i| {
4635 if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
4636 try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
4637 o.addArgAttr(llvm_fn, llvm_arg_i, "noalias");
4638 }
4639 }
4640 if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) {
4641 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4642 o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
4643 }
4644 if (ptr_info.flags.is_const) {
4645 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
4646 o.addArgAttr(llvm_fn, llvm_arg_i, "readonly");
4647 }
4648 const elem_align = Builder.Alignment.fromByteUnits(
4649 ptr_info.flags.alignment.toByteUnitsOptional() orelse
4650 @max(ptr_info.child.toType().abiAlignment(mod), 1),
4651 );
4652 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder);
4653 o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0);
4654 } else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) {
4655 .signed => {
4656 try attributes.addParamAttr(llvm_arg_i, .signext, &o.builder);
4657 o.addArgAttr(llvm_fn, llvm_arg_i, "signext");
4658 },
4659 .unsigned => {
4660 try attributes.addParamAttr(llvm_arg_i, .zeroext, &o.builder);
4661 o.addArgAttr(llvm_fn, llvm_arg_i, "zeroext");
4662 },
4663 };
4664 }
4665
4666 fn addByRefParamAttrsOld(
4667 o: *Object,
4668 attributes: *Builder.FunctionAttributes.Wip,
4669 llvm_fn: *llvm.Value,
4670 llvm_arg_i: u32,
4671 alignment: Builder.Alignment,
4672 byval_attr: bool,
4373 byval: bool,
46734374 param_llvm_ty: Builder.Type,
46744375 ) Allocator.Error!void {
46754376 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
46764377 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
46774378 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder);
4678 o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
4679 o.addArgAttr(llvm_fn, llvm_arg_i, "readonly");
4680 o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment.toByteUnits() orelse 0);
4681 if (byval_attr) {
4682 try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder);
4683 llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty.toLlvm(&o.builder));
4684 }
4379 if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder);
46854380 }
46864381};
46874382
......@@ -4712,65 +4407,22 @@ pub const DeclGen = struct {
47124407 if (decl.val.getExternFunc(mod)) |extern_func| {
47134408 _ = try o.resolveLlvmFunction(extern_func.decl);
47144409 } else {
4715 const target = mod.getTarget();
4716 const variable = try o.resolveGlobalDecl(decl_index);
4717 const global = variable.ptrConst(&o.builder).global;
4718 var llvm_global = global.toLlvm(&o.builder);
4719 variable.ptr(&o.builder).alignment = Builder.Alignment.fromByteUnits(decl.getAlignment(mod));
4720 llvm_global.setAlignment(decl.getAlignment(mod));
4721 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| {
4722 variable.ptr(&o.builder).section = try o.builder.string(section);
4723 llvm_global.setSection(section);
4724 }
4410 const variable_index = try o.resolveGlobalDecl(decl_index);
4411 variable_index.setAlignment(
4412 Builder.Alignment.fromByteUnits(decl.getAlignment(mod)),
4413 &o.builder,
4414 );
4415 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
4416 variable_index.setSection(try o.builder.string(section), &o.builder);
47254417 assert(decl.has_tv);
47264418 const init_val = if (decl.val.getVariable(mod)) |decl_var| decl_var.init else init_val: {
4727 variable.ptr(&o.builder).mutability = .constant;
4728 llvm_global.setGlobalConstant(.True);
4419 variable_index.setMutability(.constant, &o.builder);
47294420 break :init_val decl.val.toIntern();
47304421 };
4731 if (init_val != .none) {
4732 const llvm_init = try o.lowerValue(init_val);
4733 const llvm_init_ty = llvm_init.typeOf(&o.builder);
4734 if (global.ptrConst(&o.builder).type == llvm_init_ty) {
4735 llvm_global.setInitializer(llvm_init.toLlvm(&o.builder));
4736 } else {
4737 // LLVM does not allow us to change the type of globals. So we must
4738 // create a new global with the correct type, copy all its attributes,
4739 // and then update all references to point to the new global,
4740 // delete the original, and rename the new one to the old one's name.
4741 // This is necessary because LLVM does not support const bitcasting
4742 // a struct with padding bytes, which is needed to lower a const union value
4743 // to LLVM, when a field other than the most-aligned is active. Instead,
4744 // we must lower to an unnamed struct, and pointer cast at usage sites
4745 // of the global. Such an unnamed struct is the cause of the global type
4746 // mismatch, because we don't have the LLVM type until the *value* is created,
4747 // whereas the global needs to be created based on the type alone, because
4748 // lowering the value may reference the global as a pointer.
4749 // Related: https://github.com/ziglang/zig/issues/13265
4750 const llvm_global_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
4751 const new_global = o.llvm_module.addGlobalInAddressSpace(
4752 llvm_init_ty.toLlvm(&o.builder),
4753 "",
4754 @intFromEnum(llvm_global_addrspace),
4755 );
4756 new_global.setLinkage(llvm_global.getLinkage());
4757 new_global.setUnnamedAddr(llvm_global.getUnnamedAddress());
4758 new_global.setAlignment(llvm_global.getAlignment());
4759 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
4760 new_global.setSection(section);
4761 new_global.setInitializer(llvm_init.toLlvm(&o.builder));
4762 // TODO: How should this work then the address space of a global changed?
4763 llvm_global.replaceAllUsesWith(new_global);
4764 new_global.takeName(llvm_global);
4765 o.builder.llvm.globals.items[@intFromEnum(variable.ptrConst(&o.builder).global)] =
4766 new_global;
4767 llvm_global.deleteGlobal();
4768 llvm_global = new_global;
4769 variable.ptr(&o.builder).mutability = .global;
4770 global.ptr(&o.builder).type = llvm_init_ty;
4771 }
4772 variable.ptr(&o.builder).init = llvm_init;
4773 }
4422 try variable_index.setInitializer(switch (init_val) {
4423 .none => .no_init,
4424 else => try o.lowerValue(init_val),
4425 }, &o.builder);
47744426
47754427 if (o.di_builder) |dib| {
47764428 const di_file = try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
......@@ -4780,7 +4432,7 @@ pub const DeclGen = struct {
47804432 const di_global = dib.createGlobalVariableExpression(
47814433 di_file.toScope(),
47824434 mod.intern_pool.stringToSlice(decl.name),
4783 llvm_global.getValueName(),
4435 variable_index.name(&o.builder).slice(&o.builder).?,
47844436 di_file,
47854437 line_number,
47864438 try o.lowerDebugType(decl.ty, .full),
......@@ -4788,7 +4440,8 @@ pub const DeclGen = struct {
47884440 );
47894441
47904442 try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode());
4791 if (!is_internal_linkage or decl.isExtern(mod)) llvm_global.attachMetaData(di_global);
4443 if (!is_internal_linkage or decl.isExtern(mod))
4444 variable_index.toLlvm(&o.builder).attachMetaData(di_global);
47924445 }
47934446 }
47944447 }
......@@ -4800,7 +4453,6 @@ pub const FuncGen = struct {
48004453 air: Air,
48014454 liveness: Liveness,
48024455 wip: Builder.WipFunction,
4803 builder: *llvm.Builder,
48044456 di_scope: ?*llvm.DIScope,
48054457 di_file: ?*llvm.DIFile,
48064458 base_line: u32,
......@@ -4889,38 +4541,22 @@ pub const FuncGen = struct {
48894541 // We have an LLVM value but we need to create a global constant and
48904542 // set the value as its initializer, and then return a pointer to the global.
48914543 const target = mod.getTarget();
4892 const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target);
4893 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target);
4894 const llvm_ty = llvm_val.typeOf(&o.builder);
4895 const llvm_alignment = tv.ty.abiAlignment(mod);
4896 const llvm_global = o.llvm_module.addGlobalInAddressSpace(llvm_ty.toLlvm(&o.builder), "", @intFromEnum(llvm_actual_addrspace));
4897 llvm_global.setInitializer(llvm_val.toLlvm(&o.builder));
4898 llvm_global.setLinkage(.Private);
4899 llvm_global.setGlobalConstant(.True);
4900 llvm_global.setUnnamedAddr(.True);
4901 llvm_global.setAlignment(llvm_alignment);
4902
4903 var global = Builder.Global{
4904 .linkage = .private,
4905 .unnamed_addr = .unnamed_addr,
4906 .addr_space = llvm_actual_addrspace,
4907 .type = llvm_ty,
4908 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
4909 };
4910 var variable = Builder.Variable{
4911 .global = @enumFromInt(o.builder.globals.count()),
4912 .mutability = .constant,
4913 .init = llvm_val,
4914 .alignment = Builder.Alignment.fromByteUnits(llvm_alignment),
4915 };
4916 try o.builder.llvm.globals.append(o.gpa, llvm_global);
4917 const global_index = try o.builder.addGlobal(.empty, global);
4918 try o.builder.variables.append(o.gpa, variable);
4919
4544 const variable_index = try o.builder.addVariable(
4545 .empty,
4546 llvm_val.typeOf(&o.builder),
4547 toLlvmGlobalAddressSpace(.generic, target),
4548 );
4549 try variable_index.setInitializer(llvm_val, &o.builder);
4550 variable_index.setLinkage(.private, &o.builder);
4551 variable_index.setMutability(.constant, &o.builder);
4552 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4553 variable_index.setAlignment(Builder.Alignment.fromByteUnits(
4554 tv.ty.abiAlignment(mod),
4555 ), &o.builder);
49204556 return o.builder.convConst(
49214557 .unneeded,
4922 global_index.toConst(),
4923 try o.builder.ptrType(llvm_wanted_addrspace),
4558 variable_index.toConst(&o.builder),
4559 try o.builder.ptrType(toLlvmAddressSpace(.generic, target)),
49244560 );
49254561 }
49264562
......@@ -4947,31 +4583,31 @@ pub const FuncGen = struct {
49474583
49484584 const val: Builder.Value = switch (air_tags[inst]) {
49494585 // zig fmt: off
4950 .add => try self.airAdd(inst, false),
4951 .add_optimized => try self.airAdd(inst, true),
4586 .add => try self.airAdd(inst, .normal),
4587 .add_optimized => try self.airAdd(inst, .fast),
49524588 .add_wrap => try self.airAddWrap(inst),
49534589 .add_sat => try self.airAddSat(inst),
49544590
4955 .sub => try self.airSub(inst, false),
4956 .sub_optimized => try self.airSub(inst, true),
4591 .sub => try self.airSub(inst, .normal),
4592 .sub_optimized => try self.airSub(inst, .fast),
49574593 .sub_wrap => try self.airSubWrap(inst),
49584594 .sub_sat => try self.airSubSat(inst),
49594595
4960 .mul => try self.airMul(inst, false),
4961 .mul_optimized => try self.airMul(inst, true),
4596 .mul => try self.airMul(inst, .normal),
4597 .mul_optimized => try self.airMul(inst, .fast),
49624598 .mul_wrap => try self.airMulWrap(inst),
49634599 .mul_sat => try self.airMulSat(inst),
49644600
4965 .add_safe => try self.airSafeArithmetic(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),
4966 .sub_safe => try self.airSafeArithmetic(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),
4967 .mul_safe => try self.airSafeArithmetic(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),
4601 .add_safe => try self.airSafeArithmetic(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"),
4602 .sub_safe => try self.airSafeArithmetic(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
4603 .mul_safe => try self.airSafeArithmetic(inst, .@"smul.with.overflow", .@"umul.with.overflow"),
49684604
4969 .div_float => try self.airDivFloat(inst, false),
4970 .div_trunc => try self.airDivTrunc(inst, false),
4971 .div_floor => try self.airDivFloor(inst, false),
4972 .div_exact => try self.airDivExact(inst, false),
4973 .rem => try self.airRem(inst, false),
4974 .mod => try self.airMod(inst, false),
4605 .div_float => try self.airDivFloat(inst, .normal),
4606 .div_trunc => try self.airDivTrunc(inst, .normal),
4607 .div_floor => try self.airDivFloor(inst, .normal),
4608 .div_exact => try self.airDivExact(inst, .normal),
4609 .rem => try self.airRem(inst, .normal),
4610 .mod => try self.airMod(inst, .normal),
49754611 .ptr_add => try self.airPtrAdd(inst),
49764612 .ptr_sub => try self.airPtrSub(inst),
49774613 .shl => try self.airShl(inst),
......@@ -4982,16 +4618,16 @@ pub const FuncGen = struct {
49824618 .slice => try self.airSlice(inst),
49834619 .mul_add => try self.airMulAdd(inst),
49844620
4985 .div_float_optimized => try self.airDivFloat(inst, true),
4986 .div_trunc_optimized => try self.airDivTrunc(inst, true),
4987 .div_floor_optimized => try self.airDivFloor(inst, true),
4988 .div_exact_optimized => try self.airDivExact(inst, true),
4989 .rem_optimized => try self.airRem(inst, true),
4990 .mod_optimized => try self.airMod(inst, true),
4621 .div_float_optimized => try self.airDivFloat(inst, .fast),
4622 .div_trunc_optimized => try self.airDivTrunc(inst, .fast),
4623 .div_floor_optimized => try self.airDivFloor(inst, .fast),
4624 .div_exact_optimized => try self.airDivExact(inst, .fast),
4625 .rem_optimized => try self.airRem(inst, .fast),
4626 .mod_optimized => try self.airMod(inst, .fast),
49914627
4992 .add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),
4993 .sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),
4994 .mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),
4628 .add_with_overflow => try self.airOverflow(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"),
4629 .sub_with_overflow => try self.airOverflow(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
4630 .mul_with_overflow => try self.airOverflow(inst, .@"smul.with.overflow", .@"umul.with.overflow"),
49954631 .shl_with_overflow => try self.airShlWithOverflow(inst),
49964632
49974633 .bit_and, .bool_and => try self.airAnd(inst),
......@@ -5015,25 +4651,25 @@ pub const FuncGen = struct {
50154651 .round => try self.airUnaryOp(inst, .round),
50164652 .trunc_float => try self.airUnaryOp(inst, .trunc),
50174653
5018 .neg => try self.airNeg(inst, false),
5019 .neg_optimized => try self.airNeg(inst, true),
5020
5021 .cmp_eq => try self.airCmp(inst, .eq, false),
5022 .cmp_gt => try self.airCmp(inst, .gt, false),
5023 .cmp_gte => try self.airCmp(inst, .gte, false),
5024 .cmp_lt => try self.airCmp(inst, .lt, false),
5025 .cmp_lte => try self.airCmp(inst, .lte, false),
5026 .cmp_neq => try self.airCmp(inst, .neq, false),
5027
5028 .cmp_eq_optimized => try self.airCmp(inst, .eq, true),
5029 .cmp_gt_optimized => try self.airCmp(inst, .gt, true),
5030 .cmp_gte_optimized => try self.airCmp(inst, .gte, true),
5031 .cmp_lt_optimized => try self.airCmp(inst, .lt, true),
5032 .cmp_lte_optimized => try self.airCmp(inst, .lte, true),
5033 .cmp_neq_optimized => try self.airCmp(inst, .neq, true),
5034
5035 .cmp_vector => try self.airCmpVector(inst, false),
5036 .cmp_vector_optimized => try self.airCmpVector(inst, true),
4654 .neg => try self.airNeg(inst, .normal),
4655 .neg_optimized => try self.airNeg(inst, .fast),
4656
4657 .cmp_eq => try self.airCmp(inst, .eq, .normal),
4658 .cmp_gt => try self.airCmp(inst, .gt, .normal),
4659 .cmp_gte => try self.airCmp(inst, .gte, .normal),
4660 .cmp_lt => try self.airCmp(inst, .lt, .normal),
4661 .cmp_lte => try self.airCmp(inst, .lte, .normal),
4662 .cmp_neq => try self.airCmp(inst, .neq, .normal),
4663
4664 .cmp_eq_optimized => try self.airCmp(inst, .eq, .fast),
4665 .cmp_gt_optimized => try self.airCmp(inst, .gt, .fast),
4666 .cmp_gte_optimized => try self.airCmp(inst, .gte, .fast),
4667 .cmp_lt_optimized => try self.airCmp(inst, .lt, .fast),
4668 .cmp_lte_optimized => try self.airCmp(inst, .lte, .fast),
4669 .cmp_neq_optimized => try self.airCmp(inst, .neq, .fast),
4670
4671 .cmp_vector => try self.airCmpVector(inst, .normal),
4672 .cmp_vector_optimized => try self.airCmpVector(inst, .fast),
50374673 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
50384674
50394675 .is_non_null => try self.airIsNonNull(inst, false, .ne),
......@@ -5085,13 +4721,13 @@ pub const FuncGen = struct {
50854721 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
50864722 .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),
50874723
5088 .int_from_float => try self.airIntFromFloat(inst, false),
5089 .int_from_float_optimized => try self.airIntFromFloat(inst, true),
4724 .int_from_float => try self.airIntFromFloat(inst, .normal),
4725 .int_from_float_optimized => try self.airIntFromFloat(inst, .fast),
50904726
50914727 .array_to_slice => try self.airArrayToSlice(inst),
50924728 .float_from_int => try self.airFloatFromInt(inst),
5093 .cmpxchg_weak => try self.airCmpxchg(inst, true),
5094 .cmpxchg_strong => try self.airCmpxchg(inst, false),
4729 .cmpxchg_weak => try self.airCmpxchg(inst, .weak),
4730 .cmpxchg_strong => try self.airCmpxchg(inst, .strong),
50954731 .fence => try self.airFence(inst),
50964732 .atomic_rmw => try self.airAtomicRmw(inst),
50974733 .atomic_load => try self.airAtomicLoad(inst),
......@@ -5100,11 +4736,11 @@ pub const FuncGen = struct {
51004736 .memcpy => try self.airMemcpy(inst),
51014737 .set_union_tag => try self.airSetUnionTag(inst),
51024738 .get_union_tag => try self.airGetUnionTag(inst),
5103 .clz => try self.airClzCtz(inst, .@"llvm.ctlz."),
5104 .ctz => try self.airClzCtz(inst, .@"llvm.cttz."),
5105 .popcount => try self.airBitOp(inst, .@"llvm.ctpop."),
4739 .clz => try self.airClzCtz(inst, .ctlz),
4740 .ctz => try self.airClzCtz(inst, .cttz),
4741 .popcount => try self.airBitOp(inst, .ctpop),
51064742 .byte_swap => try self.airByteSwap(inst),
5107 .bit_reverse => try self.airBitOp(inst, .@"llvm.bitreverse."),
4743 .bit_reverse => try self.airBitOp(inst, .bitreverse),
51084744 .tag_name => try self.airTagName(inst),
51094745 .error_name => try self.airErrorName(inst),
51104746 .splat => try self.airSplat(inst),
......@@ -5118,8 +4754,8 @@ pub const FuncGen = struct {
51184754 .is_named_enum_value => try self.airIsNamedEnumValue(inst),
51194755 .error_set_has_value => try self.airErrorSetHasValue(inst),
51204756
5121 .reduce => try self.airReduce(inst, false),
5122 .reduce_optimized => try self.airReduce(inst, true),
4757 .reduce => try self.airReduce(inst, .normal),
4758 .reduce_optimized => try self.airReduce(inst, .fast),
51234759
51244760 .atomic_store_unordered => try self.airAtomicStore(inst, .unordered),
51254761 .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),
......@@ -5304,10 +4940,7 @@ pub const FuncGen = struct {
53044940 } else {
53054941 // LLVM does not allow bitcasting structs so we must allocate
53064942 // a local, store as one type, and then load as another type.
5307 const alignment = Builder.Alignment.fromByteUnits(@max(
5308 param_ty.abiAlignment(mod),
5309 o.target_data.abiAlignmentOfType(int_llvm_ty.toLlvm(&o.builder)),
5310 ));
4943 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
53114944 const int_ptr = try self.buildAlloca(int_llvm_ty, alignment);
53124945 _ = try self.wip.store(.normal, llvm_arg, int_ptr, alignment);
53134946 const loaded = try self.wip.load(.normal, int_llvm_ty, int_ptr, alignment, "");
......@@ -5483,12 +5116,10 @@ pub const FuncGen = struct {
54835116 // In this case the function return type is honoring the calling convention by having
54845117 // a different LLVM type than the usual one. We solve this here at the callsite
54855118 // by using our canonical type, then loading it if necessary.
5486 const alignment = Builder.Alignment.fromByteUnits(@max(
5487 o.target_data.abiAlignmentOfType(abi_ret_ty.toLlvm(&o.builder)),
5488 return_type.abiAlignment(mod),
5489 ));
5490 assert(o.target_data.abiSizeOfType(abi_ret_ty.toLlvm(&o.builder)) >=
5491 o.target_data.abiSizeOfType(llvm_ret_ty.toLlvm(&o.builder)));
5119 const alignment = Builder.Alignment.fromByteUnits(return_type.abiAlignment(mod));
5120 if (o.builder.useLibLlvm())
5121 assert(o.target_data.abiSizeOfType(abi_ret_ty.toLlvm(&o.builder)) >=
5122 o.target_data.abiSizeOfType(llvm_ret_ty.toLlvm(&o.builder)));
54925123 const rp = try self.buildAlloca(abi_ret_ty, alignment);
54935124 _ = try self.wip.store(.normal, call, rp, alignment);
54945125 return if (isByRef(return_type, mod))
......@@ -5645,22 +5276,7 @@ pub const FuncGen = struct {
56455276 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
56465277 const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
56475278
5648 const llvm_fn_name = "llvm.va_copy";
5649 const llvm_fn_ty = try o.builder.fnType(.void, &.{ .ptr, .ptr }, .normal);
5650 const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse
5651 o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder));
5652
5653 const args: [2]*llvm.Value = .{ dest_list.toLlvm(&self.wip), src_list.toLlvm(&self.wip) };
5654 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
5655 llvm_fn_ty.toLlvm(&o.builder),
5656 llvm_fn,
5657 &args,
5658 args.len,
5659 .Fast,
5660 .Auto,
5661 "",
5662 ), &self.wip);
5663
5279 _ = try self.wip.callIntrinsic(.normal, .none, .va_copy, &.{}, &.{ dest_list, src_list }, "");
56645280 return if (isByRef(va_list_ty, mod))
56655281 dest_list
56665282 else
......@@ -5668,25 +5284,10 @@ pub const FuncGen = struct {
56685284 }
56695285
56705286 fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
5671 const o = self.dg.object;
56725287 const un_op = self.air.instructions.items(.data)[inst].un_op;
5673 const list = try self.resolveInst(un_op);
5674
5675 const llvm_fn_name = "llvm.va_end";
5676 const llvm_fn_ty = try o.builder.fnType(.void, &.{.ptr}, .normal);
5677 const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse
5678 o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder));
5288 const src_list = try self.resolveInst(un_op);
56795289
5680 const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)};
5681 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
5682 llvm_fn_ty.toLlvm(&o.builder),
5683 llvm_fn,
5684 &args,
5685 args.len,
5686 .Fast,
5687 .Auto,
5688 "",
5689 ), &self.wip);
5290 _ = try self.wip.callIntrinsic(.normal, .none, .va_end, &.{}, &.{src_list}, "");
56905291 return .none;
56915292 }
56925293
......@@ -5697,44 +5298,30 @@ pub const FuncGen = struct {
56975298 const llvm_va_list_ty = try o.lowerType(va_list_ty);
56985299
56995300 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
5700 const list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
5701
5702 const llvm_fn_name = "llvm.va_start";
5703 const llvm_fn_ty = try o.builder.fnType(.void, &.{.ptr}, .normal);
5704 const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse
5705 o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder));
5706
5707 const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)};
5708 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
5709 llvm_fn_ty.toLlvm(&o.builder),
5710 llvm_fn,
5711 &args,
5712 args.len,
5713 .Fast,
5714 .Auto,
5715 "",
5716 ), &self.wip);
5301 const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
57175302
5303 _ = try self.wip.callIntrinsic(.normal, .none, .va_start, &.{}, &.{dest_list}, "");
57185304 return if (isByRef(va_list_ty, mod))
5719 list
5305 dest_list
57205306 else
5721 try self.wip.load(.normal, llvm_va_list_ty, list, result_alignment, "");
5307 try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, "");
57225308 }
57235309
5724 fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !Builder.Value {
5725 self.builder.setFastMath(want_fast_math);
5726
5310 fn airCmp(
5311 self: *FuncGen,
5312 inst: Air.Inst.Index,
5313 op: math.CompareOperator,
5314 fast: Builder.FastMathKind,
5315 ) !Builder.Value {
57275316 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
57285317 const lhs = try self.resolveInst(bin_op.lhs);
57295318 const rhs = try self.resolveInst(bin_op.rhs);
57305319 const operand_ty = self.typeOf(bin_op.lhs);
57315320
5732 return self.cmp(lhs, rhs, operand_ty, op);
5321 return self.cmp(fast, op, operand_ty, lhs, rhs);
57335322 }
57345323
5735 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
5736 self.builder.setFastMath(want_fast_math);
5737
5324 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
57385325 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
57395326 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
57405327
......@@ -5743,7 +5330,7 @@ pub const FuncGen = struct {
57435330 const vec_ty = self.typeOf(extra.lhs);
57445331 const cmp_op = extra.compareOperator();
57455332
5746 return self.cmp(lhs, rhs, vec_ty, cmp_op);
5333 return self.cmp(fast, cmp_op, vec_ty, lhs, rhs);
57475334 }
57485335
57495336 fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -5764,10 +5351,11 @@ pub const FuncGen = struct {
57645351
57655352 fn cmp(
57665353 self: *FuncGen,
5354 fast: Builder.FastMathKind,
5355 op: math.CompareOperator,
5356 operand_ty: Type,
57675357 lhs: Builder.Value,
57685358 rhs: Builder.Value,
5769 operand_ty: Type,
5770 op: math.CompareOperator,
57715359 ) Allocator.Error!Builder.Value {
57725360 const o = self.dg.object;
57735361 const mod = o.module;
......@@ -5819,13 +5407,13 @@ pub const FuncGen = struct {
58195407 self.wip.cursor = .{ .block = both_pl_block };
58205408 const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty, true);
58215409 const rhs_payload = try self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty, true);
5822 const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op);
5410 const payload_cmp = try self.cmp(fast, op, payload_ty, lhs_payload, rhs_payload);
58235411 _ = try self.wip.br(end_block);
58245412 const both_pl_block_end = self.wip.cursor.block;
58255413
58265414 self.wip.cursor = .{ .block = end_block };
5827 const llvm_i1_0 = try o.builder.intValue(.i1, 0);
5828 const llvm_i1_1 = try o.builder.intValue(.i1, 1);
5415 const llvm_i1_0 = Builder.Value.false;
5416 const llvm_i1_1 = Builder.Value.true;
58295417 const incoming_values: [3]Builder.Value = .{
58305418 switch (op) {
58315419 .eq => llvm_i1_1,
......@@ -5848,7 +5436,7 @@ pub const FuncGen = struct {
58485436 );
58495437 return phi.toValue();
58505438 },
5851 .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }),
5439 .Float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }),
58525440 else => unreachable,
58535441 };
58545442 const is_signed = int_ty.isSignedInt(mod);
......@@ -6046,7 +5634,7 @@ pub const FuncGen = struct {
60465634 if (can_elide_load)
60475635 return payload_ptr;
60485636
6049 return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, false);
5637 return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal);
60505638 }
60515639 const load_ty = err_union_llvm_ty.structFields(&o.builder)[offset];
60525640 return fg.wip.load(.normal, load_ty, payload_ptr, payload_alignment, "");
......@@ -6219,8 +5807,12 @@ pub const FuncGen = struct {
62195807 );
62205808 }
62215809
6222 fn airIntFromFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
6223 self.builder.setFastMath(want_fast_math);
5810 fn airIntFromFloat(
5811 self: *FuncGen,
5812 inst: Air.Inst.Index,
5813 fast: Builder.FastMathKind,
5814 ) !Builder.Value {
5815 _ = fast;
62245816
62255817 const o = self.dg.object;
62265818 const mod = o.module;
......@@ -6345,7 +5937,7 @@ pub const FuncGen = struct {
63455937 return ptr;
63465938
63475939 const elem_alignment = Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod));
6348 return self.loadByRef(ptr, elem_ty, elem_alignment, false);
5940 return self.loadByRef(ptr, elem_ty, elem_alignment, .normal);
63495941 }
63505942
63515943 return self.load(ptr, slice_ty);
......@@ -6385,7 +5977,7 @@ pub const FuncGen = struct {
63855977 try self.wip.gep(.inbounds, array_llvm_ty, array_llvm_val, &indices, "");
63865978 if (canElideLoad(self, body_tail)) return elem_ptr;
63875979 const elem_alignment = Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod));
6388 return self.loadByRef(elem_ptr, elem_ty, elem_alignment, false);
5980 return self.loadByRef(elem_ptr, elem_ty, elem_alignment, .normal);
63895981 } else {
63905982 const elem_llvm_ty = try o.lowerType(elem_ty);
63915983 if (Air.refToIndex(bin_op.lhs)) |lhs_index| {
......@@ -6445,7 +6037,7 @@ pub const FuncGen = struct {
64456037 if (isByRef(elem_ty, mod)) {
64466038 if (self.canElideLoad(body_tail)) return ptr;
64476039 const elem_alignment = Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod));
6448 return self.loadByRef(ptr, elem_ty, elem_alignment, false);
6040 return self.loadByRef(ptr, elem_ty, elem_alignment, .normal);
64496041 }
64506042
64516043 return self.load(ptr, ptr_ty);
......@@ -6467,7 +6059,7 @@ pub const FuncGen = struct {
64676059 if (elem_ptr.ptrInfo(mod).flags.vector_index != .none) return base_ptr;
64686060
64696061 const llvm_elem_ty = try o.lowerPtrElemTy(elem_ty);
6470 return try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(mod))
6062 return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(mod))
64716063 // If this is a single-item pointer to an array, we need another index in the GEP.
64726064 &.{ try o.builder.intValue(try o.lowerType(Type.usize), 0), rhs }
64736065 else
......@@ -6575,7 +6167,7 @@ pub const FuncGen = struct {
65756167
65766168 assert(llvm_field.alignment != 0);
65776169 const field_alignment = Builder.Alignment.fromByteUnits(llvm_field.alignment);
6578 return self.loadByRef(field_ptr, field_ty, field_alignment, false);
6170 return self.loadByRef(field_ptr, field_ty, field_alignment, .normal);
65796171 } else {
65806172 return self.load(field_ptr, field_ptr_ty);
65816173 }
......@@ -6590,7 +6182,7 @@ pub const FuncGen = struct {
65906182 const payload_alignment = Builder.Alignment.fromByteUnits(layout.payload_align);
65916183 if (isByRef(field_ty, mod)) {
65926184 if (canElideLoad(self, body_tail)) return field_ptr;
6593 return self.loadByRef(field_ptr, field_ty, payload_alignment, false);
6185 return self.loadByRef(field_ptr, field_ty, payload_alignment, .normal);
65946186 } else {
65956187 return self.wip.load(.normal, llvm_field_ty, field_ptr, payload_alignment, "");
65966188 }
......@@ -6638,6 +6230,8 @@ pub const FuncGen = struct {
66386230 }
66396231
66406232 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6233 if (!self.dg.object.builder.useLibLlvm()) return .none;
6234
66416235 const di_scope = self.di_scope orelse return .none;
66426236 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
66436237 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);
......@@ -6646,12 +6240,19 @@ pub const FuncGen = struct {
66466240 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc
66476241 else
66486242 null;
6649 self.builder.setCurrentDebugLocation(self.prev_dbg_line, self.prev_dbg_column, di_scope, inlined_at);
6243 self.wip.llvm.builder.setCurrentDebugLocation(
6244 self.prev_dbg_line,
6245 self.prev_dbg_column,
6246 di_scope,
6247 inlined_at,
6248 );
66506249 return .none;
66516250 }
66526251
66536252 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
66546253 const o = self.dg.object;
6254 if (!o.builder.useLibLlvm()) return .none;
6255
66556256 const dib = o.di_builder orelse return .none;
66566257 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
66576258
......@@ -6662,7 +6263,7 @@ pub const FuncGen = struct {
66626263 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
66636264 self.di_file = di_file;
66646265 const line_number = decl.src_line + 1;
6665 const cur_debug_location = self.builder.getCurrentDebugLocation2();
6266 const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2();
66666267
66676268 try self.dbg_inlined.append(self.gpa, .{
66686269 .loc = @ptrCast(cur_debug_location),
......@@ -6710,6 +6311,8 @@ pub const FuncGen = struct {
67106311
67116312 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
67126313 const o = self.dg.object;
6314 if (!o.builder.useLibLlvm()) return .none;
6315
67136316 if (o.di_builder == null) return .none;
67146317 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
67156318
......@@ -6725,6 +6328,8 @@ pub const FuncGen = struct {
67256328
67266329 fn airDbgBlockBegin(self: *FuncGen) !Builder.Value {
67276330 const o = self.dg.object;
6331 if (!o.builder.useLibLlvm()) return .none;
6332
67286333 const dib = o.di_builder orelse return .none;
67296334 const old_scope = self.di_scope.?;
67306335 try self.dbg_block_stack.append(self.gpa, old_scope);
......@@ -6735,6 +6340,8 @@ pub const FuncGen = struct {
67356340
67366341 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {
67376342 const o = self.dg.object;
6343 if (!o.builder.useLibLlvm()) return .none;
6344
67386345 if (o.di_builder == null) return .none;
67396346 self.di_scope = self.dbg_block_stack.pop();
67406347 return .none;
......@@ -6742,6 +6349,8 @@ pub const FuncGen = struct {
67426349
67436350 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
67446351 const o = self.dg.object;
6352 if (!o.builder.useLibLlvm()) return .none;
6353
67456354 const mod = o.module;
67466355 const dib = o.di_builder orelse return .none;
67476356 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
......@@ -6770,6 +6379,8 @@ pub const FuncGen = struct {
67706379
67716380 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
67726381 const o = self.dg.object;
6382 if (!o.builder.useLibLlvm()) return .none;
6383
67736384 const dib = o.di_builder orelse return .none;
67746385 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
67756386 const operand = try self.resolveInst(pl_op.operand);
......@@ -7374,7 +6985,7 @@ pub const FuncGen = struct {
73746985 const payload_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");
73756986 if (isByRef(payload_ty, mod)) {
73766987 if (self.canElideLoad(body_tail)) return payload_ptr;
7377 return self.loadByRef(payload_ptr, payload_ty, payload_alignment, false);
6988 return self.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal);
73786989 }
73796990 const payload_llvm_ty = err_union_llvm_ty.structFields(&o.builder)[offset];
73806991 return self.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, "");
......@@ -7570,40 +7181,18 @@ pub const FuncGen = struct {
75707181 const o = self.dg.object;
75717182 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
75727183 const index = pl_op.payload;
7573 const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.size", &.{.i32});
7574 const args: [1]*llvm.Value = .{
7575 (try o.builder.intConst(.i32, index)).toLlvm(&o.builder),
7576 };
7577 return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld(
7578 (try o.builder.fnType(.i32, &.{.i32}, .normal)).toLlvm(&o.builder),
7579 llvm_fn,
7580 &args,
7581 args.len,
7582 .Fast,
7583 .Auto,
7584 "",
7585 ), &self.wip);
7184 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{.i32}, &.{
7185 try o.builder.intValue(.i32, index),
7186 }, "");
75867187 }
75877188
75887189 fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
75897190 const o = self.dg.object;
75907191 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
75917192 const index = pl_op.payload;
7592 const operand = try self.resolveInst(pl_op.operand);
7593 const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.grow", &.{.i32});
7594 const args: [2]*llvm.Value = .{
7595 (try o.builder.intConst(.i32, index)).toLlvm(&o.builder),
7596 operand.toLlvm(&self.wip),
7597 };
7598 return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld(
7599 (try o.builder.fnType(.i32, &.{ .i32, .i32 }, .normal)).toLlvm(&o.builder),
7600 llvm_fn,
7601 &args,
7602 args.len,
7603 .Fast,
7604 .Auto,
7605 "",
7606 ), &self.wip);
7193 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{.i32}, &.{
7194 try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),
7195 }, "");
76077196 }
76087197
76097198 fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -7617,13 +7206,11 @@ pub const FuncGen = struct {
76177206 const index = try self.resolveInst(extra.lhs);
76187207 const operand = try self.resolveInst(extra.rhs);
76197208
7620 const kind: Builder.MemoryAccessKind = switch (vector_ptr_ty.isVolatilePtr(mod)) {
7621 false => .normal,
7622 true => .@"volatile",
7623 };
7209 const access_kind: Builder.MemoryAccessKind =
7210 if (vector_ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal;
76247211 const elem_llvm_ty = try o.lowerType(vector_ptr_ty.childType(mod));
76257212 const alignment = Builder.Alignment.fromByteUnits(vector_ptr_ty.ptrAlignment(mod));
7626 const loaded = try self.wip.load(kind, elem_llvm_ty, vector_ptr, alignment, "");
7213 const loaded = try self.wip.load(access_kind, elem_llvm_ty, vector_ptr, alignment, "");
76277214
76287215 const new_vector = try self.wip.insertElement(loaded, operand, index, "");
76297216 _ = try self.store(vector_ptr, vector_ptr_ty, new_vector, .none);
......@@ -7636,13 +7223,18 @@ pub const FuncGen = struct {
76367223 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
76377224 const lhs = try self.resolveInst(bin_op.lhs);
76387225 const rhs = try self.resolveInst(bin_op.rhs);
7639 const scalar_ty = self.typeOfIndex(inst).scalarType(mod);
7226 const inst_ty = self.typeOfIndex(inst);
7227 const scalar_ty = inst_ty.scalarType(mod);
76407228
7641 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, scalar_ty, 2, .{ lhs, rhs });
7642 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
7643 .@"llvm.smin."
7644 else
7645 .@"llvm.umin.", lhs, rhs, "");
7229 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, .normal, inst_ty, 2, .{ lhs, rhs });
7230 return self.wip.callIntrinsic(
7231 .normal,
7232 .none,
7233 if (scalar_ty.isSignedInt(mod)) .smin else .umin,
7234 &.{try o.lowerType(inst_ty)},
7235 &.{ lhs, rhs },
7236 "",
7237 );
76467238 }
76477239
76487240 fn airMax(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -7651,13 +7243,18 @@ pub const FuncGen = struct {
76517243 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
76527244 const lhs = try self.resolveInst(bin_op.lhs);
76537245 const rhs = try self.resolveInst(bin_op.rhs);
7654 const scalar_ty = self.typeOfIndex(inst).scalarType(mod);
7246 const inst_ty = self.typeOfIndex(inst);
7247 const scalar_ty = inst_ty.scalarType(mod);
76557248
7656 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, scalar_ty, 2, .{ lhs, rhs });
7657 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
7658 .@"llvm.smax."
7659 else
7660 .@"llvm.umax.", lhs, rhs, "");
7249 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, .normal, inst_ty, 2, .{ lhs, rhs });
7250 return self.wip.callIntrinsic(
7251 .normal,
7252 .none,
7253 if (scalar_ty.isSignedInt(mod)) .smax else .umax,
7254 &.{try o.lowerType(inst_ty)},
7255 &.{ lhs, rhs },
7256 "",
7257 );
76617258 }
76627259
76637260 fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -7670,9 +7267,7 @@ pub const FuncGen = struct {
76707267 return self.wip.buildAggregate(try o.lowerType(inst_ty), &.{ ptr, len }, "");
76717268 }
76727269
7673 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7674 self.builder.setFastMath(want_fast_math);
7675
7270 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
76767271 const o = self.dg.object;
76777272 const mod = o.module;
76787273 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7681,15 +7276,15 @@ pub const FuncGen = struct {
76817276 const inst_ty = self.typeOfIndex(inst);
76827277 const scalar_ty = inst_ty.scalarType(mod);
76837278
7684 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.add, inst_ty, 2, .{ lhs, rhs });
7279 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.add, fast, inst_ty, 2, .{ lhs, rhs });
76857280 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"add nsw" else .@"add nuw", lhs, rhs, "");
76867281 }
76877282
76887283 fn airSafeArithmetic(
76897284 fg: *FuncGen,
76907285 inst: Air.Inst.Index,
7691 signed_intrinsic: []const u8,
7692 unsigned_intrinsic: []const u8,
7286 signed_intrinsic: Builder.Intrinsic,
7287 unsigned_intrinsic: Builder.Intrinsic,
76937288 ) !Builder.Value {
76947289 const o = fg.dg.object;
76957290 const mod = o.module;
......@@ -7699,46 +7294,35 @@ pub const FuncGen = struct {
76997294 const rhs = try fg.resolveInst(bin_op.rhs);
77007295 const inst_ty = fg.typeOfIndex(inst);
77017296 const scalar_ty = inst_ty.scalarType(mod);
7702 const is_scalar = scalar_ty.ip_index == inst_ty.ip_index;
77037297
7704 const intrinsic_name = switch (scalar_ty.isSignedInt(mod)) {
7705 true => signed_intrinsic,
7706 false => unsigned_intrinsic,
7707 };
7298 const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
77087299 const llvm_inst_ty = try o.lowerType(inst_ty);
7709 const llvm_ret_ty = try o.builder.structType(.normal, &.{
7710 llvm_inst_ty,
7711 try llvm_inst_ty.changeScalar(.i1, &o.builder),
7712 });
7713 const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_inst_ty, llvm_inst_ty }, .normal);
7714 const llvm_fn = try fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty});
7715 const result_struct = (try fg.wip.unimplemented(llvm_ret_ty, "")).finish(fg.builder.buildCallOld(
7716 llvm_fn_ty.toLlvm(&o.builder),
7717 llvm_fn,
7718 &[_]*llvm.Value{ lhs.toLlvm(&fg.wip), rhs.toLlvm(&fg.wip) },
7719 2,
7720 .Fast,
7721 .Auto,
7722 "",
7723 ), &fg.wip);
7724 const overflow_bit = try fg.wip.extractValue(result_struct, &.{1}, "");
7725 const scalar_overflow_bit = switch (is_scalar) {
7726 true => overflow_bit,
7727 false => (try fg.wip.unimplemented(.i1, "")).finish(
7728 fg.builder.buildOrReduce(overflow_bit.toLlvm(&fg.wip)),
7729 &fg.wip,
7730 ),
7731 };
7300 const results =
7301 try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, "");
7302
7303 const overflow_bits = try fg.wip.extractValue(results, &.{1}, "");
7304 const overflow_bits_ty = overflow_bits.typeOfWip(&fg.wip);
7305 const overflow_bit = if (overflow_bits_ty.isVector(&o.builder))
7306 try fg.wip.callIntrinsic(
7307 .normal,
7308 .none,
7309 .@"vector.reduce.or",
7310 &.{overflow_bits_ty},
7311 &.{overflow_bits},
7312 "",
7313 )
7314 else
7315 overflow_bits;
77327316
77337317 const fail_block = try fg.wip.block(1, "OverflowFail");
77347318 const ok_block = try fg.wip.block(1, "OverflowOk");
7735 _ = try fg.wip.brCond(scalar_overflow_bit, fail_block, ok_block);
7319 _ = try fg.wip.brCond(overflow_bit, fail_block, ok_block);
77367320
77377321 fg.wip.cursor = .{ .block = fail_block };
77387322 try fg.buildSimplePanic(.integer_overflow);
77397323
77407324 fg.wip.cursor = .{ .block = ok_block };
7741 return fg.wip.extractValue(result_struct, &.{0}, "");
7325 return fg.wip.extractValue(results, &.{0}, "");
77427326 }
77437327
77447328 fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -7759,15 +7343,17 @@ pub const FuncGen = struct {
77597343 const scalar_ty = inst_ty.scalarType(mod);
77607344
77617345 if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});
7762 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
7763 .@"llvm.sadd.sat."
7764 else
7765 .@"llvm.uadd.sat.", lhs, rhs, "");
7346 return self.wip.callIntrinsic(
7347 .normal,
7348 .none,
7349 if (scalar_ty.isSignedInt(mod)) .@"sadd.sat" else .@"uadd.sat",
7350 &.{try o.lowerType(inst_ty)},
7351 &.{ lhs, rhs },
7352 "",
7353 );
77667354 }
77677355
7768 fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7769 self.builder.setFastMath(want_fast_math);
7770
7356 fn airSub(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
77717357 const o = self.dg.object;
77727358 const mod = o.module;
77737359 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7776,7 +7362,7 @@ pub const FuncGen = struct {
77767362 const inst_ty = self.typeOfIndex(inst);
77777363 const scalar_ty = inst_ty.scalarType(mod);
77787364
7779 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.sub, inst_ty, 2, .{ lhs, rhs });
7365 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.sub, fast, inst_ty, 2, .{ lhs, rhs });
77807366 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"sub nsw" else .@"sub nuw", lhs, rhs, "");
77817367 }
77827368
......@@ -7798,15 +7384,17 @@ pub const FuncGen = struct {
77987384 const scalar_ty = inst_ty.scalarType(mod);
77997385
78007386 if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});
7801 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
7802 .@"llvm.ssub.sat."
7803 else
7804 .@"llvm.usub.sat.", lhs, rhs, "");
7387 return self.wip.callIntrinsic(
7388 .normal,
7389 .none,
7390 if (scalar_ty.isSignedInt(mod)) .@"ssub.sat" else .@"usub.sat",
7391 &.{try o.lowerType(inst_ty)},
7392 &.{ lhs, rhs },
7393 "",
7394 );
78057395 }
78067396
7807 fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7808 self.builder.setFastMath(want_fast_math);
7809
7397 fn airMul(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
78107398 const o = self.dg.object;
78117399 const mod = o.module;
78127400 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7815,7 +7403,7 @@ pub const FuncGen = struct {
78157403 const inst_ty = self.typeOfIndex(inst);
78167404 const scalar_ty = inst_ty.scalarType(mod);
78177405
7818 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.mul, inst_ty, 2, .{ lhs, rhs });
7406 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.mul, fast, inst_ty, 2, .{ lhs, rhs });
78197407 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"mul nsw" else .@"mul nuw", lhs, rhs, "");
78207408 }
78217409
......@@ -7837,26 +7425,26 @@ pub const FuncGen = struct {
78377425 const scalar_ty = inst_ty.scalarType(mod);
78387426
78397427 if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});
7840 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
7841 .@"llvm.smul.fix.sat."
7842 else
7843 .@"llvm.umul.fix.sat.", lhs, rhs, "");
7428 return self.wip.callIntrinsic(
7429 .normal,
7430 .none,
7431 if (scalar_ty.isSignedInt(mod)) .@"smul.fix.sat" else .@"umul.fix.sat",
7432 &.{try o.lowerType(inst_ty)},
7433 &.{ lhs, rhs, try o.builder.intValue(.i32, 0) },
7434 "",
7435 );
78447436 }
78457437
7846 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7847 self.builder.setFastMath(want_fast_math);
7848
7438 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
78497439 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
78507440 const lhs = try self.resolveInst(bin_op.lhs);
78517441 const rhs = try self.resolveInst(bin_op.rhs);
78527442 const inst_ty = self.typeOfIndex(inst);
78537443
7854 return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7444 return self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
78557445 }
78567446
7857 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7858 self.builder.setFastMath(want_fast_math);
7859
7447 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
78607448 const o = self.dg.object;
78617449 const mod = o.module;
78627450 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7866,15 +7454,13 @@ pub const FuncGen = struct {
78667454 const scalar_ty = inst_ty.scalarType(mod);
78677455
78687456 if (scalar_ty.isRuntimeFloat()) {
7869 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7870 return self.buildFloatOp(.trunc, inst_ty, 1, .{result});
7457 const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7458 return self.buildFloatOp(.trunc, fast, inst_ty, 1, .{result});
78717459 }
78727460 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .sdiv else .udiv, lhs, rhs, "");
78737461 }
78747462
7875 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7876 self.builder.setFastMath(want_fast_math);
7877
7463 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
78787464 const o = self.dg.object;
78797465 const mod = o.module;
78807466 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7884,8 +7470,8 @@ pub const FuncGen = struct {
78847470 const scalar_ty = inst_ty.scalarType(mod);
78857471
78867472 if (scalar_ty.isRuntimeFloat()) {
7887 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7888 return self.buildFloatOp(.floor, inst_ty, 1, .{result});
7473 const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7474 return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result});
78897475 }
78907476 if (scalar_ty.isSignedInt(mod)) {
78917477 const inst_llvm_ty = try o.lowerType(inst_ty);
......@@ -7900,15 +7486,13 @@ pub const FuncGen = struct {
79007486 const div_sign_mask = try self.wip.bin(.ashr, div_sign, bit_size_minus_one, "");
79017487 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
79027488 const rem_nonzero = try self.wip.icmp(.ne, rem, zero, "");
7903 const correction = try self.wip.select(rem_nonzero, div_sign_mask, zero, "");
7489 const correction = try self.wip.select(.normal, rem_nonzero, div_sign_mask, zero, "");
79047490 return self.wip.bin(.@"add nsw", div, correction, "");
79057491 }
79067492 return self.wip.bin(.udiv, lhs, rhs, "");
79077493 }
79087494
7909 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7910 self.builder.setFastMath(want_fast_math);
7911
7495 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
79127496 const o = self.dg.object;
79137497 const mod = o.module;
79147498 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7917,16 +7501,16 @@ pub const FuncGen = struct {
79177501 const inst_ty = self.typeOfIndex(inst);
79187502 const scalar_ty = inst_ty.scalarType(mod);
79197503
7920 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7921 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
7922 .@"sdiv exact"
7923 else
7924 .@"udiv exact", lhs, rhs, "");
7504 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7505 return self.wip.bin(
7506 if (scalar_ty.isSignedInt(mod)) .@"sdiv exact" else .@"udiv exact",
7507 lhs,
7508 rhs,
7509 "",
7510 );
79257511 }
79267512
7927 fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7928 self.builder.setFastMath(want_fast_math);
7929
7513 fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
79307514 const o = self.dg.object;
79317515 const mod = o.module;
79327516 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7935,16 +7519,15 @@ pub const FuncGen = struct {
79357519 const inst_ty = self.typeOfIndex(inst);
79367520 const scalar_ty = inst_ty.scalarType(mod);
79377521
7938 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });
7522 if (scalar_ty.isRuntimeFloat())
7523 return self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs });
79397524 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
79407525 .srem
79417526 else
79427527 .urem, lhs, rhs, "");
79437528 }
79447529
7945 fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7946 self.builder.setFastMath(want_fast_math);
7947
7530 fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
79487531 const o = self.dg.object;
79497532 const mod = o.module;
79507533 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7955,12 +7538,12 @@ pub const FuncGen = struct {
79557538 const scalar_ty = inst_ty.scalarType(mod);
79567539
79577540 if (scalar_ty.isRuntimeFloat()) {
7958 const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });
7959 const b = try self.buildFloatOp(.add, inst_ty, 2, .{ a, rhs });
7960 const c = try self.buildFloatOp(.fmod, inst_ty, 2, .{ b, rhs });
7541 const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs });
7542 const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs });
7543 const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs });
79617544 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
7962 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero });
7963 return self.wip.select(ltz, c, a, "");
7545 const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero });
7546 return self.wip.select(fast, ltz, c, a, "");
79647547 }
79657548 if (scalar_ty.isSignedInt(mod)) {
79667549 const bit_size_minus_one = try o.builder.splatValue(inst_llvm_ty, try o.builder.intConst(
......@@ -7974,7 +7557,7 @@ pub const FuncGen = struct {
79747557 const rhs_masked = try self.wip.bin(.@"and", rhs, div_sign_mask, "");
79757558 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
79767559 const rem_nonzero = try self.wip.icmp(.ne, rem, zero, "");
7977 const correction = try self.wip.select(rem_nonzero, rhs_masked, zero, "");
7560 const correction = try self.wip.select(.normal, rem_nonzero, rhs_masked, zero, "");
79787561 return self.wip.bin(.@"add nsw", rem, correction, "");
79797562 }
79807563 return self.wip.bin(.urem, lhs, rhs, "");
......@@ -8028,8 +7611,8 @@ pub const FuncGen = struct {
80287611 fn airOverflow(
80297612 self: *FuncGen,
80307613 inst: Air.Inst.Index,
8031 signed_intrinsic: []const u8,
8032 unsigned_intrinsic: []const u8,
7614 signed_intrinsic: Builder.Intrinsic,
7615 unsigned_intrinsic: Builder.Intrinsic,
80337616 ) !Builder.Value {
80347617 const o = self.dg.object;
80357618 const mod = o.module;
......@@ -8041,48 +7624,30 @@ pub const FuncGen = struct {
80417624
80427625 const lhs_ty = self.typeOf(extra.lhs);
80437626 const scalar_ty = lhs_ty.scalarType(mod);
8044 const dest_ty = self.typeOfIndex(inst);
8045
8046 const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
7627 const inst_ty = self.typeOfIndex(inst);
80477628
8048 const llvm_dest_ty = try o.lowerType(dest_ty);
7629 const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
7630 const llvm_inst_ty = try o.lowerType(inst_ty);
80497631 const llvm_lhs_ty = try o.lowerType(lhs_ty);
7632 const results =
7633 try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, "");
80507634
8051 const llvm_fn = try self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty});
8052 const llvm_ret_ty = try o.builder.structType(
8053 .normal,
8054 &.{ llvm_lhs_ty, try llvm_lhs_ty.changeScalar(.i1, &o.builder) },
8055 );
8056 const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_lhs_ty, llvm_lhs_ty }, .normal);
8057 const result_struct = (try self.wip.unimplemented(llvm_ret_ty, "")).finish(
8058 self.builder.buildCallOld(
8059 llvm_fn_ty.toLlvm(&o.builder),
8060 llvm_fn,
8061 &[_]*llvm.Value{ lhs.toLlvm(&self.wip), rhs.toLlvm(&self.wip) },
8062 2,
8063 .Fast,
8064 .Auto,
8065 "",
8066 ),
8067 &self.wip,
8068 );
7635 const result_val = try self.wip.extractValue(results, &.{0}, "");
7636 const overflow_bit = try self.wip.extractValue(results, &.{1}, "");
80697637
8070 const result = try self.wip.extractValue(result_struct, &.{0}, "");
8071 const overflow_bit = try self.wip.extractValue(result_struct, &.{1}, "");
7638 const result_index = llvmField(inst_ty, 0, mod).?.index;
7639 const overflow_index = llvmField(inst_ty, 1, mod).?.index;
80727640
8073 const result_index = llvmField(dest_ty, 0, mod).?.index;
8074 const overflow_index = llvmField(dest_ty, 1, mod).?.index;
8075
8076 if (isByRef(dest_ty, mod)) {
8077 const result_alignment = Builder.Alignment.fromByteUnits(dest_ty.abiAlignment(mod));
8078 const alloca_inst = try self.buildAlloca(llvm_dest_ty, result_alignment);
7641 if (isByRef(inst_ty, mod)) {
7642 const result_alignment = Builder.Alignment.fromByteUnits(inst_ty.abiAlignment(mod));
7643 const alloca_inst = try self.buildAlloca(llvm_inst_ty, result_alignment);
80797644 {
8080 const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, result_index, "");
8081 _ = try self.wip.store(.normal, result, field_ptr, result_alignment);
7645 const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, result_index, "");
7646 _ = try self.wip.store(.normal, result_val, field_ptr, result_alignment);
80827647 }
80837648 {
80847649 const overflow_alignment = comptime Builder.Alignment.fromByteUnits(1);
8085 const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, overflow_index, "");
7650 const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, overflow_index, "");
80867651 _ = try self.wip.store(.normal, overflow_bit, field_ptr, overflow_alignment);
80877652 }
80887653
......@@ -8090,9 +7655,9 @@ pub const FuncGen = struct {
80907655 }
80917656
80927657 var fields: [2]Builder.Value = undefined;
8093 fields[result_index] = result;
7658 fields[result_index] = result_val;
80947659 fields[overflow_index] = overflow_bit;
8095 return self.wip.buildAggregate(llvm_dest_ty, &fields, "");
7660 return self.wip.buildAggregate(llvm_inst_ty, &fields, "");
80967661 }
80977662
80987663 fn buildElementwiseCall(
......@@ -8138,30 +7703,20 @@ pub const FuncGen = struct {
81387703 if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) {
81397704 .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function,
81407705 .function => |function| function,
8141 else => unreachable,
8142 };
8143
8144 const fn_type = try o.builder.fnType(return_type, param_types, .normal);
8145 const f = o.llvm_module.addFunction(fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));
8146
8147 var global = Builder.Global{
8148 .type = fn_type,
8149 .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
8150 };
8151 var function = Builder.Function{
8152 .global = @enumFromInt(o.builder.globals.count()),
7706 .variable, .replaced => unreachable,
81537707 };
8154
8155 try o.builder.llvm.globals.append(self.gpa, f);
8156 _ = try o.builder.addGlobal(fn_name, global);
8157 try o.builder.functions.append(self.gpa, function);
8158 return global.kind.function;
7708 return o.builder.addFunction(
7709 try o.builder.fnType(return_type, param_types, .normal),
7710 fn_name,
7711 toLlvmAddressSpace(.generic, o.module.getTarget()),
7712 );
81597713 }
81607714
81617715 /// Creates a floating point comparison by lowering to the appropriate
81627716 /// hardware instruction or softfloat routine for the target
81637717 fn buildFloatCmp(
81647718 self: *FuncGen,
7719 fast: Builder.FastMathKind,
81657720 pred: math.CompareOperator,
81667721 ty: Type,
81677722 params: [2]Builder.Value,
......@@ -8181,7 +7736,7 @@ pub const FuncGen = struct {
81817736 .gt => .ogt,
81827737 .gte => .oge,
81837738 };
8184 return self.wip.fcmp(cond, params[0], params[1], "");
7739 return self.wip.fcmp(fast, cond, params[0], params[1], "");
81857740 }
81867741
81877742 const float_bits = scalar_ty.floatBits(target);
......@@ -8196,11 +7751,7 @@ pub const FuncGen = struct {
81967751 };
81977752 const fn_name = try o.builder.fmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev });
81987753
8199 const libc_fn = try self.getLibcFunction(
8200 fn_name,
8201 ([1]Builder.Type{scalar_llvm_ty} ** 2)[0..],
8202 .i32,
8203 );
7754 const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32);
82047755
82057756 const zero = try o.builder.intConst(.i32, 0);
82067757 const int_cond: Builder.IntegerCondition = switch (pred) {
......@@ -8272,6 +7823,7 @@ pub const FuncGen = struct {
82727823 fn buildFloatOp(
82737824 self: *FuncGen,
82747825 comptime op: FloatOp,
7826 fast: Builder.FastMathKind,
82757827 ty: Type,
82767828 comptime params_len: usize,
82777829 params: [params_len]Builder.Value,
......@@ -8285,27 +7837,59 @@ pub const FuncGen = struct {
82857837 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
82867838 // Some operations are dedicated LLVM instructions, not available as intrinsics
82877839 .neg => return self.wip.un(.fneg, params[0], ""),
8288 .add => return self.wip.bin(.fadd, params[0], params[1], ""),
8289 .sub => return self.wip.bin(.fsub, params[0], params[1], ""),
8290 .mul => return self.wip.bin(.fmul, params[0], params[1], ""),
8291 .div => return self.wip.bin(.fdiv, params[0], params[1], ""),
8292 .fmod => return self.wip.bin(.frem, params[0], params[1], ""),
8293 .fmax => return self.wip.bin(.@"llvm.maxnum.", params[0], params[1], ""),
8294 .fmin => return self.wip.bin(.@"llvm.minnum.", params[0], params[1], ""),
8295 .ceil => return self.wip.un(.@"llvm.ceil.", params[0], ""),
8296 .cos => return self.wip.un(.@"llvm.cos.", params[0], ""),
8297 .exp => return self.wip.un(.@"llvm.exp.", params[0], ""),
8298 .exp2 => return self.wip.un(.@"llvm.exp2.", params[0], ""),
8299 .fabs => return self.wip.un(.@"llvm.fabs.", params[0], ""),
8300 .floor => return self.wip.un(.@"llvm.floor.", params[0], ""),
8301 .log => return self.wip.un(.@"llvm.log.", params[0], ""),
8302 .log10 => return self.wip.un(.@"llvm.log10.", params[0], ""),
8303 .log2 => return self.wip.un(.@"llvm.log2.", params[0], ""),
8304 .round => return self.wip.un(.@"llvm.round.", params[0], ""),
8305 .sin => return self.wip.un(.@"llvm.sin.", params[0], ""),
8306 .sqrt => return self.wip.un(.@"llvm.sqrt.", params[0], ""),
8307 .trunc => return self.wip.un(.@"llvm.trunc.", params[0], ""),
8308 .fma => return self.wip.fusedMultiplyAdd(params[0], params[1], params[2]),
7840 .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) {
7841 .normal => switch (op) {
7842 .add => .fadd,
7843 .sub => .fsub,
7844 .mul => .fmul,
7845 .div => .fdiv,
7846 .fmod => .frem,
7847 else => unreachable,
7848 },
7849 .fast => switch (op) {
7850 .add => .@"fadd fast",
7851 .sub => .@"fsub fast",
7852 .mul => .@"fmul fast",
7853 .div => .@"fdiv fast",
7854 .fmod => .@"frem fast",
7855 else => unreachable,
7856 },
7857 }, params[0], params[1], ""),
7858 .fmax,
7859 .fmin,
7860 .ceil,
7861 .cos,
7862 .exp,
7863 .exp2,
7864 .fabs,
7865 .floor,
7866 .log,
7867 .log10,
7868 .log2,
7869 .round,
7870 .sin,
7871 .sqrt,
7872 .trunc,
7873 .fma,
7874 => return self.wip.callIntrinsic(fast, .none, switch (op) {
7875 .fmax => .maxnum,
7876 .fmin => .minnum,
7877 .ceil => .ceil,
7878 .cos => .cos,
7879 .exp => .exp,
7880 .exp2 => .exp2,
7881 .fabs => .fabs,
7882 .floor => .floor,
7883 .log => .log,
7884 .log10 => .log10,
7885 .log2 => .log2,
7886 .round => .round,
7887 .sin => .sin,
7888 .sqrt => .sqrt,
7889 .trunc => .trunc,
7890 .fma => .fma,
7891 else => unreachable,
7892 }, &.{llvm_ty}, &params, ""),
83097893 .tan => unreachable,
83107894 };
83117895
......@@ -8362,7 +7946,7 @@ pub const FuncGen = struct {
83627946 }
83637947
83647948 return self.wip.call(
8365 .normal,
7949 fast.toCallKind(),
83667950 .ccc,
83677951 .none,
83687952 libc_fn.typeOf(&o.builder),
......@@ -8381,7 +7965,7 @@ pub const FuncGen = struct {
83817965 const addend = try self.resolveInst(pl_op.operand);
83827966
83837967 const ty = self.typeOfIndex(inst);
8384 return self.buildFloatOp(.fma, ty, 3, .{ mulend1, mulend2, addend });
7968 return self.buildFloatOp(.fma, .normal, ty, 3, .{ mulend1, mulend2, addend });
83857969 }
83867970
83877971 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -8499,28 +8083,32 @@ pub const FuncGen = struct {
84998083
85008084 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
85018085
8502 const result = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(mod))
8503 .@"llvm.sshl.sat."
8504 else
8505 .@"llvm.ushl.sat.", lhs, casted_rhs, "");
8086 const llvm_lhs_ty = try o.lowerType(lhs_ty);
8087 const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder);
8088 const result = try self.wip.callIntrinsic(
8089 .normal,
8090 .none,
8091 if (lhs_scalar_ty.isSignedInt(mod)) .@"sshl.sat" else .@"ushl.sat",
8092 &.{llvm_lhs_ty},
8093 &.{ lhs, casted_rhs },
8094 "",
8095 );
85068096
85078097 // LLVM langref says "If b is (statically or dynamically) equal to or
85088098 // larger than the integer bit width of the arguments, the result is a
85098099 // poison value."
85108100 // However Zig semantics says that saturating shift left can never produce
85118101 // undefined; instead it saturates.
8512 const lhs_llvm_ty = try o.lowerType(lhs_ty);
8513 const lhs_scalar_llvm_ty = lhs_llvm_ty.scalarType(&o.builder);
85148102 const bits = try o.builder.splatValue(
8515 lhs_llvm_ty,
8516 try o.builder.intConst(lhs_scalar_llvm_ty, lhs_bits),
8103 llvm_lhs_ty,
8104 try o.builder.intConst(llvm_lhs_scalar_ty, lhs_bits),
85178105 );
85188106 const lhs_max = try o.builder.splatValue(
8519 lhs_llvm_ty,
8520 try o.builder.intConst(lhs_scalar_llvm_ty, -1),
8107 llvm_lhs_ty,
8108 try o.builder.intConst(llvm_lhs_scalar_ty, -1),
85218109 );
85228110 const in_range = try self.wip.icmp(.ult, rhs, bits, "");
8523 return self.wip.select(in_range, result, lhs_max, "");
8111 return self.wip.select(.normal, in_range, result, lhs_max, "");
85248112 }
85258113
85268114 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value {
......@@ -8873,21 +8461,14 @@ pub const FuncGen = struct {
88738461 // Even if safety is disabled, we still emit a memset to undefined since it conveys
88748462 // extra information to LLVM. However, safety makes the difference between using
88758463 // 0xaa or actual undefined for the fill byte.
8876 const fill_byte = if (safety)
8877 try o.builder.intConst(.i8, 0xaa)
8878 else
8879 try o.builder.undefConst(.i8);
8880 const operand_size = operand_ty.abiSize(mod);
8881 const usize_ty = try o.lowerType(Type.usize);
8882 const len = try o.builder.intValue(usize_ty, operand_size);
8883 const dest_ptr_align = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));
8884 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet(
8885 dest_ptr.toLlvm(&self.wip),
8886 fill_byte.toLlvm(&o.builder),
8887 len.toLlvm(&self.wip),
8888 @intCast(dest_ptr_align.toByteUnits() orelse 0),
8889 ptr_ty.isVolatilePtr(mod),
8890 ), &self.wip);
8464 const len = try o.builder.intValue(try o.lowerType(Type.usize), operand_ty.abiSize(mod));
8465 _ = try self.wip.callMemSet(
8466 dest_ptr,
8467 Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)),
8468 if (safety) try o.builder.intValue(.i8, 0xaa) else try o.builder.undefValue(.i8),
8469 len,
8470 if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal,
8471 );
88918472 if (safety and mod.comp.bin_file.options.valgrind) {
88928473 try self.valgrindMarkUndef(dest_ptr, len);
88938474 }
......@@ -8940,90 +8521,38 @@ pub const FuncGen = struct {
89408521
89418522 fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
89428523 _ = inst;
8943 const o = self.dg.object;
8944 const llvm_fn = try self.getIntrinsic("llvm.trap", &.{});
8945 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
8946 (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder),
8947 llvm_fn,
8948 undefined,
8949 0,
8950 .Cold,
8951 .Auto,
8952 "",
8953 ), &self.wip);
8524 _ = try self.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, "");
89548525 _ = try self.wip.@"unreachable"();
89558526 return .none;
89568527 }
89578528
89588529 fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
89598530 _ = inst;
8960 const o = self.dg.object;
8961 const llvm_fn = try self.getIntrinsic("llvm.debugtrap", &.{});
8962 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
8963 (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder),
8964 llvm_fn,
8965 undefined,
8966 0,
8967 .C,
8968 .Auto,
8969 "",
8970 ), &self.wip);
8531 _ = try self.wip.callIntrinsic(.normal, .none, .debugtrap, &.{}, &.{}, "");
89718532 return .none;
89728533 }
89738534
89748535 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
89758536 _ = inst;
89768537 const o = self.dg.object;
8977 const mod = o.module;
89788538 const llvm_usize = try o.lowerType(Type.usize);
8979 const target = mod.getTarget();
8980 if (!target_util.supportsReturnAddress(target)) {
8539 if (!target_util.supportsReturnAddress(o.module.getTarget())) {
89818540 // https://github.com/ziglang/zig/issues/11946
89828541 return o.builder.intValue(llvm_usize, 0);
89838542 }
8984
8985 const llvm_fn = try self.getIntrinsic("llvm.returnaddress", &.{});
8986 const params = [_]*llvm.Value{
8987 (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder),
8988 };
8989 const ptr_val = (try self.wip.unimplemented(.ptr, "")).finish(self.builder.buildCallOld(
8990 (try o.builder.fnType(.ptr, &.{.i32}, .normal)).toLlvm(&o.builder),
8991 llvm_fn,
8992 &params,
8993 params.len,
8994 .Fast,
8995 .Auto,
8996 "",
8997 ), &self.wip);
8998 return self.wip.cast(.ptrtoint, ptr_val, llvm_usize, "");
8543 const result = try self.wip.callIntrinsic(.normal, .none, .returnaddress, &.{}, &.{
8544 try o.builder.intValue(.i32, 0),
8545 }, "");
8546 return self.wip.cast(.ptrtoint, result, llvm_usize, "");
89998547 }
90008548
90018549 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
90028550 _ = inst;
90038551 const o = self.dg.object;
9004 const llvm_fn_name = "llvm.frameaddress.p0";
9005 const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
9006 const fn_type = try o.builder.fnType(.ptr, &.{.i32}, .normal);
9007 break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder));
9008 };
9009 const llvm_fn_ty = try o.builder.fnType(.ptr, &.{.i32}, .normal);
9010
9011 const params = [_]*llvm.Value{
9012 (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder),
9013 };
9014 const ptr_val = (try self.wip.unimplemented(llvm_fn_ty.functionReturn(&o.builder), "")).finish(
9015 self.builder.buildCallOld(
9016 llvm_fn_ty.toLlvm(&o.builder),
9017 llvm_fn,
9018 &params,
9019 params.len,
9020 .Fast,
9021 .Auto,
9022 "",
9023 ),
9024 &self.wip,
9025 );
9026 return self.wip.cast(.ptrtoint, ptr_val, try o.lowerType(Type.usize), "");
8552 const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{
8553 try o.builder.intValue(.i32, 0),
8554 }, "");
8555 return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), "");
90278556 }
90288557
90298558 fn airFence(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -9033,15 +8562,20 @@ pub const FuncGen = struct {
90338562 return .none;
90348563 }
90358564
9036 fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !Builder.Value {
8565 fn airCmpxchg(
8566 self: *FuncGen,
8567 inst: Air.Inst.Index,
8568 kind: Builder.Function.Instruction.CmpXchg.Kind,
8569 ) !Builder.Value {
90378570 const o = self.dg.object;
90388571 const mod = o.module;
90398572 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
90408573 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
90418574 const ptr = try self.resolveInst(extra.ptr);
8575 const ptr_ty = self.typeOf(extra.ptr);
90428576 var expected_value = try self.resolveInst(extra.expected_value);
90438577 var new_value = try self.resolveInst(extra.new_value);
9044 const operand_ty = self.typeOf(extra.ptr).childType(mod);
8578 const operand_ty = ptr_ty.childType(mod);
90458579 const llvm_operand_ty = try o.lowerType(operand_ty);
90468580 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, false);
90478581 if (llvm_abi_ty != .none) {
......@@ -9052,22 +8586,18 @@ pub const FuncGen = struct {
90528586 new_value = try self.wip.conv(signedness, new_value, llvm_abi_ty, "");
90538587 }
90548588
9055 const llvm_result_ty = try o.builder.structType(.normal, &.{
9056 if (llvm_abi_ty != .none) llvm_abi_ty else llvm_operand_ty,
9057 .i1,
9058 });
9059 const result = (try self.wip.unimplemented(llvm_result_ty, "")).finish(
9060 self.builder.buildAtomicCmpXchg(
9061 ptr.toLlvm(&self.wip),
9062 expected_value.toLlvm(&self.wip),
9063 new_value.toLlvm(&self.wip),
9064 @enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.successOrder()))),
9065 @enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.failureOrder()))),
9066 llvm.Bool.fromBool(self.sync_scope == .singlethread),
9067 ),
9068 &self.wip,
8589 const result = try self.wip.cmpxchg(
8590 kind,
8591 if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal,
8592 ptr,
8593 expected_value,
8594 new_value,
8595 self.sync_scope,
8596 toLlvmAtomicOrdering(extra.successOrder()),
8597 toLlvmAtomicOrdering(extra.failureOrder()),
8598 Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)),
8599 "",
90698600 );
9070 result.toLlvm(&self.wip).setWeak(llvm.Bool.fromBool(is_weak));
90718601
90728602 const optional_ty = self.typeOfIndex(inst);
90738603
......@@ -9077,7 +8607,7 @@ pub const FuncGen = struct {
90778607
90788608 if (optional_ty.optionalReprIsPayload(mod)) {
90798609 const zero = try o.builder.zeroInitValue(payload.typeOfWip(&self.wip));
9080 return self.wip.select(success_bit, zero, payload, "");
8610 return self.wip.select(.normal, success_bit, zero, payload, "");
90818611 }
90828612
90838613 comptime assert(optional_layout_version == 3);
......@@ -9099,63 +8629,54 @@ pub const FuncGen = struct {
90998629 const is_float = operand_ty.isRuntimeFloat();
91008630 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
91018631 const ordering = toLlvmAtomicOrdering(extra.ordering());
9102 const single_threaded = llvm.Bool.fromBool(self.sync_scope == .singlethread);
9103 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .Xchg);
8632 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .xchg);
91048633 const llvm_operand_ty = try o.lowerType(operand_ty);
8634
8635 const access_kind: Builder.MemoryAccessKind =
8636 if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal;
8637 const ptr_alignment = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));
8638
91058639 if (llvm_abi_ty != .none) {
91068640 // operand needs widening and truncating or bitcasting.
9107 const casted_operand = try self.wip.cast(
9108 if (is_float) .bitcast else if (is_signed_int) .sext else .zext,
9109 @enumFromInt(@intFromEnum(operand)),
9110 llvm_abi_ty,
9111 "",
9112 );
9113
9114 const uncasted_result = (try self.wip.unimplemented(llvm_abi_ty, "")).finish(
9115 self.builder.buildAtomicRmw(
9116 op,
9117 ptr.toLlvm(&self.wip),
9118 casted_operand.toLlvm(&self.wip),
9119 @enumFromInt(@intFromEnum(ordering)),
9120 single_threaded,
8641 return self.wip.cast(if (is_float) .bitcast else .trunc, try self.wip.atomicrmw(
8642 access_kind,
8643 op,
8644 ptr,
8645 try self.wip.cast(
8646 if (is_float) .bitcast else if (is_signed_int) .sext else .zext,
8647 operand,
8648 llvm_abi_ty,
8649 "",
91218650 ),
9122 &self.wip,
9123 );
9124
9125 if (is_float) {
9126 return self.wip.cast(.bitcast, uncasted_result, llvm_operand_ty, "");
9127 } else {
9128 return self.wip.cast(.trunc, uncasted_result, llvm_operand_ty, "");
9129 }
8651 self.sync_scope,
8652 ordering,
8653 ptr_alignment,
8654 "",
8655 ), llvm_operand_ty, "");
91308656 }
91318657
9132 if (!llvm_operand_ty.isPointer(&o.builder)) {
9133 return (try self.wip.unimplemented(llvm_operand_ty, "")).finish(
9134 self.builder.buildAtomicRmw(
9135 op,
9136 ptr.toLlvm(&self.wip),
9137 operand.toLlvm(&self.wip),
9138 @enumFromInt(@intFromEnum(ordering)),
9139 single_threaded,
9140 ),
9141 &self.wip,
9142 );
9143 }
8658 if (!llvm_operand_ty.isPointer(&o.builder)) return self.wip.atomicrmw(
8659 access_kind,
8660 op,
8661 ptr,
8662 operand,
8663 self.sync_scope,
8664 ordering,
8665 ptr_alignment,
8666 "",
8667 );
91448668
91458669 // It's a pointer but we need to treat it as an int.
9146 const llvm_usize = try o.lowerType(Type.usize);
9147 const casted_operand = try self.wip.cast(.ptrtoint, operand, llvm_usize, "");
9148 const uncasted_result = (try self.wip.unimplemented(llvm_usize, "")).finish(
9149 self.builder.buildAtomicRmw(
9150 op,
9151 ptr.toLlvm(&self.wip),
9152 casted_operand.toLlvm(&self.wip),
9153 @enumFromInt(@intFromEnum(ordering)),
9154 single_threaded,
9155 ),
9156 &self.wip,
9157 );
9158 return self.wip.cast(.inttoptr, uncasted_result, llvm_operand_ty, "");
8670 return self.wip.cast(.inttoptr, try self.wip.atomicrmw(
8671 access_kind,
8672 op,
8673 ptr,
8674 try self.wip.cast(.ptrtoint, operand, try o.lowerType(Type.usize), ""),
8675 self.sync_scope,
8676 ordering,
8677 ptr_alignment,
8678 "",
8679 ), llvm_operand_ty, "");
91598680 }
91608681
91618682 fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -9172,16 +8693,14 @@ pub const FuncGen = struct {
91728693 const ptr_alignment = Builder.Alignment.fromByteUnits(
91738694 info.flags.alignment.toByteUnitsOptional() orelse info.child.toType().abiAlignment(mod),
91748695 );
9175 const ptr_kind: Builder.MemoryAccessKind = switch (info.flags.is_volatile) {
9176 false => .normal,
9177 true => .@"volatile",
9178 };
8696 const access_kind: Builder.MemoryAccessKind =
8697 if (info.flags.is_volatile) .@"volatile" else .normal;
91798698 const elem_llvm_ty = try o.lowerType(elem_ty);
91808699
91818700 if (llvm_abi_ty != .none) {
91828701 // operand needs widening and truncating
91838702 const loaded = try self.wip.loadAtomic(
9184 ptr_kind,
8703 access_kind,
91858704 llvm_abi_ty,
91868705 ptr,
91878706 self.sync_scope,
......@@ -9192,7 +8711,7 @@ pub const FuncGen = struct {
91928711 return self.wip.cast(.trunc, loaded, elem_llvm_ty, "");
91938712 }
91948713 return self.wip.loadAtomic(
9195 ptr_kind,
8714 access_kind,
91968715 elem_llvm_ty,
91978716 ptr,
91988717 self.sync_scope,
......@@ -9239,7 +8758,8 @@ pub const FuncGen = struct {
92398758 const elem_ty = self.typeOf(bin_op.rhs);
92408759 const dest_ptr_align = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));
92418760 const dest_ptr = try self.sliceOrArrayPtr(dest_slice, ptr_ty);
9242 const is_volatile = ptr_ty.isVolatilePtr(mod);
8761 const access_kind: Builder.MemoryAccessKind =
8762 if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal;
92438763
92448764 // Any WebAssembly runtime will trap when the destination pointer is out-of-bounds, regardless
92458765 // of the length. This means we need to emit a check where we skip the memset when the length
......@@ -9260,17 +8780,10 @@ pub const FuncGen = struct {
92608780 try o.builder.undefValue(.i8);
92618781 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
92628782 if (intrinsic_len0_traps) {
9263 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile);
8783 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind);
92648784 } else {
9265 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet(
9266 dest_ptr.toLlvm(&self.wip),
9267 fill_byte.toLlvm(&self.wip),
9268 len.toLlvm(&self.wip),
9269 @intCast(dest_ptr_align.toByteUnits() orelse 0),
9270 is_volatile,
9271 ), &self.wip);
8785 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
92728786 }
9273
92748787 if (safety and mod.comp.bin_file.options.valgrind) {
92758788 try self.valgrindMarkUndef(dest_ptr, len);
92768789 }
......@@ -9282,19 +8795,12 @@ pub const FuncGen = struct {
92828795 // repeating byte pattern of 0 bytes. In such case, the memset
92838796 // intrinsic can be used.
92848797 if (try elem_val.hasRepeatedByteRepr(elem_ty, mod)) |byte_val| {
9285 const fill_byte = try self.resolveValue(.{ .ty = Type.u8, .val = byte_val });
8798 const fill_byte = try o.builder.intValue(.i8, byte_val);
92868799 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
9287
92888800 if (intrinsic_len0_traps) {
9289 try self.safeWasmMemset(dest_ptr, fill_byte.toValue(), len, dest_ptr_align, is_volatile);
8801 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind);
92908802 } else {
9291 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet(
9292 dest_ptr.toLlvm(&self.wip),
9293 fill_byte.toLlvm(&o.builder),
9294 len.toLlvm(&self.wip),
9295 @intCast(dest_ptr_align.toByteUnits() orelse 0),
9296 is_volatile,
9297 ), &self.wip);
8803 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
92988804 }
92998805 return .none;
93008806 }
......@@ -9309,15 +8815,9 @@ pub const FuncGen = struct {
93098815 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
93108816
93118817 if (intrinsic_len0_traps) {
9312 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile);
8818 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind);
93138819 } else {
9314 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet(
9315 dest_ptr.toLlvm(&self.wip),
9316 fill_byte.toLlvm(&self.wip),
9317 len.toLlvm(&self.wip),
9318 @intCast(dest_ptr_align.toByteUnits() orelse 0),
9319 is_volatile,
9320 ), &self.wip);
8820 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
93218821 }
93228822 return .none;
93238823 }
......@@ -9343,10 +8843,10 @@ pub const FuncGen = struct {
93438843 const body_block = try self.wip.block(1, "InlineMemsetBody");
93448844 const end_block = try self.wip.block(1, "InlineMemsetEnd");
93458845
9346 const usize_ty = try o.lowerType(Type.usize);
8846 const llvm_usize_ty = try o.lowerType(Type.usize);
93478847 const len = switch (ptr_ty.ptrSize(mod)) {
93488848 .Slice => try self.wip.extractValue(dest_slice, &.{1}, ""),
9349 .One => try o.builder.intValue(usize_ty, ptr_ty.childType(mod).arrayLen(mod)),
8849 .One => try o.builder.intValue(llvm_usize_ty, ptr_ty.childType(mod).arrayLen(mod)),
93508850 .Many, .C => unreachable,
93518851 };
93528852 const elem_llvm_ty = try o.lowerType(elem_ty);
......@@ -9359,25 +8859,22 @@ pub const FuncGen = struct {
93598859 _ = try self.wip.brCond(end, body_block, end_block);
93608860
93618861 self.wip.cursor = .{ .block = body_block };
9362 const elem_abi_alignment = elem_ty.abiAlignment(mod);
9363 const it_ptr_alignment = Builder.Alignment.fromByteUnits(
9364 @min(elem_abi_alignment, dest_ptr_align.toByteUnits() orelse std.math.maxInt(u64)),
8862 const elem_abi_align = elem_ty.abiAlignment(mod);
8863 const it_ptr_align = Builder.Alignment.fromByteUnits(
8864 @min(elem_abi_align, dest_ptr_align.toByteUnits() orelse std.math.maxInt(u64)),
93658865 );
93668866 if (isByRef(elem_ty, mod)) {
9367 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy(
9368 it_ptr.toValue().toLlvm(&self.wip),
9369 @intCast(it_ptr_alignment.toByteUnits() orelse 0),
9370 value.toLlvm(&self.wip),
9371 elem_abi_alignment,
9372 (try o.builder.intConst(usize_ty, elem_abi_size)).toLlvm(&o.builder),
9373 is_volatile,
9374 ), &self.wip);
9375 } else _ = try self.wip.store(switch (is_volatile) {
9376 false => .normal,
9377 true => .@"volatile",
9378 }, value, it_ptr.toValue(), it_ptr_alignment);
8867 _ = try self.wip.callMemCpy(
8868 it_ptr.toValue(),
8869 it_ptr_align,
8870 value,
8871 Builder.Alignment.fromByteUnits(elem_abi_align),
8872 try o.builder.intValue(llvm_usize_ty, elem_abi_size),
8873 access_kind,
8874 );
8875 } else _ = try self.wip.store(access_kind, value, it_ptr.toValue(), it_ptr_align);
93798876 const next_ptr = try self.wip.gep(.inbounds, elem_llvm_ty, it_ptr.toValue(), &.{
9380 try o.builder.intValue(usize_ty, 1),
8877 try o.builder.intValue(llvm_usize_ty, 1),
93818878 }, "");
93828879 _ = try self.wip.br(loop_block);
93838880
......@@ -9392,22 +8889,16 @@ pub const FuncGen = struct {
93928889 fill_byte: Builder.Value,
93938890 len: Builder.Value,
93948891 dest_ptr_align: Builder.Alignment,
9395 is_volatile: bool,
8892 access_kind: Builder.MemoryAccessKind,
93968893 ) !void {
93978894 const o = self.dg.object;
9398 const llvm_usize_ty = try o.lowerType(Type.usize);
9399 const cond = try self.cmp(len, try o.builder.intValue(llvm_usize_ty, 0), Type.usize, .neq);
8895 const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0);
8896 const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero);
94008897 const memset_block = try self.wip.block(1, "MemsetTrapSkip");
94018898 const end_block = try self.wip.block(2, "MemsetTrapEnd");
94028899 _ = try self.wip.brCond(cond, memset_block, end_block);
94038900 self.wip.cursor = .{ .block = memset_block };
9404 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet(
9405 dest_ptr.toLlvm(&self.wip),
9406 fill_byte.toLlvm(&self.wip),
9407 len.toLlvm(&self.wip),
9408 @intCast(dest_ptr_align.toByteUnits() orelse 0),
9409 is_volatile,
9410 ), &self.wip);
8901 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
94118902 _ = try self.wip.br(end_block);
94128903 self.wip.cursor = .{ .block = end_block };
94138904 }
......@@ -9423,7 +8914,8 @@ pub const FuncGen = struct {
94238914 const src_ptr = try self.sliceOrArrayPtr(src_slice, src_ptr_ty);
94248915 const len = try self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty);
94258916 const dest_ptr = try self.sliceOrArrayPtr(dest_slice, dest_ptr_ty);
9426 const is_volatile = src_ptr_ty.isVolatilePtr(mod) or dest_ptr_ty.isVolatilePtr(mod);
8917 const access_kind: Builder.MemoryAccessKind = if (src_ptr_ty.isVolatilePtr(mod) or
8918 dest_ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal;
94278919
94288920 // When bulk-memory is enabled, this will be lowered to WebAssembly's memory.copy instruction.
94298921 // This instruction will trap on an invalid address, regardless of the length.
......@@ -9434,33 +8926,33 @@ pub const FuncGen = struct {
94348926 std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and
94358927 dest_ptr_ty.isSlice(mod))
94368928 {
9437 const zero_usize = try o.builder.intValue(try o.lowerType(Type.usize), 0);
9438 const cond = try self.cmp(len, zero_usize, Type.usize, .neq);
8929 const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0);
8930 const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero);
94398931 const memcpy_block = try self.wip.block(1, "MemcpyTrapSkip");
94408932 const end_block = try self.wip.block(2, "MemcpyTrapEnd");
94418933 _ = try self.wip.brCond(cond, memcpy_block, end_block);
94428934 self.wip.cursor = .{ .block = memcpy_block };
9443 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy(
9444 dest_ptr.toLlvm(&self.wip),
9445 dest_ptr_ty.ptrAlignment(mod),
9446 src_ptr.toLlvm(&self.wip),
9447 src_ptr_ty.ptrAlignment(mod),
9448 len.toLlvm(&self.wip),
9449 is_volatile,
9450 ), &self.wip);
8935 _ = try self.wip.callMemCpy(
8936 dest_ptr,
8937 Builder.Alignment.fromByteUnits(dest_ptr_ty.ptrAlignment(mod)),
8938 src_ptr,
8939 Builder.Alignment.fromByteUnits(src_ptr_ty.ptrAlignment(mod)),
8940 len,
8941 access_kind,
8942 );
94518943 _ = try self.wip.br(end_block);
94528944 self.wip.cursor = .{ .block = end_block };
94538945 return .none;
94548946 }
94558947
9456 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy(
9457 dest_ptr.toLlvm(&self.wip),
9458 dest_ptr_ty.ptrAlignment(mod),
9459 src_ptr.toLlvm(&self.wip),
9460 src_ptr_ty.ptrAlignment(mod),
9461 len.toLlvm(&self.wip),
9462 is_volatile,
9463 ), &self.wip);
8948 _ = try self.wip.callMemCpy(
8949 dest_ptr,
8950 Builder.Alignment.fromByteUnits(dest_ptr_ty.ptrAlignment(mod)),
8951 src_ptr,
8952 Builder.Alignment.fromByteUnits(src_ptr_ty.ptrAlignment(mod)),
8953 len,
8954 access_kind,
8955 );
94648956 return .none;
94658957 }
94668958
......@@ -9513,39 +9005,51 @@ pub const FuncGen = struct {
95139005 const operand = try self.resolveInst(un_op);
95149006 const operand_ty = self.typeOf(un_op);
95159007
9516 return self.buildFloatOp(op, operand_ty, 1, .{operand});
9008 return self.buildFloatOp(op, .normal, operand_ty, 1, .{operand});
95179009 }
95189010
9519 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
9520 self.builder.setFastMath(want_fast_math);
9521
9011 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
95229012 const un_op = self.air.instructions.items(.data)[inst].un_op;
95239013 const operand = try self.resolveInst(un_op);
95249014 const operand_ty = self.typeOf(un_op);
95259015
9526 return self.buildFloatOp(.neg, operand_ty, 1, .{operand});
9016 return self.buildFloatOp(.neg, fast, operand_ty, 1, .{operand});
95279017 }
95289018
9529 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value {
9019 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value {
95309020 const o = self.dg.object;
95319021 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
9022 const inst_ty = self.typeOfIndex(inst);
9023 const operand_ty = self.typeOf(ty_op.operand);
95329024 const operand = try self.resolveInst(ty_op.operand);
95339025
9534 const wrong_size_result = try self.wip.bin(intrinsic, operand, (try o.builder.intConst(.i1, 0)).toValue(), "");
9535
9536 const result_ty = self.typeOfIndex(inst);
9537 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");
9026 const result = try self.wip.callIntrinsic(
9027 .normal,
9028 .none,
9029 intrinsic,
9030 &.{try o.lowerType(operand_ty)},
9031 &.{ operand, .false },
9032 "",
9033 );
9034 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
95389035 }
95399036
9540 fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value {
9037 fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value {
95419038 const o = self.dg.object;
95429039 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
9040 const inst_ty = self.typeOfIndex(inst);
9041 const operand_ty = self.typeOf(ty_op.operand);
95439042 const operand = try self.resolveInst(ty_op.operand);
95449043
9545 const wrong_size_result = try self.wip.un(intrinsic, operand, "");
9546
9547 const result_ty = self.typeOfIndex(inst);
9548 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");
9044 const result = try self.wip.callIntrinsic(
9045 .normal,
9046 .none,
9047 intrinsic,
9048 &.{try o.lowerType(operand_ty)},
9049 &.{operand},
9050 "",
9051 );
9052 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
95499053 }
95509054
95519055 fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -9556,6 +9060,7 @@ pub const FuncGen = struct {
95569060 var bits = operand_ty.intInfo(mod).bits;
95579061 assert(bits % 8 == 0);
95589062
9063 const inst_ty = self.typeOfIndex(inst);
95599064 var operand = try self.resolveInst(ty_op.operand);
95609065 var llvm_operand_ty = try o.lowerType(operand_ty);
95619066
......@@ -9576,10 +9081,9 @@ pub const FuncGen = struct {
95769081 bits = bits + 8;
95779082 }
95789083
9579 const wrong_size_result = try self.wip.un(.@"llvm.bswap.", operand, "");
9580
9581 const result_ty = self.typeOfIndex(inst);
9582 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");
9084 const result =
9085 try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, "");
9086 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
95839087 }
95849088
95859089 fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -9609,11 +9113,7 @@ pub const FuncGen = struct {
96099113
96109114 self.wip.cursor = .{ .block = end_block };
96119115 const phi = try self.wip.phi(.i1, "");
9612 try phi.finish(
9613 &.{ Builder.Constant.true.toValue(), Builder.Constant.false.toValue() },
9614 &.{ valid_block, invalid_block },
9615 &self.wip,
9616 );
9116 try phi.finish(&.{ .true, .false }, &.{ valid_block, invalid_block }, &self.wip);
96179117 return phi.toValue();
96189118 }
96199119
......@@ -9646,37 +9146,22 @@ pub const FuncGen = struct {
96469146 errdefer assert(o.named_enum_map.remove(enum_type.decl));
96479147
96489148 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
9649 const llvm_fn_name = try o.builder.fmt("__zig_is_named_enum_value_{}", .{
9650 fqn.fmt(&mod.intern_pool),
9651 });
9149 const function_index = try o.builder.addFunction(
9150 try o.builder.fnType(.i1, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
9151 try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}),
9152 toLlvmAddressSpace(.generic, mod.getTarget()),
9153 );
96529154
96539155 var attributes: Builder.FunctionAttributes.Wip = .{};
96549156 defer attributes.deinit(&o.builder);
9157 try o.addCommonFnAttributes(&attributes);
96559158
9656 const fn_type = try o.builder.fnType(.i1, &.{
9657 try o.lowerType(enum_type.tag_ty.toType()),
9658 }, .normal);
9659 const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));
9660 fn_val.setLinkage(.Internal);
9661 fn_val.setFunctionCallConv(.Fast);
9662 try o.addCommonFnAttributes(&attributes, fn_val);
9663
9664 var global = Builder.Global{
9665 .linkage = .internal,
9666 .type = fn_type,
9667 .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
9668 };
9669 var function = Builder.Function{
9670 .global = @enumFromInt(o.builder.globals.count()),
9671 .call_conv = .fastcc,
9672 .attributes = try attributes.finish(&o.builder),
9673 };
9674 try o.builder.llvm.globals.append(self.gpa, fn_val);
9675 _ = try o.builder.addGlobal(llvm_fn_name, global);
9676 try o.builder.functions.append(self.gpa, function);
9677 gop.value_ptr.* = global.kind.function;
9159 function_index.setLinkage(.internal, &o.builder);
9160 function_index.setCallConv(.fastcc, &o.builder);
9161 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9162 gop.value_ptr.* = function_index;
96789163
9679 var wip = try Builder.WipFunction.init(&o.builder, global.kind.function);
9164 var wip = try Builder.WipFunction.init(&o.builder, function_index);
96809165 defer wip.deinit();
96819166 wip.cursor = .{ .block = try wip.block(0, "Entry") };
96829167
......@@ -9693,13 +9178,13 @@ pub const FuncGen = struct {
96939178 try wip_switch.addCase(this_tag_int_value, named_block, &wip);
96949179 }
96959180 wip.cursor = .{ .block = named_block };
9696 _ = try wip.ret(Builder.Constant.true.toValue());
9181 _ = try wip.ret(.true);
96979182
96989183 wip.cursor = .{ .block = unnamed_block };
9699 _ = try wip.ret(Builder.Constant.false.toValue());
9184 _ = try wip.ret(.false);
97009185
97019186 try wip.finish();
9702 return global.kind.function;
9187 return function_index;
97039188 }
97049189
97059190 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -9730,38 +9215,25 @@ pub const FuncGen = struct {
97309215 if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function;
97319216 errdefer assert(o.decl_map.remove(enum_type.decl));
97329217
9218 const usize_ty = try o.lowerType(Type.usize);
9219 const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
97339220 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
9734 const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)});
9221 const function_index = try o.builder.addFunction(
9222 try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
9223 try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}),
9224 toLlvmAddressSpace(.generic, mod.getTarget()),
9225 );
97359226
97369227 var attributes: Builder.FunctionAttributes.Wip = .{};
97379228 defer attributes.deinit(&o.builder);
9229 try o.addCommonFnAttributes(&attributes);
97389230
9739 const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
9740 const usize_ty = try o.lowerType(Type.usize);
9231 function_index.setLinkage(.internal, &o.builder);
9232 function_index.setCallConv(.fastcc, &o.builder);
9233 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9234 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
97419235
9742 const fn_type = try o.builder.fnType(ret_ty, &.{
9743 try o.lowerType(enum_type.tag_ty.toType()),
9744 }, .normal);
9745 const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));
9746 fn_val.setLinkage(.Internal);
9747 fn_val.setFunctionCallConv(.Fast);
9748 try o.addCommonFnAttributes(&attributes, fn_val);
9749
9750 var global = Builder.Global{
9751 .linkage = .internal,
9752 .type = fn_type,
9753 .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
9754 };
9755 var function = Builder.Function{
9756 .global = @enumFromInt(o.builder.globals.count()),
9757 .call_conv = .fastcc,
9758 .attributes = try attributes.finish(&o.builder),
9759 };
9760 try o.builder.llvm.globals.append(self.gpa, fn_val);
9761 gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global);
9762 try o.builder.functions.append(self.gpa, function);
9763
9764 var wip = try Builder.WipFunction.init(&o.builder, global.kind.function);
9236 var wip = try Builder.WipFunction.init(&o.builder, function_index);
97659237 defer wip.deinit();
97669238 wip.cursor = .{ .block = try wip.block(0, "Entry") };
97679239
......@@ -9771,36 +9243,20 @@ pub const FuncGen = struct {
97719243 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
97729244 defer wip_switch.finish(&wip);
97739245
9774 for (enum_type.names, 0..) |name_ip, field_index| {
9775 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_ip));
9776 const str_init = try o.builder.stringNullConst(name);
9777 const str_ty = str_init.typeOf(&o.builder);
9778 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");
9779 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));
9780 str_llvm_global.setLinkage(.Private);
9781 str_llvm_global.setGlobalConstant(.True);
9782 str_llvm_global.setUnnamedAddr(.True);
9783 str_llvm_global.setAlignment(1);
9784
9785 var str_global = Builder.Global{
9786 .linkage = .private,
9787 .unnamed_addr = .unnamed_addr,
9788 .type = str_ty,
9789 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
9790 };
9791 var str_variable = Builder.Variable{
9792 .global = @enumFromInt(o.builder.globals.count()),
9793 .mutability = .constant,
9794 .init = str_init,
9795 .alignment = comptime Builder.Alignment.fromByteUnits(1),
9796 };
9797 try o.builder.llvm.globals.append(o.gpa, str_llvm_global);
9798 const global_index = try o.builder.addGlobal(.empty, str_global);
9799 try o.builder.variables.append(o.gpa, str_variable);
9800
9801 const slice_val = try o.builder.structValue(ret_ty, &.{
9802 global_index.toConst(),
9803 try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len),
9246 for (enum_type.names, 0..) |name, field_index| {
9247 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
9248 const name_init = try o.builder.stringNullConst(name_string);
9249 const name_variable_index =
9250 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
9251 try name_variable_index.setInitializer(name_init, &o.builder);
9252 name_variable_index.setLinkage(.private, &o.builder);
9253 name_variable_index.setMutability(.constant, &o.builder);
9254 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
9255 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
9256
9257 const name_val = try o.builder.structValue(ret_ty, &.{
9258 name_variable_index.toConst(&o.builder),
9259 try o.builder.intConst(usize_ty, name_string.slice(&o.builder).?.len),
98049260 });
98059261
98069262 const return_block = try wip.block(1, "Name");
......@@ -9810,14 +9266,14 @@ pub const FuncGen = struct {
98109266 try wip_switch.addCase(this_tag_int_value, return_block, &wip);
98119267
98129268 wip.cursor = .{ .block = return_block };
9813 _ = try wip.ret(slice_val);
9269 _ = try wip.ret(name_val);
98149270 }
98159271
98169272 wip.cursor = .{ .block = bad_value_block };
98179273 _ = try wip.@"unreachable"();
98189274
98199275 try wip.finish();
9820 return global.kind.function;
9276 return function_index;
98219277 }
98229278
98239279 fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index {
......@@ -9826,33 +9282,20 @@ pub const FuncGen = struct {
98269282 const name = try o.builder.string(lt_errors_fn_name);
98279283 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
98289284
9829 // Function signature: fn (anyerror) bool
9830
9831 const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal);
9832 const llvm_fn = o.llvm_module.addFunction(name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));
9285 const function_index = try o.builder.addFunction(
9286 try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal),
9287 name,
9288 toLlvmAddressSpace(.generic, o.module.getTarget()),
9289 );
98339290
98349291 var attributes: Builder.FunctionAttributes.Wip = .{};
98359292 defer attributes.deinit(&o.builder);
9293 try o.addCommonFnAttributes(&attributes);
98369294
9837 llvm_fn.setLinkage(.Internal);
9838 llvm_fn.setFunctionCallConv(.Fast);
9839 try o.addCommonFnAttributes(&attributes, llvm_fn);
9840
9841 var global = Builder.Global{
9842 .linkage = .internal,
9843 .type = fn_type,
9844 .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
9845 };
9846 var function = Builder.Function{
9847 .global = @enumFromInt(o.builder.globals.count()),
9848 .call_conv = .fastcc,
9849 .attributes = try attributes.finish(&o.builder),
9850 };
9851
9852 try o.builder.llvm.globals.append(self.gpa, llvm_fn);
9853 _ = try o.builder.addGlobal(name, global);
9854 try o.builder.functions.append(self.gpa, function);
9855 return global.kind.function;
9295 function_index.setLinkage(.internal, &o.builder);
9296 function_index.setCallConv(.fastcc, &o.builder);
9297 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9298 return function_index;
98569299 }
98579300
98589301 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -9885,7 +9328,7 @@ pub const FuncGen = struct {
98859328 const a = try self.resolveInst(extra.lhs);
98869329 const b = try self.resolveInst(extra.rhs);
98879330
9888 return self.wip.select(pred, a, b, "");
9331 return self.wip.select(.normal, pred, a, b, "");
98899332 }
98909333
98919334 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -9997,8 +9440,7 @@ pub const FuncGen = struct {
99979440 return self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, "");
99989441 }
99999442
10000 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
10001 self.builder.setFastMath(want_fast_math);
9443 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
100029444 const o = self.dg.object;
100039445 const mod = o.module;
100049446 const target = mod.getTarget();
......@@ -10006,72 +9448,53 @@ pub const FuncGen = struct {
100069448 const reduce = self.air.instructions.items(.data)[inst].reduce;
100079449 const operand = try self.resolveInst(reduce.operand);
100089450 const operand_ty = self.typeOf(reduce.operand);
9451 const llvm_operand_ty = try o.lowerType(operand_ty);
100099452 const scalar_ty = self.typeOfIndex(inst);
100109453 const llvm_scalar_ty = try o.lowerType(scalar_ty);
100119454
100129455 switch (reduce.operation) {
10013 .And => return (try self.wip.unimplemented(llvm_scalar_ty, ""))
10014 .finish(self.builder.buildAndReduce(operand.toLlvm(&self.wip)), &self.wip),
10015 .Or => return (try self.wip.unimplemented(llvm_scalar_ty, ""))
10016 .finish(self.builder.buildOrReduce(operand.toLlvm(&self.wip)), &self.wip),
10017 .Xor => return (try self.wip.unimplemented(llvm_scalar_ty, ""))
10018 .finish(self.builder.buildXorReduce(operand.toLlvm(&self.wip)), &self.wip),
10019 .Min => switch (scalar_ty.zigTypeTag(mod)) {
10020 .Int => return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish(
10021 self.builder.buildIntMinReduce(
10022 operand.toLlvm(&self.wip),
10023 scalar_ty.isSignedInt(mod),
10024 ),
10025 &self.wip,
10026 ),
10027 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
10028 return (try self.wip.unimplemented(llvm_scalar_ty, ""))
10029 .finish(self.builder.buildFPMinReduce(operand.toLlvm(&self.wip)), &self.wip);
10030 },
10031 else => unreachable,
10032 },
10033 .Max => switch (scalar_ty.zigTypeTag(mod)) {
10034 .Int => return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish(
10035 self.builder.buildIntMaxReduce(
10036 operand.toLlvm(&self.wip),
10037 scalar_ty.isSignedInt(mod),
10038 ),
10039 &self.wip,
10040 ),
10041 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
10042 return (try self.wip.unimplemented(llvm_scalar_ty, ""))
10043 .finish(self.builder.buildFPMaxReduce(operand.toLlvm(&self.wip)), &self.wip);
10044 },
9456 .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
9457 .And => .@"vector.reduce.and",
9458 .Or => .@"vector.reduce.or",
9459 .Xor => .@"vector.reduce.xor",
100459460 else => unreachable,
10046 },
10047 .Add => switch (scalar_ty.zigTypeTag(mod)) {
10048 .Int => return (try self.wip.unimplemented(llvm_scalar_ty, ""))
10049 .finish(self.builder.buildAddReduce(operand.toLlvm(&self.wip)), &self.wip),
10050 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
10051 const neutral_value = try o.builder.fpConst(llvm_scalar_ty, -0.0);
10052 return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish(
10053 self.builder.buildFPAddReduce(
10054 neutral_value.toLlvm(&o.builder),
10055 operand.toLlvm(&self.wip),
10056 ),
10057 &self.wip,
10058 );
10059 },
9461 }, &.{llvm_operand_ty}, &.{operand}, ""),
9462 .Min, .Max => switch (scalar_ty.zigTypeTag(mod)) {
9463 .Int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
9464 .Min => if (scalar_ty.isSignedInt(mod))
9465 .@"vector.reduce.smin"
9466 else
9467 .@"vector.reduce.umin",
9468 .Max => if (scalar_ty.isSignedInt(mod))
9469 .@"vector.reduce.smax"
9470 else
9471 .@"vector.reduce.umax",
9472 else => unreachable,
9473 }, &.{llvm_operand_ty}, &.{operand}, ""),
9474 .Float => if (intrinsicsAllowed(scalar_ty, target))
9475 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
9476 .Min => .@"vector.reduce.fmin",
9477 .Max => .@"vector.reduce.fmax",
9478 else => unreachable,
9479 }, &.{llvm_operand_ty}, &.{operand}, ""),
100609480 else => unreachable,
100619481 },
10062 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
10063 .Int => return (try self.wip.unimplemented(llvm_scalar_ty, ""))
10064 .finish(self.builder.buildMulReduce(operand.toLlvm(&self.wip)), &self.wip),
10065 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
10066 const neutral_value = try o.builder.fpConst(llvm_scalar_ty, 1.0);
10067 return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish(
10068 self.builder.buildFPMulReduce(
10069 neutral_value.toLlvm(&o.builder),
10070 operand.toLlvm(&self.wip),
10071 ),
10072 &self.wip,
10073 );
10074 },
9482 .Add, .Mul => switch (scalar_ty.zigTypeTag(mod)) {
9483 .Int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
9484 .Add => .@"vector.reduce.add",
9485 .Mul => .@"vector.reduce.mul",
9486 else => unreachable,
9487 }, &.{llvm_operand_ty}, &.{operand}, ""),
9488 .Float => if (intrinsicsAllowed(scalar_ty, target))
9489 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
9490 .Add => .@"vector.reduce.fadd",
9491 .Mul => .@"vector.reduce.fmul",
9492 else => unreachable,
9493 }, &.{llvm_operand_ty}, &.{ switch (reduce.operation) {
9494 .Add => try o.builder.fpValue(llvm_scalar_ty, -0.0),
9495 .Mul => try o.builder.fpValue(llvm_scalar_ty, 1.0),
9496 else => unreachable,
9497 }, operand }, ""),
100759498 else => unreachable,
100769499 },
100779500 }
......@@ -10168,10 +9591,8 @@ pub const FuncGen = struct {
101689591 else
101699592 try self.wip.cast(.bitcast, non_int_val, small_int_ty, "");
101709593 const shift_rhs = try o.builder.intValue(int_ty, running_bits);
10171 // If the field is as large as the entire packed struct, this
10172 // zext would go from, e.g. i16 to i16. This is legal with
10173 // constZExtOrBitCast but not legal with constZExt.
10174 const extended_int_val = try self.wip.conv(.unsigned, small_int_val, int_ty, "");
9594 const extended_int_val =
9595 try self.wip.conv(.unsigned, small_int_val, int_ty, "");
101759596 const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, "");
101769597 running_int = try self.wip.bin(.@"or", running_int, shifted, "");
101779598 running_bits += ty_bit_size;
......@@ -10416,29 +9837,12 @@ pub const FuncGen = struct {
104169837 .data => {},
104179838 }
104189839
10419 const llvm_fn_name = "llvm.prefetch.p0";
10420 // declare void @llvm.prefetch(i8*, i32, i32, i32)
10421 const llvm_fn_ty = try o.builder.fnType(.void, &.{ .ptr, .i32, .i32, .i32 }, .normal);
10422 const fn_val = o.llvm_module.getNamedFunction(llvm_fn_name) orelse
10423 o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder));
10424
10425 const ptr = try self.resolveInst(prefetch.ptr);
10426
10427 const params = [_]*llvm.Value{
10428 ptr.toLlvm(&self.wip),
10429 (try o.builder.intConst(.i32, @intFromEnum(prefetch.rw))).toLlvm(&o.builder),
10430 (try o.builder.intConst(.i32, prefetch.locality)).toLlvm(&o.builder),
10431 (try o.builder.intConst(.i32, @intFromEnum(prefetch.cache))).toLlvm(&o.builder),
10432 };
10433 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld(
10434 llvm_fn_ty.toLlvm(&o.builder),
10435 fn_val,
10436 &params,
10437 params.len,
10438 .C,
10439 .Auto,
10440 "",
10441 ), &self.wip);
9840 _ = try self.wip.callIntrinsic(.normal, .none, .prefetch, &.{.ptr}, &.{
9841 try self.resolveInst(prefetch.ptr),
9842 try o.builder.intValue(.i32, prefetch.rw),
9843 try o.builder.intValue(.i32, prefetch.locality),
9844 try o.builder.intValue(.i32, prefetch.cache),
9845 }, "");
104429846 return .none;
104439847 }
104449848
......@@ -10451,26 +9855,18 @@ pub const FuncGen = struct {
104519855 return self.wip.cast(.addrspacecast, operand, try o.lowerType(inst_ty), "");
104529856 }
104539857
10454 fn amdgcnWorkIntrinsic(self: *FuncGen, dimension: u32, default: u32, comptime basename: []const u8) !Builder.Value {
10455 const o = self.dg.object;
10456 const llvm_fn_name = switch (dimension) {
10457 0 => basename ++ ".x",
10458 1 => basename ++ ".y",
10459 2 => basename ++ ".z",
10460 else => return o.builder.intValue(.i32, default),
10461 };
10462
10463 const args: [0]*llvm.Value = .{};
10464 const llvm_fn = try self.getIntrinsic(llvm_fn_name, &.{});
10465 return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld(
10466 (try o.builder.fnType(.i32, &.{}, .normal)).toLlvm(&o.builder),
10467 llvm_fn,
10468 &args,
10469 args.len,
10470 .Fast,
10471 .Auto,
10472 "",
10473 ), &self.wip);
9858 fn amdgcnWorkIntrinsic(
9859 self: *FuncGen,
9860 dimension: u32,
9861 default: u32,
9862 comptime basename: []const u8,
9863 ) !Builder.Value {
9864 return self.wip.callIntrinsic(.normal, .none, switch (dimension) {
9865 0 => @field(Builder.Intrinsic, basename ++ ".x"),
9866 1 => @field(Builder.Intrinsic, basename ++ ".y"),
9867 2 => @field(Builder.Intrinsic, basename ++ ".z"),
9868 else => return self.dg.object.builder.intValue(.i32, default),
9869 }, &.{}, &.{}, "");
104749870 }
104759871
104769872 fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -10480,7 +9876,7 @@ pub const FuncGen = struct {
104809876
104819877 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
104829878 const dimension = pl_op.payload;
10483 return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workitem.id");
9879 return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workitem.id");
104849880 }
104859881
104869882 fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -10492,27 +9888,10 @@ pub const FuncGen = struct {
104929888 const dimension = pl_op.payload;
104939889 if (dimension >= 3) return o.builder.intValue(.i32, 1);
104949890
10495 var attributes: Builder.FunctionAttributes.Wip = .{};
10496 defer attributes.deinit(&o.builder);
10497
104989891 // Fetch the dispatch pointer, which points to this structure:
104999892 // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913
10500 const llvm_fn = try self.getIntrinsic("llvm.amdgcn.dispatch.ptr", &.{});
10501 const args: [0]*llvm.Value = .{};
10502 const llvm_ret_ty = try o.builder.ptrType(Builder.AddrSpace.amdgpu.constant);
10503 const dispatch_ptr = (try self.wip.unimplemented(llvm_ret_ty, "")).finish(self.builder.buildCallOld(
10504 (try o.builder.fnType(llvm_ret_ty, &.{}, .normal)).toLlvm(&o.builder),
10505 llvm_fn,
10506 &args,
10507 args.len,
10508 .Fast,
10509 .Auto,
10510 "",
10511 ), &self.wip);
10512 try attributes.addRetAttr(.{
10513 .@"align" = comptime Builder.Alignment.fromByteUnits(4),
10514 }, &o.builder);
10515 o.addAttrInt(dispatch_ptr.toLlvm(&self.wip), 0, "align", 4);
9893 const dispatch_ptr =
9894 try self.wip.callIntrinsic(.normal, .none, .@"amdgcn.dispatch.ptr", &.{}, &.{}, "");
105169895
105179896 // Load the work_group_* member from the struct as u16.
105189897 // Just treat the dispatch pointer as an array of u16 to keep things simple.
......@@ -10530,45 +9909,29 @@ pub const FuncGen = struct {
105309909
105319910 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
105329911 const dimension = pl_op.payload;
10533 return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workgroup.id");
9912 return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workgroup.id");
105349913 }
105359914
105369915 fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index {
105379916 const o = self.dg.object;
9917 const mod = o.module;
9918
105389919 const table = o.error_name_table;
105399920 if (table != .none) return table;
105409921
10541 const mod = o.module;
10542 const slice_ty = Type.slice_const_u8_sentinel_0;
10543 const slice_alignment = slice_ty.abiAlignment(mod);
10544 const undef_init = try o.builder.undefConst(.ptr); // TODO: Address space
10545
10546 const name = try o.builder.string("__zig_err_name_table");
10547 const error_name_table_global = o.llvm_module.addGlobal(Builder.Type.ptr.toLlvm(&o.builder), name.slice(&o.builder).?);
10548 error_name_table_global.setInitializer(undef_init.toLlvm(&o.builder));
10549 error_name_table_global.setLinkage(.Private);
10550 error_name_table_global.setGlobalConstant(.True);
10551 error_name_table_global.setUnnamedAddr(.True);
10552 error_name_table_global.setAlignment(slice_alignment);
10553
10554 var global = Builder.Global{
10555 .linkage = .private,
10556 .unnamed_addr = .unnamed_addr,
10557 .type = .ptr,
10558 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
10559 };
10560 var variable = Builder.Variable{
10561 .global = @enumFromInt(o.builder.globals.count()),
10562 .mutability = .constant,
10563 .init = undef_init,
10564 .alignment = Builder.Alignment.fromByteUnits(slice_alignment),
10565 };
10566 try o.builder.llvm.globals.append(o.gpa, error_name_table_global);
10567 _ = try o.builder.addGlobal(name, global);
10568 try o.builder.variables.append(o.gpa, variable);
9922 // TODO: Address space
9923 const variable_index =
9924 try o.builder.addVariable(try o.builder.string("__zig_err_name_table"), .ptr, .default);
9925 variable_index.setLinkage(.private, &o.builder);
9926 variable_index.setMutability(.constant, &o.builder);
9927 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
9928 variable_index.setAlignment(
9929 Builder.Alignment.fromByteUnits(Type.slice_const_u8_sentinel_0.abiAlignment(mod)),
9930 &o.builder,
9931 );
105699932
10570 o.error_name_table = global.kind.variable;
10571 return global.kind.variable;
9933 o.error_name_table = variable_index;
9934 return variable_index;
105729935 }
105739936
105749937 /// Assumes the optional is not pointer-like and payload has bits.
......@@ -10613,7 +9976,7 @@ pub const FuncGen = struct {
106139976 if (can_elide_load)
106149977 return payload_ptr;
106159978
10616 return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, false);
9979 return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal);
106179980 }
106189981 const payload_llvm_ty = try o.lowerType(payload_ty);
106199982 return fg.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, "");
......@@ -10716,27 +10079,13 @@ pub const FuncGen = struct {
1071610079 }
1071710080 }
1071810081
10719 fn getIntrinsic(
10720 fg: *FuncGen,
10721 name: []const u8,
10722 types: []const Builder.Type,
10723 ) Allocator.Error!*llvm.Value {
10724 const o = fg.dg.object;
10725 const id = llvm.lookupIntrinsicID(name.ptr, name.len);
10726 assert(id != 0);
10727 const llvm_types = try o.gpa.alloc(*llvm.Type, types.len);
10728 defer o.gpa.free(llvm_types);
10729 for (llvm_types, types) |*llvm_type, ty| llvm_type.* = ty.toLlvm(&o.builder);
10730 return o.llvm_module.getIntrinsicDeclaration(id, llvm_types.ptr, llvm_types.len);
10731 }
10732
1073310082 /// Load a by-ref type by constructing a new alloca and performing a memcpy.
1073410083 fn loadByRef(
1073510084 fg: *FuncGen,
1073610085 ptr: Builder.Value,
1073710086 pointee_type: Type,
1073810087 ptr_alignment: Builder.Alignment,
10739 is_volatile: bool,
10088 access_kind: Builder.MemoryAccessKind,
1074010089 ) !Builder.Value {
1074110090 const o = fg.dg.object;
1074210091 const mod = o.module;
......@@ -10745,16 +10094,15 @@ pub const FuncGen = struct {
1074510094 @max(ptr_alignment.toByteUnits() orelse 0, pointee_type.abiAlignment(mod)),
1074610095 );
1074710096 const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align);
10748 const usize_ty = try o.lowerType(Type.usize);
1074910097 const size_bytes = pointee_type.abiSize(mod);
10750 _ = (try fg.wip.unimplemented(.void, "")).finish(fg.builder.buildMemCpy(
10751 result_ptr.toLlvm(&fg.wip),
10752 @intCast(result_align.toByteUnits() orelse 0),
10753 ptr.toLlvm(&fg.wip),
10754 @intCast(ptr_alignment.toByteUnits() orelse 0),
10755 (try o.builder.intConst(usize_ty, size_bytes)).toLlvm(&o.builder),
10756 is_volatile,
10757 ), &fg.wip);
10098 _ = try fg.wip.callMemCpy(
10099 result_ptr,
10100 result_align,
10101 ptr,
10102 ptr_alignment,
10103 try o.builder.intValue(try o.lowerType(Type.usize), size_bytes),
10104 access_kind,
10105 );
1075810106 return result_ptr;
1075910107 }
1076010108
......@@ -10771,30 +10119,29 @@ pub const FuncGen = struct {
1077110119 const ptr_alignment = Builder.Alignment.fromByteUnits(
1077210120 info.flags.alignment.toByteUnitsOptional() orelse elem_ty.abiAlignment(mod),
1077310121 );
10774 const ptr_kind: Builder.MemoryAccessKind = switch (info.flags.is_volatile) {
10775 false => .normal,
10776 true => .@"volatile",
10777 };
10122 const access_kind: Builder.MemoryAccessKind =
10123 if (info.flags.is_volatile) .@"volatile" else .normal;
1077810124
1077910125 assert(info.flags.vector_index != .runtime);
1078010126 if (info.flags.vector_index != .none) {
10781 const index_u32 = try o.builder.intValue(.i32, @intFromEnum(info.flags.vector_index));
10127 const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index);
1078210128 const vec_elem_ty = try o.lowerType(elem_ty);
1078310129 const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty);
1078410130
10785 const loaded_vector = try self.wip.load(ptr_kind, vec_ty, ptr, ptr_alignment, "");
10131 const loaded_vector = try self.wip.load(access_kind, vec_ty, ptr, ptr_alignment, "");
1078610132 return self.wip.extractElement(loaded_vector, index_u32, "");
1078710133 }
1078810134
1078910135 if (info.packed_offset.host_size == 0) {
1079010136 if (isByRef(elem_ty, mod)) {
10791 return self.loadByRef(ptr, elem_ty, ptr_alignment, info.flags.is_volatile);
10137 return self.loadByRef(ptr, elem_ty, ptr_alignment, access_kind);
1079210138 }
10793 return self.wip.load(ptr_kind, try o.lowerType(elem_ty), ptr, ptr_alignment, "");
10139 return self.wip.load(access_kind, try o.lowerType(elem_ty), ptr, ptr_alignment, "");
1079410140 }
1079510141
1079610142 const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8));
10797 const containing_int = try self.wip.load(ptr_kind, containing_int_ty, ptr, ptr_alignment, "");
10143 const containing_int =
10144 try self.wip.load(access_kind, containing_int_ty, ptr, ptr_alignment, "");
1079810145
1079910146 const elem_bits = ptr_ty.childType(mod).bitSize(mod);
1080010147 const shift_amt = try o.builder.intValue(containing_int_ty, info.packed_offset.bit_offset);
......@@ -10841,23 +10188,21 @@ pub const FuncGen = struct {
1084110188 return;
1084210189 }
1084310190 const ptr_alignment = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));
10844 const ptr_kind: Builder.MemoryAccessKind = switch (info.flags.is_volatile) {
10845 false => .normal,
10846 true => .@"volatile",
10847 };
10191 const access_kind: Builder.MemoryAccessKind =
10192 if (info.flags.is_volatile) .@"volatile" else .normal;
1084810193
1084910194 assert(info.flags.vector_index != .runtime);
1085010195 if (info.flags.vector_index != .none) {
10851 const index_u32 = try o.builder.intValue(.i32, @intFromEnum(info.flags.vector_index));
10196 const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index);
1085210197 const vec_elem_ty = try o.lowerType(elem_ty);
1085310198 const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty);
1085410199
10855 const loaded_vector = try self.wip.load(ptr_kind, vec_ty, ptr, ptr_alignment, "");
10200 const loaded_vector = try self.wip.load(access_kind, vec_ty, ptr, ptr_alignment, "");
1085610201
1085710202 const modified_vector = try self.wip.insertElement(loaded_vector, elem, index_u32, "");
1085810203
1085910204 assert(ordering == .none);
10860 _ = try self.wip.store(ptr_kind, modified_vector, ptr, ptr_alignment);
10205 _ = try self.wip.store(access_kind, modified_vector, ptr, ptr_alignment);
1086110206 return;
1086210207 }
1086310208
......@@ -10865,7 +10210,7 @@ pub const FuncGen = struct {
1086510210 const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8));
1086610211 assert(ordering == .none);
1086710212 const containing_int =
10868 try self.wip.load(ptr_kind, containing_int_ty, ptr, ptr_alignment, "");
10213 try self.wip.load(access_kind, containing_int_ty, ptr, ptr_alignment, "");
1086910214 const elem_bits = ptr_ty.childType(mod).bitSize(mod);
1087010215 const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset);
1087110216 // Convert to equally-sized integer type in order to perform the bit
......@@ -10889,23 +10234,29 @@ pub const FuncGen = struct {
1088910234 const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, "");
1089010235
1089110236 assert(ordering == .none);
10892 _ = try self.wip.store(ptr_kind, ored_value, ptr, ptr_alignment);
10237 _ = try self.wip.store(access_kind, ored_value, ptr, ptr_alignment);
1089310238 return;
1089410239 }
1089510240 if (!isByRef(elem_ty, mod)) {
10896 _ = try self.wip.storeAtomic(ptr_kind, elem, ptr, self.sync_scope, ordering, ptr_alignment);
10241 _ = try self.wip.storeAtomic(
10242 access_kind,
10243 elem,
10244 ptr,
10245 self.sync_scope,
10246 ordering,
10247 ptr_alignment,
10248 );
1089710249 return;
1089810250 }
1089910251 assert(ordering == .none);
10900 const size_bytes = elem_ty.abiSize(mod);
10901 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy(
10902 ptr.toLlvm(&self.wip),
10903 @intCast(ptr_alignment.toByteUnits() orelse 0),
10904 elem.toLlvm(&self.wip),
10905 elem_ty.abiAlignment(mod),
10906 (try o.builder.intConst(try o.lowerType(Type.usize), size_bytes)).toLlvm(&o.builder),
10907 info.flags.is_volatile,
10908 ), &self.wip);
10252 _ = try self.wip.callMemCpy(
10253 ptr,
10254 ptr_alignment,
10255 elem,
10256 Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod)),
10257 try o.builder.intValue(try o.lowerType(Type.usize), elem_ty.abiSize(mod)),
10258 access_kind,
10259 );
1090910260 }
1091010261
1091110262 fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void {
......@@ -10982,26 +10333,15 @@ pub const FuncGen = struct {
1098210333 else => unreachable,
1098310334 };
1098410335
10985 const fn_llvm_ty = (try o.builder.fnType(llvm_usize, &(.{llvm_usize} ** 2), .normal)).toLlvm(&o.builder);
10986 const array_ptr_as_usize = try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, "");
10987 const args = [_]*llvm.Value{ array_ptr_as_usize.toLlvm(&fg.wip), default_value.toLlvm(&fg.wip) };
10988 const asm_fn = llvm.getInlineAsm(
10989 fn_llvm_ty,
10990 arch_specific.template.ptr,
10991 arch_specific.template.len,
10992 arch_specific.constraints.ptr,
10993 arch_specific.constraints.len,
10994 .True, // has side effects
10995 .False, // alignstack
10996 .ATT,
10997 .False, // can throw
10998 );
10999
11000 const call = (try fg.wip.unimplemented(llvm_usize, "")).finish(
11001 fg.builder.buildCallOld(fn_llvm_ty, asm_fn, &args, args.len, .C, .Auto, ""),
11002 &fg.wip,
10336 return fg.wip.callAsm(
10337 .none,
10338 try o.builder.fnType(llvm_usize, &.{ llvm_usize, llvm_usize }, .normal),
10339 .{ .sideeffect = true },
10340 try o.builder.string(arch_specific.template),
10341 try o.builder.string(arch_specific.constraints),
10342 &.{ try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, ""), default_value },
10343 "",
1100310344 );
11004 return call;
1100510345 }
1100610346
1100710347 fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type {
......@@ -11032,17 +10372,17 @@ fn toLlvmAtomicRmwBinOp(
1103210372 op: std.builtin.AtomicRmwOp,
1103310373 is_signed: bool,
1103410374 is_float: bool,
11035) llvm.AtomicRMWBinOp {
10375) Builder.Function.Instruction.AtomicRmw.Operation {
1103610376 return switch (op) {
11037 .Xchg => .Xchg,
11038 .Add => if (is_float) .FAdd else return .Add,
11039 .Sub => if (is_float) .FSub else return .Sub,
11040 .And => .And,
11041 .Nand => .Nand,
11042 .Or => .Or,
11043 .Xor => .Xor,
11044 .Max => if (is_float) .FMax else if (is_signed) .Max else return .UMax,
11045 .Min => if (is_float) .FMin else if (is_signed) .Min else return .UMin,
10377 .Xchg => .xchg,
10378 .Add => if (is_float) .fadd else return .add,
10379 .Sub => if (is_float) .fsub else return .sub,
10380 .And => .@"and",
10381 .Nand => .nand,
10382 .Or => .@"or",
10383 .Xor => .xor,
10384 .Max => if (is_float) .fmax else if (is_signed) .max else return .umax,
10385 .Min => if (is_float) .fmin else if (is_signed) .min else return .umin,
1104610386 };
1104710387}
1104810388
......@@ -12008,15 +11348,19 @@ fn buildAllocaInner(
1200811348
1200911349 const alloca = blk: {
1201011350 const prev_cursor = wip.cursor;
12011 const prev_debug_location = wip.llvm.builder.getCurrentDebugLocation2();
11351 const prev_debug_location = if (wip.builder.useLibLlvm())
11352 wip.llvm.builder.getCurrentDebugLocation2()
11353 else
11354 undefined;
1201211355 defer {
1201311356 wip.cursor = prev_cursor;
1201411357 if (wip.cursor.block == .entry) wip.cursor.instruction += 1;
12015 if (di_scope_non_null) wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location);
11358 if (wip.builder.useLibLlvm() and di_scope_non_null)
11359 wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location);
1201611360 }
1201711361
1201811362 wip.cursor = .{ .block = .entry };
12019 wip.llvm.builder.clearCurrentDebugLocation();
11363 if (wip.builder.useLibLlvm()) wip.llvm.builder.clearCurrentDebugLocation();
1202011364 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");
1202111365 };
1202211366
src/codegen/llvm/Builder.zig+3028-1057
......@@ -13,6 +13,7 @@ llvm: if (build_options.have_llvm) struct {
1313 types: std.ArrayListUnmanaged(*llvm.Type),
1414 globals: std.ArrayListUnmanaged(*llvm.Value),
1515 constants: std.ArrayListUnmanaged(*llvm.Value),
16 replacements: std.AutoHashMapUnmanaged(*llvm.Value, Global.Index),
1617} else void,
1718
1819source_filename: String,
......@@ -50,10 +51,12 @@ constant_extra: std.ArrayListUnmanaged(u32),
5051constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb),
5152
5253pub const expected_args_len = 16;
54pub const expected_attrs_len = 16;
5355pub const expected_fields_len = 32;
5456pub const expected_gep_indices_len = 8;
5557pub const expected_cases_len = 8;
5658pub const expected_incoming_len = 8;
59pub const expected_intrinsic_name_len = 64;
5760
5861pub const Options = struct {
5962 allocator: Allocator,
......@@ -151,11 +154,14 @@ pub const Type = enum(u32) {
151154 i80,
152155 i128,
153156 ptr,
157 @"ptr addrspace(4)",
154158
155159 none = std.math.maxInt(u32),
156160 _,
157161
158162 pub const err_int = Type.i16;
163 pub const ptr_amdgpu_constant =
164 @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));
159165
160166 pub const Tag = enum(u4) {
161167 simple,
......@@ -391,7 +397,7 @@ pub const Type = enum(u32) {
391397 .double, .i64, .x86_mmx => 64,
392398 .x86_fp80, .i80 => 80,
393399 .fp128, .ppc_fp128, .i128 => 128,
394 .ptr => @panic("TODO: query data layout"),
400 .ptr, .@"ptr addrspace(4)" => @panic("TODO: query data layout"),
395401 _ => {
396402 const item = builder.type_items.items[@intFromEnum(self)];
397403 return switch (item.tag) {
......@@ -690,7 +696,7 @@ pub const Type = enum(u32) {
690696 }
691697 },
692698 .integer => try writer.print("i{d}", .{item.data}),
693 .pointer => try writer.print("ptr{}", .{@as(AddrSpace, @enumFromInt(item.data))}),
699 .pointer => try writer.print("ptr{ }", .{@as(AddrSpace, @enumFromInt(item.data))}),
694700 .target => {
695701 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
696702 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
......@@ -795,6 +801,7 @@ pub const Type = enum(u32) {
795801 .i80,
796802 .i128,
797803 .ptr,
804 .@"ptr addrspace(4)",
798805 => true,
799806 .none => unreachable,
800807 _ => {
......@@ -1151,13 +1158,13 @@ pub const Attribute = union(Kind) {
11511158 .sret,
11521159 .elementtype,
11531160 => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }),
1154 .@"align" => |alignment| try writer.print("{}", .{alignment}),
1161 .@"align" => |alignment| try writer.print("{ }", .{alignment}),
11551162 .dereferenceable,
11561163 .dereferenceable_or_null,
11571164 => |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }),
11581165 .nofpclass => |fpclass| {
11591166 const Int = @typeInfo(FpClass).Struct.backing_integer.?;
1160 try writer.print("{s}(", .{@tagName(attribute)});
1167 try writer.print(" {s}(", .{@tagName(attribute)});
11611168 var any = false;
11621169 var remaining: Int = @bitCast(fpclass);
11631170 inline for (@typeInfo(FpClass).Struct.decls) |decl| {
......@@ -1175,13 +1182,13 @@ pub const Attribute = union(Kind) {
11751182 },
11761183 .alignstack => |alignment| try writer.print(
11771184 if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null)
1178 "{s}={d}"
1185 " {s}={d}"
11791186 else
1180 "{s}({d})",
1187 " {s}({d})",
11811188 .{ @tagName(attribute), alignment.toByteUnits() orelse return },
11821189 ),
11831190 .allockind => |allockind| {
1184 try writer.print("{s}(\"", .{@tagName(attribute)});
1191 try writer.print(" {s}(\"", .{@tagName(attribute)});
11851192 var any = false;
11861193 inline for (@typeInfo(AllocKind).Struct.fields) |field| {
11871194 if (comptime std.mem.eql(u8, field.name, "_")) continue;
......@@ -1196,22 +1203,30 @@ pub const Attribute = union(Kind) {
11961203 try writer.writeAll("\")");
11971204 },
11981205 .allocsize => |allocsize| {
1199 try writer.print("{s}({d}", .{ @tagName(attribute), allocsize.elem_size });
1206 try writer.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });
12001207 if (allocsize.num_elems != AllocSize.none)
12011208 try writer.print(",{d}", .{allocsize.num_elems});
12021209 try writer.writeByte(')');
12031210 },
1204 .memory => |memory| try writer.print("{s}({s}, argmem: {s}, inaccessiblemem: {s})", .{
1205 @tagName(attribute),
1206 @tagName(memory.other),
1207 @tagName(memory.argmem),
1208 @tagName(memory.inaccessiblemem),
1209 }),
1211 .memory => |memory| {
1212 try writer.print(" {s}(", .{@tagName(attribute)});
1213 var any = memory.other != .none or
1214 (memory.argmem == .none and memory.inaccessiblemem == .none);
1215 if (any) try writer.writeAll(@tagName(memory.other));
1216 inline for (.{ "argmem", "inaccessiblemem" }) |kind| {
1217 if (@field(memory, kind) != memory.other) {
1218 if (any) try writer.writeAll(", ");
1219 try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });
1220 any = true;
1221 }
1222 }
1223 try writer.writeByte(')');
1224 },
12101225 .uwtable => |uwtable| if (uwtable != .none) {
1211 try writer.writeAll(@tagName(attribute));
1226 try writer.print(" {s}", .{@tagName(attribute)});
12121227 if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)});
12131228 },
1214 .vscale_range => |vscale_range| try writer.print("{s}({d},{d})", .{
1229 .vscale_range => |vscale_range| try writer.print(" {s}({d},{d})", .{
12151230 @tagName(attribute),
12161231 vscale_range.min.toByteUnits().?,
12171232 vscale_range.max.toByteUnits() orelse 0,
......@@ -1335,21 +1350,29 @@ pub const Attribute = union(Kind) {
13351350 //sanitize_memtag,
13361351 sanitize_address_dyninit,
13371352
1338 string = std.math.maxInt(u31) - 1,
1339 none = std.math.maxInt(u31),
1353 string = std.math.maxInt(u31),
1354 none = std.math.maxInt(u32),
13401355 _,
13411356
13421357 pub const len = @typeInfo(Kind).Enum.fields.len - 2;
13431358
13441359 pub fn fromString(str: String) Kind {
13451360 assert(!str.isAnon());
1346 return @enumFromInt(@intFromEnum(str));
1361 const kind: Kind = @enumFromInt(@intFromEnum(str));
1362 assert(kind != .none);
1363 return kind;
13471364 }
13481365
13491366 fn toString(self: Kind) ?String {
1367 assert(self != .none);
13501368 const str: String = @enumFromInt(@intFromEnum(self));
13511369 return if (str.isAnon()) null else str;
13521370 }
1371
1372 fn toLlvm(self: Kind, builder: *const Builder) *c_uint {
1373 assert(builder.useLibLlvm());
1374 return &builder.llvm.attribute_kind_ids.?[@intFromEnum(self)];
1375 }
13531376 };
13541377
13551378 pub const FpClass = packed struct(u32) {
......@@ -1424,12 +1447,16 @@ pub const Attribute = union(Kind) {
14241447 };
14251448
14261449 pub const Memory = packed struct(u32) {
1427 argmem: Effect,
1428 inaccessiblemem: Effect,
1429 other: Effect,
1450 argmem: Effect = .none,
1451 inaccessiblemem: Effect = .none,
1452 other: Effect = .none,
14301453 _: u26 = 0,
14311454
14321455 pub const Effect = enum(u2) { none, read, write, readwrite };
1456
1457 fn all(effect: Effect) Memory {
1458 return .{ .argmem = effect, .inaccessiblemem = effect, .other = effect };
1459 }
14331460 };
14341461
14351462 pub const UwTable = enum(u32) {
......@@ -1683,17 +1710,17 @@ pub const FunctionAttributes = enum(u32) {
16831710};
16841711
16851712pub const Linkage = enum {
1686 external,
16871713 private,
16881714 internal,
1689 available_externally,
1690 linkonce,
16911715 weak,
1692 common,
1716 weak_odr,
1717 linkonce,
1718 linkonce_odr,
1719 available_externally,
16931720 appending,
1721 common,
16941722 extern_weak,
1695 linkonce_odr,
1696 weak_odr,
1723 external,
16971724
16981725 pub fn format(
16991726 self: Linkage,
......@@ -1703,6 +1730,22 @@ pub const Linkage = enum {
17031730 ) @TypeOf(writer).Error!void {
17041731 if (self != .external) try writer.print(" {s}", .{@tagName(self)});
17051732 }
1733
1734 fn toLlvm(self: Linkage) llvm.Linkage {
1735 return switch (self) {
1736 .private => .Private,
1737 .internal => .Internal,
1738 .weak => .WeakAny,
1739 .weak_odr => .WeakODR,
1740 .linkonce => .LinkOnceAny,
1741 .linkonce_odr => .LinkOnceODR,
1742 .available_externally => .AvailableExternally,
1743 .appending => .Appending,
1744 .common => .Common,
1745 .extern_weak => .ExternalWeak,
1746 .external => .External,
1747 };
1748 }
17061749};
17071750
17081751pub const Preemption = enum {
......@@ -1733,6 +1776,14 @@ pub const Visibility = enum {
17331776 ) @TypeOf(writer).Error!void {
17341777 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
17351778 }
1779
1780 fn toLlvm(self: Visibility) llvm.Visibility {
1781 return switch (self) {
1782 .default => .Default,
1783 .hidden => .Hidden,
1784 .protected => .Protected,
1785 };
1786 }
17361787};
17371788
17381789pub const DllStorageClass = enum {
......@@ -1748,6 +1799,14 @@ pub const DllStorageClass = enum {
17481799 ) @TypeOf(writer).Error!void {
17491800 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
17501801 }
1802
1803 fn toLlvm(self: DllStorageClass) llvm.DLLStorageClass {
1804 return switch (self) {
1805 .default => .Default,
1806 .dllimport => .DLLImport,
1807 .dllexport => .DLLExport,
1808 };
1809 }
17511810};
17521811
17531812pub const ThreadLocal = enum {
......@@ -1759,20 +1818,28 @@ pub const ThreadLocal = enum {
17591818
17601819 pub fn format(
17611820 self: ThreadLocal,
1762 comptime _: []const u8,
1821 comptime prefix: []const u8,
17631822 _: std.fmt.FormatOptions,
17641823 writer: anytype,
17651824 ) @TypeOf(writer).Error!void {
17661825 if (self == .default) return;
1767 try writer.writeAll(" thread_local");
1768 if (self != .generaldynamic) {
1769 try writer.writeByte('(');
1770 try writer.writeAll(@tagName(self));
1771 try writer.writeByte(')');
1772 }
1826 try writer.print("{s}thread_local", .{prefix});
1827 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});
1828 }
1829
1830 fn toLlvm(self: ThreadLocal) llvm.ThreadLocalMode {
1831 return switch (self) {
1832 .default => .NotThreadLocal,
1833 .generaldynamic => .GeneralDynamicTLSModel,
1834 .localdynamic => .LocalDynamicTLSModel,
1835 .initialexec => .InitialExecTLSModel,
1836 .localexec => .LocalExecTLSModel,
1837 };
17731838 }
17741839};
17751840
1841pub const Mutability = enum { global, constant };
1842
17761843pub const UnnamedAddr = enum {
17771844 default,
17781845 unnamed_addr,
......@@ -1867,7 +1934,7 @@ pub const AddrSpace = enum(u24) {
18671934 _: std.fmt.FormatOptions,
18681935 writer: anytype,
18691936 ) @TypeOf(writer).Error!void {
1870 if (self != .default) try writer.print("{s} addrspace({d})", .{ prefix, @intFromEnum(self) });
1937 if (self != .default) try writer.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });
18711938 }
18721939};
18731940
......@@ -1908,7 +1975,7 @@ pub const Alignment = enum(u6) {
19081975 _: std.fmt.FormatOptions,
19091976 writer: anytype,
19101977 ) @TypeOf(writer).Error!void {
1911 try writer.print("{s} align {d}", .{ prefix, self.toByteUnits() orelse return });
1978 try writer.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });
19121979 }
19131980};
19141981
......@@ -2031,6 +2098,11 @@ pub const CallConv = enum(u10) {
20312098 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),
20322099 }
20332100 }
2101
2102 fn toLlvm(self: CallConv) llvm.CallConv {
2103 // These enum values appear in LLVM IR, and so are guaranteed to be stable.
2104 return @enumFromInt(@intFromEnum(self));
2105 }
20342106};
20352107
20362108pub const Global = struct {
......@@ -2067,10 +2139,6 @@ pub const Global = struct {
20672139 return self.unwrap(builder) == other.unwrap(builder);
20682140 }
20692141
2070 pub fn name(self: Index, builder: *const Builder) String {
2071 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
2072 }
2073
20742142 pub fn ptr(self: Index, builder: *Builder) *Global {
20752143 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
20762144 }
......@@ -2079,6 +2147,10 @@ pub const Global = struct {
20792147 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
20802148 }
20812149
2150 pub fn name(self: Index, builder: *const Builder) String {
2151 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
2152 }
2153
20822154 pub fn typeOf(self: Index, builder: *const Builder) Type {
20832155 return self.ptrConst(builder).type;
20842156 }
......@@ -2087,6 +2159,30 @@ pub const Global = struct {
20872159 return @enumFromInt(@intFromEnum(Constant.first_global) + @intFromEnum(self));
20882160 }
20892161
2162 pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void {
2163 if (builder.useLibLlvm()) self.toLlvm(builder).setLinkage(linkage.toLlvm());
2164 self.ptr(builder).linkage = linkage;
2165 self.updateDsoLocal(builder);
2166 }
2167
2168 pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void {
2169 if (builder.useLibLlvm()) self.toLlvm(builder).setVisibility(visibility.toLlvm());
2170 self.ptr(builder).visibility = visibility;
2171 self.updateDsoLocal(builder);
2172 }
2173
2174 pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void {
2175 if (builder.useLibLlvm()) self.toLlvm(builder).setDLLStorageClass(class.toLlvm());
2176 self.ptr(builder).dll_storage_class = class;
2177 }
2178
2179 pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void {
2180 if (builder.useLibLlvm()) self.toLlvm(builder).setUnnamedAddr(
2181 llvm.Bool.fromBool(unnamed_addr != .default),
2182 );
2183 self.ptr(builder).unnamed_addr = unnamed_addr;
2184 }
2185
20902186 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
20912187 assert(builder.useLibLlvm());
20922188 return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))];
......@@ -2122,9 +2218,36 @@ pub const Global = struct {
21222218
21232219 pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
21242220 try builder.ensureUnusedGlobalCapacity(.empty);
2221 if (builder.useLibLlvm())
2222 try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1);
21252223 self.replaceAssumeCapacity(other, builder);
21262224 }
21272225
2226 pub fn delete(self: Index, builder: *Builder) void {
2227 if (builder.useLibLlvm()) self.toLlvm(builder).eraseGlobalValue();
2228 self.ptr(builder).kind = .{ .replaced = .none };
2229 }
2230
2231 fn updateDsoLocal(self: Index, builder: *Builder) void {
2232 const self_ptr = self.ptr(builder);
2233 switch (self_ptr.linkage) {
2234 .private, .internal => {
2235 self_ptr.visibility = .default;
2236 self_ptr.dll_storage_class = .default;
2237 self_ptr.preemption = .implicit_dso_local;
2238 },
2239 .extern_weak => if (self_ptr.preemption == .implicit_dso_local) {
2240 self_ptr.preemption = .dso_local;
2241 },
2242 else => switch (self_ptr.visibility) {
2243 .default => if (self_ptr.preemption == .implicit_dso_local) {
2244 self_ptr.preemption = .dso_local;
2245 },
2246 else => self_ptr.preemption = .implicit_dso_local,
2247 },
2248 }
2249 }
2250
21282251 fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void {
21292252 const old_name = self.name(builder);
21302253 if (new_name == old_name) return;
......@@ -2151,7 +2274,7 @@ pub const Global = struct {
21512274 if (!builder.useLibLlvm()) return;
21522275 const index = @intFromEnum(self.unwrap(builder));
21532276 const name_slice = self.name(builder).slice(builder) orelse "";
2154 builder.llvm.globals.items[index].setValueName2(name_slice.ptr, name_slice.len);
2277 builder.llvm.globals.items[index].setValueName(name_slice.ptr, name_slice.len);
21552278 }
21562279
21572280 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
......@@ -2161,13 +2284,8 @@ pub const Global = struct {
21612284 if (builder.useLibLlvm()) {
21622285 const self_llvm = self.toLlvm(builder);
21632286 self_llvm.replaceAllUsesWith(other.toLlvm(builder));
2164 switch (self.ptr(builder).kind) {
2165 .alias,
2166 .variable,
2167 => self_llvm.deleteGlobal(),
2168 .function => self_llvm.deleteFunction(),
2169 .replaced => unreachable,
2170 }
2287 self_llvm.removeGlobalValue();
2288 builder.llvm.replacements.putAssumeCapacityNoClobber(self_llvm, other);
21712289 }
21722290 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
21732291 }
......@@ -2179,42 +2297,17 @@ pub const Global = struct {
21792297 };
21802298 }
21812299 };
2182
2183 pub fn updateAttributes(self: *Global) void {
2184 switch (self.linkage) {
2185 .private, .internal => {
2186 self.visibility = .default;
2187 self.dll_storage_class = .default;
2188 self.preemption = .implicit_dso_local;
2189 },
2190 .extern_weak => if (self.preemption == .implicit_dso_local) {
2191 self.preemption = .dso_local;
2192 },
2193 else => switch (self.visibility) {
2194 .default => if (self.preemption == .implicit_dso_local) {
2195 self.preemption = .dso_local;
2196 },
2197 else => self.preemption = .implicit_dso_local,
2198 },
2199 }
2200 }
22012300};
22022301
22032302pub const Alias = struct {
22042303 global: Global.Index,
22052304 thread_local: ThreadLocal = .default,
2206 init: Constant = .no_init,
2305 aliasee: Constant = .no_init,
22072306
22082307 pub const Index = enum(u32) {
22092308 none = std.math.maxInt(u32),
22102309 _,
22112310
2212 pub fn getAliasee(self: Index, builder: *const Builder) Global.Index {
2213 const aliasee = self.ptrConst(builder).init.getBase(builder);
2214 assert(aliasee != .none);
2215 return aliasee;
2216 }
2217
22182311 pub fn ptr(self: Index, builder: *Builder) *Alias {
22192312 return &builder.aliases.items[@intFromEnum(self)];
22202313 }
......@@ -2223,6 +2316,14 @@ pub const Alias = struct {
22232316 return &builder.aliases.items[@intFromEnum(self)];
22242317 }
22252318
2319 pub fn name(self: Index, builder: *const Builder) String {
2320 return self.ptrConst(builder).global.name(builder);
2321 }
2322
2323 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
2324 return self.ptrConst(builder).global.rename(new_name, builder);
2325 }
2326
22262327 pub fn typeOf(self: Index, builder: *const Builder) Type {
22272328 return self.ptrConst(builder).global.typeOf(builder);
22282329 }
......@@ -2235,7 +2336,18 @@ pub const Alias = struct {
22352336 return self.toConst(builder).toValue();
22362337 }
22372338
2238 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
2339 pub fn getAliasee(self: Index, builder: *const Builder) Global.Index {
2340 const aliasee = self.ptrConst(builder).aliasee.getBase(builder);
2341 assert(aliasee != .none);
2342 return aliasee;
2343 }
2344
2345 pub fn setAliasee(self: Index, aliasee: Constant, builder: *Builder) void {
2346 if (builder.useLibLlvm()) self.toLlvm(builder).setAliasee(aliasee.toLlvm(builder));
2347 self.ptr(builder).aliasee = aliasee;
2348 }
2349
2350 fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
22392351 return self.ptrConst(builder).global.toLlvm(builder);
22402352 }
22412353 };
......@@ -2244,7 +2356,7 @@ pub const Alias = struct {
22442356pub const Variable = struct {
22452357 global: Global.Index,
22462358 thread_local: ThreadLocal = .default,
2247 mutability: enum { global, constant } = .global,
2359 mutability: Mutability = .global,
22482360 init: Constant = .no_init,
22492361 section: String = .none,
22502362 alignment: Alignment = .default,
......@@ -2261,6 +2373,14 @@ pub const Variable = struct {
22612373 return &builder.variables.items[@intFromEnum(self)];
22622374 }
22632375
2376 pub fn name(self: Index, builder: *const Builder) String {
2377 return self.ptrConst(builder).global.name(builder);
2378 }
2379
2380 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
2381 return self.ptrConst(builder).global.rename(new_name, builder);
2382 }
2383
22642384 pub fn typeOf(self: Index, builder: *const Builder) Type {
22652385 return self.ptrConst(builder).global.typeOf(builder);
22662386 }
......@@ -2269,14 +2389,1407 @@ pub const Variable = struct {
22692389 return self.ptrConst(builder).global.toConst();
22702390 }
22712391
2272 pub fn toValue(self: Index, builder: *const Builder) Value {
2273 return self.toConst(builder).toValue();
2274 }
2392 pub fn toValue(self: Index, builder: *const Builder) Value {
2393 return self.toConst(builder).toValue();
2394 }
2395
2396 pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void {
2397 return self.ptrConst(builder).global.setLinkage(linkage, builder);
2398 }
2399
2400 pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void {
2401 return self.ptrConst(builder).global.setUnnamedAddr(unnamed_addr, builder);
2402 }
2403
2404 pub fn setThreadLocal(self: Index, thread_local: ThreadLocal, builder: *Builder) void {
2405 if (builder.useLibLlvm()) self.toLlvm(builder).setThreadLocalMode(thread_local.toLlvm());
2406 self.ptr(builder).thread_local = thread_local;
2407 }
2408
2409 pub fn setMutability(self: Index, mutability: Mutability, builder: *Builder) void {
2410 if (builder.useLibLlvm()) self.toLlvm(builder).setGlobalConstant(
2411 llvm.Bool.fromBool(mutability == .constant),
2412 );
2413 self.ptr(builder).mutability = mutability;
2414 }
2415
2416 pub fn setInitializer(
2417 self: Index,
2418 initializer: Constant,
2419 builder: *Builder,
2420 ) Allocator.Error!void {
2421 if (initializer != .no_init) {
2422 const variable = self.ptrConst(builder);
2423 const global = variable.global.ptr(builder);
2424 const initializer_type = initializer.typeOf(builder);
2425 if (builder.useLibLlvm() and global.type != initializer_type) {
2426 try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1);
2427 // LLVM does not allow us to change the type of globals. So we must
2428 // create a new global with the correct type, copy all its attributes,
2429 // and then update all references to point to the new global,
2430 // delete the original, and rename the new one to the old one's name.
2431 // This is necessary because LLVM does not support const bitcasting
2432 // a struct with padding bytes, which is needed to lower a const union value
2433 // to LLVM, when a field other than the most-aligned is active. Instead,
2434 // we must lower to an unnamed struct, and pointer cast at usage sites
2435 // of the global. Such an unnamed struct is the cause of the global type
2436 // mismatch, because we don't have the LLVM type until the *value* is created,
2437 // whereas the global needs to be created based on the type alone, because
2438 // lowering the value may reference the global as a pointer.
2439 // Related: https://github.com/ziglang/zig/issues/13265
2440 const old_global = &builder.llvm.globals.items[@intFromEnum(variable.global)];
2441 const new_global = builder.llvm.module.?.addGlobalInAddressSpace(
2442 initializer_type.toLlvm(builder),
2443 "",
2444 @intFromEnum(global.addr_space),
2445 );
2446 new_global.setLinkage(global.linkage.toLlvm());
2447 new_global.setUnnamedAddr(llvm.Bool.fromBool(global.unnamed_addr != .default));
2448 new_global.setAlignment(@intCast(variable.alignment.toByteUnits() orelse 0));
2449 if (variable.section != .none)
2450 new_global.setSection(variable.section.slice(builder).?);
2451 old_global.*.replaceAllUsesWith(new_global);
2452 builder.llvm.replacements.putAssumeCapacityNoClobber(old_global.*, variable.global);
2453 new_global.takeName(old_global.*);
2454 old_global.*.removeGlobalValue();
2455 old_global.* = new_global;
2456 self.ptr(builder).mutability = .global;
2457 }
2458 global.type = initializer_type;
2459 }
2460 if (builder.useLibLlvm()) self.toLlvm(builder).setInitializer(switch (initializer) {
2461 .no_init => null,
2462 else => initializer.toLlvm(builder),
2463 });
2464 self.ptr(builder).init = initializer;
2465 }
2466
2467 pub fn setSection(self: Index, section: String, builder: *Builder) void {
2468 if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?);
2469 self.ptr(builder).section = section;
2470 }
2471
2472 pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void {
2473 if (builder.useLibLlvm())
2474 self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0));
2475 self.ptr(builder).alignment = alignment;
2476 }
2477
2478 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
2479 return self.ptrConst(builder).global.toLlvm(builder);
2480 }
2481 };
2482};
2483
2484pub const Intrinsic = enum {
2485 // Variable Argument Handling
2486 va_start,
2487 va_end,
2488 va_copy,
2489
2490 // Code Generator
2491 returnaddress,
2492 addressofreturnaddress,
2493 sponentry,
2494 frameaddress,
2495 prefetch,
2496 @"thread.pointer",
2497
2498 // Standard C/C++ Library
2499 abs,
2500 smax,
2501 smin,
2502 umax,
2503 umin,
2504 memcpy,
2505 @"memcpy.inline",
2506 memmove,
2507 memset,
2508 @"memset.inline",
2509 sqrt,
2510 powi,
2511 sin,
2512 cos,
2513 pow,
2514 exp,
2515 exp2,
2516 ldexp,
2517 frexp,
2518 log,
2519 log10,
2520 log2,
2521 fma,
2522 fabs,
2523 minnum,
2524 maxnum,
2525 minimum,
2526 maximum,
2527 copysign,
2528 floor,
2529 ceil,
2530 trunc,
2531 rint,
2532 nearbyint,
2533 round,
2534 roundeven,
2535 lround,
2536 llround,
2537 lrint,
2538 llrint,
2539
2540 // Bit Manipulation
2541 bitreverse,
2542 bswap,
2543 ctpop,
2544 ctlz,
2545 cttz,
2546 fshl,
2547 fshr,
2548
2549 // Arithmetic with Overflow
2550 @"sadd.with.overflow",
2551 @"uadd.with.overflow",
2552 @"ssub.with.overflow",
2553 @"usub.with.overflow",
2554 @"smul.with.overflow",
2555 @"umul.with.overflow",
2556
2557 // Saturation Arithmetic
2558 @"sadd.sat",
2559 @"uadd.sat",
2560 @"ssub.sat",
2561 @"usub.sat",
2562 @"sshl.sat",
2563 @"ushl.sat",
2564
2565 // Fixed Point Arithmetic
2566 @"smul.fix",
2567 @"umul.fix",
2568 @"smul.fix.sat",
2569 @"umul.fix.sat",
2570 @"sdiv.fix",
2571 @"udiv.fix",
2572 @"sdiv.fix.sat",
2573 @"udiv.fix.sat",
2574
2575 // Specialised Arithmetic
2576 canonicalize,
2577 fmuladd,
2578
2579 // Vector Reduction
2580 @"vector.reduce.add",
2581 @"vector.reduce.fadd",
2582 @"vector.reduce.mul",
2583 @"vector.reduce.fmul",
2584 @"vector.reduce.and",
2585 @"vector.reduce.or",
2586 @"vector.reduce.xor",
2587 @"vector.reduce.smax",
2588 @"vector.reduce.smin",
2589 @"vector.reduce.umax",
2590 @"vector.reduce.umin",
2591 @"vector.reduce.fmax",
2592 @"vector.reduce.fmin",
2593 @"vector.reduce.fmaximum",
2594 @"vector.reduce.fminimum",
2595 @"vector.insert",
2596 @"vector.extract",
2597
2598 // Floating-Point Test
2599 @"is.fpclass",
2600
2601 // General
2602 @"var.annotation",
2603 @"ptr.annotation",
2604 annotation,
2605 @"codeview.annotation",
2606 trap,
2607 debugtrap,
2608 ubsantrap,
2609 stackprotector,
2610 stackguard,
2611 objectsize,
2612 expect,
2613 @"expect.with.probability",
2614 assume,
2615 @"ssa.copy",
2616 @"type.test",
2617 @"type.checked.load",
2618 @"type.checked.load.relative",
2619 @"arithmetic.fence",
2620 donothing,
2621 @"load.relative",
2622 sideeffect,
2623 @"is.constant",
2624 ptrmask,
2625 @"threadlocal.address",
2626 vscale,
2627
2628 // AMDGPU
2629 @"amdgcn.workitem.id.x",
2630 @"amdgcn.workitem.id.y",
2631 @"amdgcn.workitem.id.z",
2632 @"amdgcn.workgroup.id.x",
2633 @"amdgcn.workgroup.id.y",
2634 @"amdgcn.workgroup.id.z",
2635 @"amdgcn.dispatch.ptr",
2636
2637 // WebAssembly
2638 @"wasm.memory.size",
2639 @"wasm.memory.grow",
2640
2641 const Signature = struct {
2642 ret_len: u8,
2643 params: []const Parameter,
2644 attrs: []const Attribute = &.{},
2645
2646 const Parameter = struct {
2647 kind: Kind,
2648 attrs: []const Attribute = &.{},
2649
2650 const Kind = union(enum) {
2651 type: Type,
2652 overloaded,
2653 matches: u8,
2654 matches_scalar: u8,
2655 matches_changed_scalar: struct {
2656 index: u8,
2657 scalar: Type,
2658 },
2659 };
2660 };
2661 };
2662
2663 const signatures = std.enums.EnumArray(Intrinsic, Signature).init(.{
2664 .va_start = .{
2665 .ret_len = 0,
2666 .params = &.{
2667 .{ .kind = .{ .type = .ptr } },
2668 },
2669 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
2670 },
2671 .va_end = .{
2672 .ret_len = 0,
2673 .params = &.{
2674 .{ .kind = .{ .type = .ptr } },
2675 },
2676 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
2677 },
2678 .va_copy = .{
2679 .ret_len = 0,
2680 .params = &.{
2681 .{ .kind = .{ .type = .ptr } },
2682 .{ .kind = .{ .type = .ptr } },
2683 },
2684 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
2685 },
2686
2687 .returnaddress = .{
2688 .ret_len = 1,
2689 .params = &.{
2690 .{ .kind = .{ .type = .ptr } },
2691 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
2692 },
2693 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2694 },
2695 .addressofreturnaddress = .{
2696 .ret_len = 1,
2697 .params = &.{
2698 .{ .kind = .overloaded },
2699 },
2700 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2701 },
2702 .sponentry = .{
2703 .ret_len = 1,
2704 .params = &.{
2705 .{ .kind = .overloaded },
2706 },
2707 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2708 },
2709 .frameaddress = .{
2710 .ret_len = 1,
2711 .params = &.{
2712 .{ .kind = .overloaded },
2713 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
2714 },
2715 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2716 },
2717 .prefetch = .{
2718 .ret_len = 0,
2719 .params = &.{
2720 .{ .kind = .overloaded, .attrs = &.{ .nocapture, .readonly } },
2721 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
2722 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
2723 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
2724 },
2725 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.readwrite) } },
2726 },
2727 .@"thread.pointer" = .{
2728 .ret_len = 1,
2729 .params = &.{
2730 .{ .kind = .{ .type = .ptr } },
2731 },
2732 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2733 },
2734
2735 .abs = .{
2736 .ret_len = 1,
2737 .params = &.{
2738 .{ .kind = .overloaded },
2739 .{ .kind = .{ .matches = 0 } },
2740 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
2741 },
2742 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2743 },
2744 .smax = .{
2745 .ret_len = 1,
2746 .params = &.{
2747 .{ .kind = .overloaded },
2748 .{ .kind = .{ .matches = 0 } },
2749 .{ .kind = .{ .matches = 0 } },
2750 },
2751 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2752 },
2753 .smin = .{
2754 .ret_len = 1,
2755 .params = &.{
2756 .{ .kind = .overloaded },
2757 .{ .kind = .{ .matches = 0 } },
2758 .{ .kind = .{ .matches = 0 } },
2759 },
2760 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2761 },
2762 .umax = .{
2763 .ret_len = 1,
2764 .params = &.{
2765 .{ .kind = .overloaded },
2766 .{ .kind = .{ .matches = 0 } },
2767 .{ .kind = .{ .matches = 0 } },
2768 },
2769 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2770 },
2771 .umin = .{
2772 .ret_len = 1,
2773 .params = &.{
2774 .{ .kind = .overloaded },
2775 .{ .kind = .{ .matches = 0 } },
2776 .{ .kind = .{ .matches = 0 } },
2777 },
2778 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2779 },
2780 .memcpy = .{
2781 .ret_len = 0,
2782 .params = &.{
2783 .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .writeonly } },
2784 .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .readonly } },
2785 .{ .kind = .overloaded },
2786 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
2787 },
2788 .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .readwrite } } },
2789 },
2790 .@"memcpy.inline" = .{
2791 .ret_len = 0,
2792 .params = &.{
2793 .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .writeonly } },
2794 .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .readonly } },
2795 .{ .kind = .overloaded, .attrs = &.{.immarg} },
2796 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
2797 },
2798 .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .readwrite } } },
2799 },
2800 .memmove = .{
2801 .ret_len = 0,
2802 .params = &.{
2803 .{ .kind = .overloaded, .attrs = &.{ .nocapture, .writeonly } },
2804 .{ .kind = .overloaded, .attrs = &.{ .nocapture, .readonly } },
2805 .{ .kind = .overloaded },
2806 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
2807 },
2808 .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .readwrite } } },
2809 },
2810 .memset = .{
2811 .ret_len = 0,
2812 .params = &.{
2813 .{ .kind = .overloaded, .attrs = &.{ .nocapture, .writeonly } },
2814 .{ .kind = .{ .type = .i8 } },
2815 .{ .kind = .overloaded },
2816 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
2817 },
2818 .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .write } } },
2819 },
2820 .@"memset.inline" = .{
2821 .ret_len = 0,
2822 .params = &.{
2823 .{ .kind = .overloaded, .attrs = &.{ .nocapture, .writeonly } },
2824 .{ .kind = .{ .type = .i8 } },
2825 .{ .kind = .overloaded, .attrs = &.{.immarg} },
2826 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
2827 },
2828 .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .write } } },
2829 },
2830 .sqrt = .{
2831 .ret_len = 1,
2832 .params = &.{
2833 .{ .kind = .overloaded },
2834 .{ .kind = .{ .matches = 0 } },
2835 },
2836 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2837 },
2838 .powi = .{
2839 .ret_len = 1,
2840 .params = &.{
2841 .{ .kind = .overloaded },
2842 .{ .kind = .{ .matches = 0 } },
2843 .{ .kind = .overloaded },
2844 },
2845 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2846 },
2847 .sin = .{
2848 .ret_len = 1,
2849 .params = &.{
2850 .{ .kind = .overloaded },
2851 .{ .kind = .{ .matches = 0 } },
2852 },
2853 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2854 },
2855 .cos = .{
2856 .ret_len = 1,
2857 .params = &.{
2858 .{ .kind = .overloaded },
2859 .{ .kind = .{ .matches = 0 } },
2860 },
2861 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2862 },
2863 .pow = .{
2864 .ret_len = 1,
2865 .params = &.{
2866 .{ .kind = .overloaded },
2867 .{ .kind = .{ .matches = 0 } },
2868 .{ .kind = .{ .matches = 0 } },
2869 },
2870 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2871 },
2872 .exp = .{
2873 .ret_len = 1,
2874 .params = &.{
2875 .{ .kind = .overloaded },
2876 .{ .kind = .{ .matches = 0 } },
2877 },
2878 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2879 },
2880 .exp2 = .{
2881 .ret_len = 1,
2882 .params = &.{
2883 .{ .kind = .overloaded },
2884 .{ .kind = .{ .matches = 0 } },
2885 },
2886 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2887 },
2888 .ldexp = .{
2889 .ret_len = 1,
2890 .params = &.{
2891 .{ .kind = .overloaded },
2892 .{ .kind = .{ .matches = 0 } },
2893 .{ .kind = .overloaded },
2894 },
2895 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2896 },
2897 .frexp = .{
2898 .ret_len = 2,
2899 .params = &.{
2900 .{ .kind = .overloaded },
2901 .{ .kind = .overloaded },
2902 .{ .kind = .{ .matches = 0 } },
2903 },
2904 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2905 },
2906 .log = .{
2907 .ret_len = 1,
2908 .params = &.{
2909 .{ .kind = .overloaded },
2910 .{ .kind = .{ .matches = 0 } },
2911 },
2912 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2913 },
2914 .log10 = .{
2915 .ret_len = 1,
2916 .params = &.{
2917 .{ .kind = .overloaded },
2918 .{ .kind = .{ .matches = 0 } },
2919 },
2920 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2921 },
2922 .log2 = .{
2923 .ret_len = 1,
2924 .params = &.{
2925 .{ .kind = .overloaded },
2926 .{ .kind = .{ .matches = 0 } },
2927 },
2928 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2929 },
2930 .fma = .{
2931 .ret_len = 1,
2932 .params = &.{
2933 .{ .kind = .overloaded },
2934 .{ .kind = .{ .matches = 0 } },
2935 .{ .kind = .{ .matches = 0 } },
2936 .{ .kind = .{ .matches = 0 } },
2937 },
2938 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2939 },
2940 .fabs = .{
2941 .ret_len = 1,
2942 .params = &.{
2943 .{ .kind = .overloaded },
2944 .{ .kind = .{ .matches = 0 } },
2945 },
2946 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2947 },
2948 .minnum = .{
2949 .ret_len = 1,
2950 .params = &.{
2951 .{ .kind = .overloaded },
2952 .{ .kind = .{ .matches = 0 } },
2953 .{ .kind = .{ .matches = 0 } },
2954 },
2955 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2956 },
2957 .maxnum = .{
2958 .ret_len = 1,
2959 .params = &.{
2960 .{ .kind = .overloaded },
2961 .{ .kind = .{ .matches = 0 } },
2962 .{ .kind = .{ .matches = 0 } },
2963 },
2964 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2965 },
2966 .minimum = .{
2967 .ret_len = 1,
2968 .params = &.{
2969 .{ .kind = .overloaded },
2970 .{ .kind = .{ .matches = 0 } },
2971 .{ .kind = .{ .matches = 0 } },
2972 },
2973 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2974 },
2975 .maximum = .{
2976 .ret_len = 1,
2977 .params = &.{
2978 .{ .kind = .overloaded },
2979 .{ .kind = .{ .matches = 0 } },
2980 .{ .kind = .{ .matches = 0 } },
2981 },
2982 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2983 },
2984 .copysign = .{
2985 .ret_len = 1,
2986 .params = &.{
2987 .{ .kind = .overloaded },
2988 .{ .kind = .{ .matches = 0 } },
2989 .{ .kind = .{ .matches = 0 } },
2990 },
2991 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
2992 },
2993 .floor = .{
2994 .ret_len = 1,
2995 .params = &.{
2996 .{ .kind = .overloaded },
2997 .{ .kind = .{ .matches = 0 } },
2998 },
2999 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3000 },
3001 .ceil = .{
3002 .ret_len = 1,
3003 .params = &.{
3004 .{ .kind = .overloaded },
3005 .{ .kind = .{ .matches = 0 } },
3006 },
3007 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3008 },
3009 .trunc = .{
3010 .ret_len = 1,
3011 .params = &.{
3012 .{ .kind = .overloaded },
3013 .{ .kind = .{ .matches = 0 } },
3014 },
3015 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3016 },
3017 .rint = .{
3018 .ret_len = 1,
3019 .params = &.{
3020 .{ .kind = .overloaded },
3021 .{ .kind = .{ .matches = 0 } },
3022 },
3023 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3024 },
3025 .nearbyint = .{
3026 .ret_len = 1,
3027 .params = &.{
3028 .{ .kind = .overloaded },
3029 .{ .kind = .{ .matches = 0 } },
3030 },
3031 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3032 },
3033 .round = .{
3034 .ret_len = 1,
3035 .params = &.{
3036 .{ .kind = .overloaded },
3037 .{ .kind = .{ .matches = 0 } },
3038 },
3039 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3040 },
3041 .roundeven = .{
3042 .ret_len = 1,
3043 .params = &.{
3044 .{ .kind = .overloaded },
3045 .{ .kind = .{ .matches = 0 } },
3046 },
3047 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3048 },
3049 .lround = .{
3050 .ret_len = 1,
3051 .params = &.{
3052 .{ .kind = .overloaded },
3053 .{ .kind = .overloaded },
3054 },
3055 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3056 },
3057 .llround = .{
3058 .ret_len = 1,
3059 .params = &.{
3060 .{ .kind = .overloaded },
3061 .{ .kind = .overloaded },
3062 },
3063 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3064 },
3065 .lrint = .{
3066 .ret_len = 1,
3067 .params = &.{
3068 .{ .kind = .overloaded },
3069 .{ .kind = .overloaded },
3070 },
3071 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3072 },
3073 .llrint = .{
3074 .ret_len = 1,
3075 .params = &.{
3076 .{ .kind = .overloaded },
3077 .{ .kind = .overloaded },
3078 },
3079 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3080 },
3081
3082 .bitreverse = .{
3083 .ret_len = 1,
3084 .params = &.{
3085 .{ .kind = .overloaded },
3086 .{ .kind = .{ .matches = 0 } },
3087 },
3088 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3089 },
3090 .bswap = .{
3091 .ret_len = 1,
3092 .params = &.{
3093 .{ .kind = .overloaded },
3094 .{ .kind = .{ .matches = 0 } },
3095 },
3096 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3097 },
3098 .ctpop = .{
3099 .ret_len = 1,
3100 .params = &.{
3101 .{ .kind = .overloaded },
3102 .{ .kind = .{ .matches = 0 } },
3103 },
3104 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3105 },
3106 .ctlz = .{
3107 .ret_len = 1,
3108 .params = &.{
3109 .{ .kind = .overloaded },
3110 .{ .kind = .{ .matches = 0 } },
3111 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
3112 },
3113 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3114 },
3115 .cttz = .{
3116 .ret_len = 1,
3117 .params = &.{
3118 .{ .kind = .overloaded },
3119 .{ .kind = .{ .matches = 0 } },
3120 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
3121 },
3122 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3123 },
3124 .fshl = .{
3125 .ret_len = 1,
3126 .params = &.{
3127 .{ .kind = .overloaded },
3128 .{ .kind = .{ .matches = 0 } },
3129 .{ .kind = .{ .matches = 0 } },
3130 .{ .kind = .{ .matches = 0 } },
3131 },
3132 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3133 },
3134 .fshr = .{
3135 .ret_len = 1,
3136 .params = &.{
3137 .{ .kind = .overloaded },
3138 .{ .kind = .{ .matches = 0 } },
3139 .{ .kind = .{ .matches = 0 } },
3140 .{ .kind = .{ .matches = 0 } },
3141 },
3142 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3143 },
3144
3145 .@"sadd.with.overflow" = .{
3146 .ret_len = 2,
3147 .params = &.{
3148 .{ .kind = .overloaded },
3149 .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } },
3150 .{ .kind = .{ .matches = 0 } },
3151 .{ .kind = .{ .matches = 0 } },
3152 },
3153 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3154 },
3155 .@"uadd.with.overflow" = .{
3156 .ret_len = 2,
3157 .params = &.{
3158 .{ .kind = .overloaded },
3159 .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } },
3160 .{ .kind = .{ .matches = 0 } },
3161 .{ .kind = .{ .matches = 0 } },
3162 },
3163 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3164 },
3165 .@"ssub.with.overflow" = .{
3166 .ret_len = 2,
3167 .params = &.{
3168 .{ .kind = .overloaded },
3169 .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } },
3170 .{ .kind = .{ .matches = 0 } },
3171 .{ .kind = .{ .matches = 0 } },
3172 },
3173 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3174 },
3175 .@"usub.with.overflow" = .{
3176 .ret_len = 2,
3177 .params = &.{
3178 .{ .kind = .overloaded },
3179 .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } },
3180 .{ .kind = .{ .matches = 0 } },
3181 .{ .kind = .{ .matches = 0 } },
3182 },
3183 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3184 },
3185 .@"smul.with.overflow" = .{
3186 .ret_len = 2,
3187 .params = &.{
3188 .{ .kind = .overloaded },
3189 .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } },
3190 .{ .kind = .{ .matches = 0 } },
3191 .{ .kind = .{ .matches = 0 } },
3192 },
3193 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3194 },
3195 .@"umul.with.overflow" = .{
3196 .ret_len = 2,
3197 .params = &.{
3198 .{ .kind = .overloaded },
3199 .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } },
3200 .{ .kind = .{ .matches = 0 } },
3201 .{ .kind = .{ .matches = 0 } },
3202 },
3203 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3204 },
3205
3206 .@"sadd.sat" = .{
3207 .ret_len = 1,
3208 .params = &.{
3209 .{ .kind = .overloaded },
3210 .{ .kind = .{ .matches = 0 } },
3211 .{ .kind = .{ .matches = 0 } },
3212 },
3213 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3214 },
3215 .@"uadd.sat" = .{
3216 .ret_len = 1,
3217 .params = &.{
3218 .{ .kind = .overloaded },
3219 .{ .kind = .{ .matches = 0 } },
3220 .{ .kind = .{ .matches = 0 } },
3221 },
3222 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3223 },
3224 .@"ssub.sat" = .{
3225 .ret_len = 1,
3226 .params = &.{
3227 .{ .kind = .overloaded },
3228 .{ .kind = .{ .matches = 0 } },
3229 .{ .kind = .{ .matches = 0 } },
3230 },
3231 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3232 },
3233 .@"usub.sat" = .{
3234 .ret_len = 1,
3235 .params = &.{
3236 .{ .kind = .overloaded },
3237 .{ .kind = .{ .matches = 0 } },
3238 .{ .kind = .{ .matches = 0 } },
3239 },
3240 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3241 },
3242 .@"sshl.sat" = .{
3243 .ret_len = 1,
3244 .params = &.{
3245 .{ .kind = .overloaded },
3246 .{ .kind = .{ .matches = 0 } },
3247 .{ .kind = .{ .matches = 0 } },
3248 },
3249 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3250 },
3251 .@"ushl.sat" = .{
3252 .ret_len = 1,
3253 .params = &.{
3254 .{ .kind = .overloaded },
3255 .{ .kind = .{ .matches = 0 } },
3256 .{ .kind = .{ .matches = 0 } },
3257 },
3258 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3259 },
3260
3261 .@"smul.fix" = .{
3262 .ret_len = 1,
3263 .params = &.{
3264 .{ .kind = .overloaded },
3265 .{ .kind = .{ .matches = 0 } },
3266 .{ .kind = .{ .matches = 0 } },
3267 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3268 },
3269 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3270 },
3271 .@"umul.fix" = .{
3272 .ret_len = 1,
3273 .params = &.{
3274 .{ .kind = .overloaded },
3275 .{ .kind = .{ .matches = 0 } },
3276 .{ .kind = .{ .matches = 0 } },
3277 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3278 },
3279 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3280 },
3281 .@"smul.fix.sat" = .{
3282 .ret_len = 1,
3283 .params = &.{
3284 .{ .kind = .overloaded },
3285 .{ .kind = .{ .matches = 0 } },
3286 .{ .kind = .{ .matches = 0 } },
3287 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3288 },
3289 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3290 },
3291 .@"umul.fix.sat" = .{
3292 .ret_len = 1,
3293 .params = &.{
3294 .{ .kind = .overloaded },
3295 .{ .kind = .{ .matches = 0 } },
3296 .{ .kind = .{ .matches = 0 } },
3297 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3298 },
3299 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3300 },
3301 .@"sdiv.fix" = .{
3302 .ret_len = 1,
3303 .params = &.{
3304 .{ .kind = .overloaded },
3305 .{ .kind = .{ .matches = 0 } },
3306 .{ .kind = .{ .matches = 0 } },
3307 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3308 },
3309 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3310 },
3311 .@"udiv.fix" = .{
3312 .ret_len = 1,
3313 .params = &.{
3314 .{ .kind = .overloaded },
3315 .{ .kind = .{ .matches = 0 } },
3316 .{ .kind = .{ .matches = 0 } },
3317 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3318 },
3319 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3320 },
3321 .@"sdiv.fix.sat" = .{
3322 .ret_len = 1,
3323 .params = &.{
3324 .{ .kind = .overloaded },
3325 .{ .kind = .{ .matches = 0 } },
3326 .{ .kind = .{ .matches = 0 } },
3327 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3328 },
3329 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3330 },
3331 .@"udiv.fix.sat" = .{
3332 .ret_len = 1,
3333 .params = &.{
3334 .{ .kind = .overloaded },
3335 .{ .kind = .{ .matches = 0 } },
3336 .{ .kind = .{ .matches = 0 } },
3337 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3338 },
3339 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3340 },
3341
3342 .canonicalize = .{
3343 .ret_len = 1,
3344 .params = &.{
3345 .{ .kind = .overloaded },
3346 .{ .kind = .{ .matches = 0 } },
3347 },
3348 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3349 },
3350 .fmuladd = .{
3351 .ret_len = 1,
3352 .params = &.{
3353 .{ .kind = .overloaded },
3354 .{ .kind = .{ .matches = 0 } },
3355 .{ .kind = .{ .matches = 0 } },
3356 .{ .kind = .{ .matches = 0 } },
3357 },
3358 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3359 },
3360
3361 .@"vector.reduce.add" = .{
3362 .ret_len = 1,
3363 .params = &.{
3364 .{ .kind = .{ .matches_scalar = 1 } },
3365 .{ .kind = .overloaded },
3366 },
3367 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3368 },
3369 .@"vector.reduce.fadd" = .{
3370 .ret_len = 1,
3371 .params = &.{
3372 .{ .kind = .{ .matches_scalar = 2 } },
3373 .{ .kind = .{ .matches_scalar = 2 } },
3374 .{ .kind = .overloaded },
3375 },
3376 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3377 },
3378 .@"vector.reduce.mul" = .{
3379 .ret_len = 1,
3380 .params = &.{
3381 .{ .kind = .{ .matches_scalar = 1 } },
3382 .{ .kind = .overloaded },
3383 },
3384 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3385 },
3386 .@"vector.reduce.fmul" = .{
3387 .ret_len = 1,
3388 .params = &.{
3389 .{ .kind = .{ .matches_scalar = 2 } },
3390 .{ .kind = .{ .matches_scalar = 2 } },
3391 .{ .kind = .overloaded },
3392 },
3393 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3394 },
3395 .@"vector.reduce.and" = .{
3396 .ret_len = 1,
3397 .params = &.{
3398 .{ .kind = .{ .matches_scalar = 1 } },
3399 .{ .kind = .overloaded },
3400 },
3401 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3402 },
3403 .@"vector.reduce.or" = .{
3404 .ret_len = 1,
3405 .params = &.{
3406 .{ .kind = .{ .matches_scalar = 1 } },
3407 .{ .kind = .overloaded },
3408 },
3409 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3410 },
3411 .@"vector.reduce.xor" = .{
3412 .ret_len = 1,
3413 .params = &.{
3414 .{ .kind = .{ .matches_scalar = 1 } },
3415 .{ .kind = .overloaded },
3416 },
3417 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3418 },
3419 .@"vector.reduce.smax" = .{
3420 .ret_len = 1,
3421 .params = &.{
3422 .{ .kind = .{ .matches_scalar = 1 } },
3423 .{ .kind = .overloaded },
3424 },
3425 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3426 },
3427 .@"vector.reduce.smin" = .{
3428 .ret_len = 1,
3429 .params = &.{
3430 .{ .kind = .{ .matches_scalar = 1 } },
3431 .{ .kind = .overloaded },
3432 },
3433 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3434 },
3435 .@"vector.reduce.umax" = .{
3436 .ret_len = 1,
3437 .params = &.{
3438 .{ .kind = .{ .matches_scalar = 1 } },
3439 .{ .kind = .overloaded },
3440 },
3441 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3442 },
3443 .@"vector.reduce.umin" = .{
3444 .ret_len = 1,
3445 .params = &.{
3446 .{ .kind = .{ .matches_scalar = 1 } },
3447 .{ .kind = .overloaded },
3448 },
3449 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3450 },
3451 .@"vector.reduce.fmax" = .{
3452 .ret_len = 1,
3453 .params = &.{
3454 .{ .kind = .{ .matches_scalar = 1 } },
3455 .{ .kind = .overloaded },
3456 },
3457 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3458 },
3459 .@"vector.reduce.fmin" = .{
3460 .ret_len = 1,
3461 .params = &.{
3462 .{ .kind = .{ .matches_scalar = 1 } },
3463 .{ .kind = .overloaded },
3464 },
3465 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3466 },
3467 .@"vector.reduce.fmaximum" = .{
3468 .ret_len = 1,
3469 .params = &.{
3470 .{ .kind = .{ .matches_scalar = 1 } },
3471 .{ .kind = .overloaded },
3472 },
3473 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3474 },
3475 .@"vector.reduce.fminimum" = .{
3476 .ret_len = 1,
3477 .params = &.{
3478 .{ .kind = .{ .matches_scalar = 1 } },
3479 .{ .kind = .overloaded },
3480 },
3481 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3482 },
3483 .@"vector.insert" = .{
3484 .ret_len = 1,
3485 .params = &.{
3486 .{ .kind = .overloaded },
3487 .{ .kind = .{ .matches = 0 } },
3488 .{ .kind = .overloaded },
3489 .{ .kind = .{ .type = .i64 } },
3490 },
3491 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3492 },
3493 .@"vector.extract" = .{
3494 .ret_len = 1,
3495 .params = &.{
3496 .{ .kind = .overloaded },
3497 .{ .kind = .overloaded },
3498 .{ .kind = .{ .type = .i64 } },
3499 },
3500 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3501 },
3502
3503 .@"is.fpclass" = .{
3504 .ret_len = 1,
3505 .params = &.{
3506 .{ .kind = .{ .matches_changed_scalar = .{ .index = 1, .scalar = .i1 } } },
3507 .{ .kind = .overloaded },
3508 .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} },
3509 },
3510 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3511 },
3512
3513 .@"var.annotation" = .{
3514 .ret_len = 0,
3515 .params = &.{
3516 .{ .kind = .overloaded },
3517 .{ .kind = .overloaded },
3518 .{ .kind = .{ .matches = 1 } },
3519 .{ .kind = .{ .type = .i32 } },
3520 .{ .kind = .{ .matches = 1 } },
3521 },
3522 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } },
3523 },
3524 .@"ptr.annotation" = .{
3525 .ret_len = 1,
3526 .params = &.{
3527 .{ .kind = .overloaded },
3528 .{ .kind = .{ .matches = 0 } },
3529 .{ .kind = .overloaded },
3530 .{ .kind = .{ .matches = 2 } },
3531 .{ .kind = .{ .type = .i32 } },
3532 .{ .kind = .{ .matches = 2 } },
3533 },
3534 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } },
3535 },
3536 .annotation = .{
3537 .ret_len = 1,
3538 .params = &.{
3539 .{ .kind = .overloaded },
3540 .{ .kind = .{ .matches = 0 } },
3541 .{ .kind = .overloaded },
3542 .{ .kind = .{ .matches = 2 } },
3543 .{ .kind = .{ .type = .i32 } },
3544 },
3545 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } },
3546 },
3547 .@"codeview.annotation" = .{
3548 .ret_len = 0,
3549 .params = &.{
3550 .{ .kind = .{ .type = .metadata } },
3551 },
3552 .attrs = &.{ .nocallback, .noduplicate, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } },
3553 },
3554 .trap = .{
3555 .ret_len = 0,
3556 .params = &.{},
3557 .attrs = &.{ .cold, .noreturn, .nounwind, .{ .memory = .{ .inaccessiblemem = .write } } },
3558 },
3559 .debugtrap = .{
3560 .ret_len = 0,
3561 .params = &.{},
3562 .attrs = &.{.nounwind},
3563 },
3564 .ubsantrap = .{
3565 .ret_len = 0,
3566 .params = &.{
3567 .{ .kind = .{ .type = .i8 }, .attrs = &.{.immarg} },
3568 },
3569 .attrs = &.{ .cold, .noreturn, .nounwind },
3570 },
3571 .stackprotector = .{
3572 .ret_len = 0,
3573 .params = &.{
3574 .{ .kind = .{ .type = .ptr } },
3575 .{ .kind = .{ .type = .ptr } },
3576 },
3577 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
3578 },
3579 .stackguard = .{
3580 .ret_len = 1,
3581 .params = &.{
3582 .{ .kind = .{ .type = .ptr } },
3583 },
3584 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
3585 },
3586 .objectsize = .{
3587 .ret_len = 1,
3588 .params = &.{
3589 .{ .kind = .overloaded },
3590 .{ .kind = .overloaded },
3591 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
3592 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
3593 .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} },
3594 },
3595 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3596 },
3597 .expect = .{
3598 .ret_len = 1,
3599 .params = &.{
3600 .{ .kind = .overloaded },
3601 .{ .kind = .{ .matches = 0 } },
3602 .{ .kind = .{ .matches = 0 } },
3603 },
3604 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3605 },
3606 .@"expect.with.probability" = .{
3607 .ret_len = 1,
3608 .params = &.{
3609 .{ .kind = .overloaded },
3610 .{ .kind = .{ .matches = 0 } },
3611 .{ .kind = .{ .matches = 0 } },
3612 .{ .kind = .{ .type = .double }, .attrs = &.{.immarg} },
3613 },
3614 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3615 },
3616 .assume = .{
3617 .ret_len = 0,
3618 .params = &.{
3619 .{ .kind = .{ .type = .i1 }, .attrs = &.{.noundef} },
3620 },
3621 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .write } } },
3622 },
3623 .@"ssa.copy" = .{
3624 .ret_len = 1,
3625 .params = &.{
3626 .{ .kind = .overloaded },
3627 .{ .kind = .{ .matches = 0 }, .attrs = &.{.returned} },
3628 },
3629 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3630 },
3631 .@"type.test" = .{
3632 .ret_len = 1,
3633 .params = &.{
3634 .{ .kind = .{ .type = .i1 } },
3635 .{ .kind = .{ .type = .ptr } },
3636 .{ .kind = .{ .type = .metadata } },
3637 },
3638 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3639 },
3640 .@"type.checked.load" = .{
3641 .ret_len = 2,
3642 .params = &.{
3643 .{ .kind = .{ .type = .ptr } },
3644 .{ .kind = .{ .type = .i1 } },
3645 .{ .kind = .{ .type = .ptr } },
3646 .{ .kind = .{ .type = .i32 } },
3647 .{ .kind = .{ .type = .metadata } },
3648 },
3649 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3650 },
3651 .@"type.checked.load.relative" = .{
3652 .ret_len = 2,
3653 .params = &.{
3654 .{ .kind = .{ .type = .ptr } },
3655 .{ .kind = .{ .type = .i1 } },
3656 .{ .kind = .{ .type = .ptr } },
3657 .{ .kind = .{ .type = .i32 } },
3658 .{ .kind = .{ .type = .metadata } },
3659 },
3660 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3661 },
3662 .@"arithmetic.fence" = .{
3663 .ret_len = 1,
3664 .params = &.{
3665 .{ .kind = .overloaded },
3666 .{ .kind = .{ .matches = 0 } },
3667 },
3668 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3669 },
3670 .donothing = .{
3671 .ret_len = 0,
3672 .params = &.{},
3673 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3674 },
3675 .@"load.relative" = .{
3676 .ret_len = 1,
3677 .params = &.{
3678 .{ .kind = .{ .type = .ptr } },
3679 .{ .kind = .{ .type = .ptr } },
3680 .{ .kind = .overloaded },
3681 },
3682 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .argmem = .read } } },
3683 },
3684 .sideeffect = .{
3685 .ret_len = 0,
3686 .params = &.{},
3687 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } },
3688 },
3689 .@"is.constant" = .{
3690 .ret_len = 1,
3691 .params = &.{
3692 .{ .kind = .{ .type = .i1 } },
3693 .{ .kind = .overloaded },
3694 },
3695 .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3696 },
3697 .ptrmask = .{
3698 .ret_len = 1,
3699 .params = &.{
3700 .{ .kind = .overloaded },
3701 .{ .kind = .{ .matches = 0 } },
3702 .{ .kind = .overloaded },
3703 },
3704 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3705 },
3706 .@"threadlocal.address" = .{
3707 .ret_len = 1,
3708 .params = &.{
3709 .{ .kind = .overloaded, .attrs = &.{.nonnull} },
3710 .{ .kind = .{ .matches = 0 }, .attrs = &.{.nonnull} },
3711 },
3712 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3713 },
3714 .vscale = .{
3715 .ret_len = 1,
3716 .params = &.{
3717 .{ .kind = .overloaded },
3718 },
3719 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3720 },
3721
3722 .@"amdgcn.workitem.id.x" = .{
3723 .ret_len = 1,
3724 .params = &.{
3725 .{ .kind = .{ .type = .i32 } },
3726 },
3727 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3728 },
3729 .@"amdgcn.workitem.id.y" = .{
3730 .ret_len = 1,
3731 .params = &.{
3732 .{ .kind = .{ .type = .i32 } },
3733 },
3734 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3735 },
3736 .@"amdgcn.workitem.id.z" = .{
3737 .ret_len = 1,
3738 .params = &.{
3739 .{ .kind = .{ .type = .i32 } },
3740 },
3741 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3742 },
3743 .@"amdgcn.workgroup.id.x" = .{
3744 .ret_len = 1,
3745 .params = &.{
3746 .{ .kind = .{ .type = .i32 } },
3747 },
3748 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3749 },
3750 .@"amdgcn.workgroup.id.y" = .{
3751 .ret_len = 1,
3752 .params = &.{
3753 .{ .kind = .{ .type = .i32 } },
3754 },
3755 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3756 },
3757 .@"amdgcn.workgroup.id.z" = .{
3758 .ret_len = 1,
3759 .params = &.{
3760 .{ .kind = .{ .type = .i32 } },
3761 },
3762 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3763 },
3764 .@"amdgcn.dispatch.ptr" = .{
3765 .ret_len = 1,
3766 .params = &.{
3767 .{
3768 .kind = .{ .type = Type.ptr_amdgpu_constant },
3769 .attrs = &.{.{ .@"align" = Builder.Alignment.fromByteUnits(4) }},
3770 },
3771 },
3772 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3773 },
22753774
2276 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
2277 return self.ptrConst(builder).global.toLlvm(builder);
2278 }
2279 };
3775 .@"wasm.memory.size" = .{
3776 .ret_len = 1,
3777 .params = &.{
3778 .{ .kind = .overloaded },
3779 .{ .kind = .{ .type = .i32 } },
3780 },
3781 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } },
3782 },
3783 .@"wasm.memory.grow" = .{
3784 .ret_len = 1,
3785 .params = &.{
3786 .{ .kind = .overloaded },
3787 .{ .kind = .{ .type = .i32 } },
3788 .{ .kind = .{ .matches = 0 } },
3789 },
3790 .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn },
3791 },
3792 });
22803793};
22813794
22823795pub const Function = struct {
......@@ -2303,6 +3816,14 @@ pub const Function = struct {
23033816 return &builder.functions.items[@intFromEnum(self)];
23043817 }
23053818
3819 pub fn name(self: Index, builder: *const Builder) String {
3820 return self.ptrConst(builder).global.name(builder);
3821 }
3822
3823 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
3824 return self.ptrConst(builder).global.rename(new_name, builder);
3825 }
3826
23063827 pub fn typeOf(self: Index, builder: *const Builder) Type {
23073828 return self.ptrConst(builder).global.typeOf(builder);
23083829 }
......@@ -2315,6 +3836,110 @@ pub const Function = struct {
23153836 return self.toConst(builder).toValue();
23163837 }
23173838
3839 pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void {
3840 return self.ptrConst(builder).global.setLinkage(linkage, builder);
3841 }
3842
3843 pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void {
3844 return self.ptrConst(builder).global.setUnnamedAddr(unnamed_addr, builder);
3845 }
3846
3847 pub fn setCallConv(self: Index, call_conv: CallConv, builder: *Builder) void {
3848 if (builder.useLibLlvm()) self.toLlvm(builder).setFunctionCallConv(call_conv.toLlvm());
3849 self.ptr(builder).call_conv = call_conv;
3850 }
3851
3852 pub fn setAttributes(
3853 self: Index,
3854 new_function_attributes: FunctionAttributes,
3855 builder: *Builder,
3856 ) void {
3857 if (builder.useLibLlvm()) {
3858 const llvm_function = self.toLlvm(builder);
3859 const old_function_attributes = self.ptrConst(builder).attributes;
3860 for (0..@max(
3861 old_function_attributes.slice(builder).len,
3862 new_function_attributes.slice(builder).len,
3863 )) |function_attribute_index| {
3864 const llvm_attribute_index =
3865 @as(llvm.AttributeIndex, @intCast(function_attribute_index)) -% 1;
3866 const old_attributes_slice =
3867 old_function_attributes.get(function_attribute_index, builder).slice(builder);
3868 const new_attributes_slice =
3869 new_function_attributes.get(function_attribute_index, builder).slice(builder);
3870 var old_attribute_index: usize = 0;
3871 var new_attribute_index: usize = 0;
3872 while (true) {
3873 const old_attribute_kind = if (old_attribute_index < old_attributes_slice.len)
3874 old_attributes_slice[old_attribute_index].getKind(builder)
3875 else
3876 .none;
3877 const new_attribute_kind = if (new_attribute_index < new_attributes_slice.len)
3878 new_attributes_slice[new_attribute_index].getKind(builder)
3879 else
3880 .none;
3881 switch (std.math.order(
3882 @intFromEnum(old_attribute_kind),
3883 @intFromEnum(new_attribute_kind),
3884 )) {
3885 .lt => {
3886 // Removed
3887 if (old_attribute_kind.toString()) |attribute_name| {
3888 const attribute_name_slice = attribute_name.slice(builder).?;
3889 llvm_function.removeStringAttributeAtIndex(
3890 llvm_attribute_index,
3891 attribute_name_slice.ptr,
3892 @intCast(attribute_name_slice.len),
3893 );
3894 } else {
3895 const llvm_kind_id = old_attribute_kind.toLlvm(builder).*;
3896 assert(llvm_kind_id != 0);
3897 llvm_function.removeEnumAttributeAtIndex(
3898 llvm_attribute_index,
3899 llvm_kind_id,
3900 );
3901 }
3902 old_attribute_index += 1;
3903 continue;
3904 },
3905 .eq => {
3906 // Iteration finished
3907 if (old_attribute_kind == .none) break;
3908 // No change
3909 if (old_attributes_slice[old_attribute_index] ==
3910 new_attributes_slice[new_attribute_index])
3911 {
3912 old_attribute_index += 1;
3913 new_attribute_index += 1;
3914 continue;
3915 }
3916 old_attribute_index += 1;
3917 },
3918 .gt => {},
3919 }
3920 // New or changed
3921 llvm_function.addAttributeAtIndex(
3922 llvm_attribute_index,
3923 new_attributes_slice[new_attribute_index].toLlvm(builder),
3924 );
3925 new_attribute_index += 1;
3926 }
3927 }
3928 }
3929 self.ptr(builder).attributes = new_function_attributes;
3930 }
3931
3932 pub fn setSection(self: Index, section: String, builder: *Builder) void {
3933 if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?);
3934 self.ptr(builder).section = section;
3935 }
3936
3937 pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void {
3938 if (builder.useLibLlvm())
3939 self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0));
3940 self.ptr(builder).alignment = alignment;
3941 }
3942
23183943 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
23193944 return self.ptrConst(builder).global.toLlvm(builder);
23203945 }
......@@ -2342,12 +3967,15 @@ pub const Function = struct {
23423967 arg,
23433968 ashr,
23443969 @"ashr exact",
3970 atomicrmw,
23453971 bitcast,
23463972 block,
23473973 br,
23483974 br_cond,
23493975 call,
23503976 @"call fast",
3977 cmpxchg,
3978 @"cmpxchg weak",
23513979 extractelement,
23523980 extractvalue,
23533981 fadd,
......@@ -2414,43 +4042,8 @@ pub const Function = struct {
24144042 insertelement,
24154043 insertvalue,
24164044 inttoptr,
2417 @"llvm.maxnum.",
2418 @"llvm.minnum.",
2419 @"llvm.ceil.",
2420 @"llvm.cos.",
2421 @"llvm.exp.",
2422 @"llvm.exp2.",
2423 @"llvm.fabs.",
2424 @"llvm.floor.",
2425 @"llvm.log.",
2426 @"llvm.log10.",
2427 @"llvm.log2.",
2428 @"llvm.round.",
2429 @"llvm.sin.",
2430 @"llvm.sqrt.",
2431 @"llvm.trunc.",
2432 @"llvm.fma.",
2433 @"llvm.bitreverse.",
2434 @"llvm.bswap.",
2435 @"llvm.ctpop.",
2436 @"llvm.ctlz.",
2437 @"llvm.cttz.",
2438 @"llvm.sadd.sat.",
2439 @"llvm.smax.",
2440 @"llvm.smin.",
2441 @"llvm.smul.fix.sat.",
2442 @"llvm.sshl.sat.",
2443 @"llvm.ssub.sat.",
2444 @"llvm.uadd.sat.",
2445 @"llvm.umax.",
2446 @"llvm.umin.",
2447 @"llvm.umul.fix.sat.",
2448 @"llvm.ushl.sat.",
2449 @"llvm.usub.sat.",
24504045 load,
24514046 @"load atomic",
2452 @"load atomic volatile",
2453 @"load volatile",
24544047 lshr,
24554048 @"lshr exact",
24564049 mul,
......@@ -2481,8 +4074,6 @@ pub const Function = struct {
24814074 srem,
24824075 store,
24834076 @"store atomic",
2484 @"store atomic volatile",
2485 @"store volatile",
24864077 sub,
24874078 @"sub nsw",
24884079 @"sub nuw",
......@@ -2495,7 +4086,6 @@ pub const Function = struct {
24954086 @"udiv exact",
24964087 urem,
24974088 uitofp,
2498 unimplemented,
24994089 @"unreachable",
25004090 va_arg,
25014091 xor,
......@@ -2536,8 +4126,6 @@ pub const Function = struct {
25364126 .@"ret void",
25374127 .store,
25384128 .@"store atomic",
2539 .@"store atomic volatile",
2540 .@"store volatile",
25414129 .@"switch",
25424130 .@"unreachable",
25434131 => false,
......@@ -2549,7 +4137,6 @@ pub const Function = struct {
25494137 .@"notail call fast",
25504138 .@"tail call",
25514139 .@"tail call fast",
2552 .unimplemented,
25534140 => self.typeOfWip(wip) != .void,
25544141 else => true,
25554142 };
......@@ -2575,22 +4162,6 @@ pub const Function = struct {
25754162 .@"frem fast",
25764163 .fsub,
25774164 .@"fsub fast",
2578 .@"llvm.maxnum.",
2579 .@"llvm.minnum.",
2580 .@"llvm.ctlz.",
2581 .@"llvm.cttz.",
2582 .@"llvm.sadd.sat.",
2583 .@"llvm.smax.",
2584 .@"llvm.smin.",
2585 .@"llvm.smul.fix.sat.",
2586 .@"llvm.sshl.sat.",
2587 .@"llvm.ssub.sat.",
2588 .@"llvm.uadd.sat.",
2589 .@"llvm.umax.",
2590 .@"llvm.umin.",
2591 .@"llvm.umul.fix.sat.",
2592 .@"llvm.ushl.sat.",
2593 .@"llvm.usub.sat.",
25944165 .lshr,
25954166 .@"lshr exact",
25964167 .mul,
......@@ -2635,6 +4206,7 @@ pub const Function = struct {
26354206 ),
26364207 .arg => wip.function.typeOf(wip.builder)
26374208 .functionParameters(wip.builder)[instruction.data],
4209 .atomicrmw => wip.extraData(AtomicRmw, instruction.data).val.typeOfWip(wip),
26384210 .block => .label,
26394211 .br,
26404212 .br_cond,
......@@ -2643,8 +4215,6 @@ pub const Function = struct {
26434215 .@"ret void",
26444216 .store,
26454217 .@"store atomic",
2646 .@"store atomic volatile",
2647 .@"store volatile",
26484218 .@"switch",
26494219 .@"unreachable",
26504220 => .none,
......@@ -2657,6 +4227,12 @@ pub const Function = struct {
26574227 .@"tail call",
26584228 .@"tail call fast",
26594229 => wip.extraData(Call, instruction.data).ty.functionReturn(wip.builder),
4230 .cmpxchg,
4231 .@"cmpxchg weak",
4232 => wip.builder.structTypeAssumeCapacity(.normal, &.{
4233 wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip),
4234 .i1,
4235 }) catch unreachable,
26604236 .extractelement => wip.extraData(ExtractElement, instruction.data)
26614237 .val.typeOfWip(wip).childType(wip.builder),
26624238 .extractvalue => {
......@@ -2710,22 +4286,6 @@ pub const Function = struct {
27104286 .changeScalarAssumeCapacity(.i1, wip.builder),
27114287 .fneg,
27124288 .@"fneg fast",
2713 .@"llvm.ceil.",
2714 .@"llvm.cos.",
2715 .@"llvm.exp.",
2716 .@"llvm.exp2.",
2717 .@"llvm.fabs.",
2718 .@"llvm.floor.",
2719 .@"llvm.log.",
2720 .@"llvm.log10.",
2721 .@"llvm.log2.",
2722 .@"llvm.round.",
2723 .@"llvm.sin.",
2724 .@"llvm.sqrt.",
2725 .@"llvm.trunc.",
2726 .@"llvm.bitreverse.",
2727 .@"llvm.bswap.",
2728 .@"llvm.ctpop.",
27294289 => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip),
27304290 .getelementptr,
27314291 .@"getelementptr inbounds",
......@@ -2744,8 +4304,6 @@ pub const Function = struct {
27444304 .insertvalue => wip.extraData(InsertValue, instruction.data).val.typeOfWip(wip),
27454305 .load,
27464306 .@"load atomic",
2747 .@"load atomic volatile",
2748 .@"load volatile",
27494307 => wip.extraData(Load, instruction.data).type,
27504308 .phi,
27514309 .@"phi fast",
......@@ -2760,9 +4318,7 @@ pub const Function = struct {
27604318 wip.builder,
27614319 );
27624320 },
2763 .unimplemented => @enumFromInt(instruction.data),
27644321 .va_arg => wip.extraData(VaArg, instruction.data).type,
2765 .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip),
27664322 };
27674323 }
27684324
......@@ -2791,22 +4347,6 @@ pub const Function = struct {
27914347 .@"frem fast",
27924348 .fsub,
27934349 .@"fsub fast",
2794 .@"llvm.maxnum.",
2795 .@"llvm.minnum.",
2796 .@"llvm.ctlz.",
2797 .@"llvm.cttz.",
2798 .@"llvm.sadd.sat.",
2799 .@"llvm.smax.",
2800 .@"llvm.smin.",
2801 .@"llvm.smul.fix.sat.",
2802 .@"llvm.sshl.sat.",
2803 .@"llvm.ssub.sat.",
2804 .@"llvm.uadd.sat.",
2805 .@"llvm.umax.",
2806 .@"llvm.umin.",
2807 .@"llvm.umul.fix.sat.",
2808 .@"llvm.ushl.sat.",
2809 .@"llvm.usub.sat.",
28104350 .lshr,
28114351 .@"lshr exact",
28124352 .mul,
......@@ -2851,6 +4391,8 @@ pub const Function = struct {
28514391 ),
28524392 .arg => function.global.typeOf(builder)
28534393 .functionParameters(builder)[instruction.data],
4394 .atomicrmw => function.extraData(AtomicRmw, instruction.data)
4395 .val.typeOf(function_index, builder),
28544396 .block => .label,
28554397 .br,
28564398 .br_cond,
......@@ -2859,8 +4401,6 @@ pub const Function = struct {
28594401 .@"ret void",
28604402 .store,
28614403 .@"store atomic",
2862 .@"store atomic volatile",
2863 .@"store volatile",
28644404 .@"switch",
28654405 .@"unreachable",
28664406 => .none,
......@@ -2873,6 +4413,13 @@ pub const Function = struct {
28734413 .@"tail call",
28744414 .@"tail call fast",
28754415 => function.extraData(Call, instruction.data).ty.functionReturn(builder),
4416 .cmpxchg,
4417 .@"cmpxchg weak",
4418 => builder.structTypeAssumeCapacity(.normal, &.{
4419 function.extraData(CmpXchg, instruction.data)
4420 .cmp.typeOf(function_index, builder),
4421 .i1,
4422 }) catch unreachable,
28764423 .extractelement => function.extraData(ExtractElement, instruction.data)
28774424 .val.typeOf(function_index, builder).childType(builder),
28784425 .extractvalue => {
......@@ -2927,22 +4474,6 @@ pub const Function = struct {
29274474 .changeScalarAssumeCapacity(.i1, builder),
29284475 .fneg,
29294476 .@"fneg fast",
2930 .@"llvm.ceil.",
2931 .@"llvm.cos.",
2932 .@"llvm.exp.",
2933 .@"llvm.exp2.",
2934 .@"llvm.fabs.",
2935 .@"llvm.floor.",
2936 .@"llvm.log.",
2937 .@"llvm.log10.",
2938 .@"llvm.log2.",
2939 .@"llvm.round.",
2940 .@"llvm.sin.",
2941 .@"llvm.sqrt.",
2942 .@"llvm.trunc.",
2943 .@"llvm.bitreverse.",
2944 .@"llvm.bswap.",
2945 .@"llvm.ctpop.",
29464477 => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder),
29474478 .getelementptr,
29484479 .@"getelementptr inbounds",
......@@ -2963,8 +4494,6 @@ pub const Function = struct {
29634494 .val.typeOf(function_index, builder),
29644495 .load,
29654496 .@"load atomic",
2966 .@"load atomic volatile",
2967 .@"load volatile",
29684497 => function.extraData(Load, instruction.data).type,
29694498 .phi,
29704499 .@"phi fast",
......@@ -2979,9 +4508,7 @@ pub const Function = struct {
29794508 builder,
29804509 );
29814510 },
2982 .unimplemented => @enumFromInt(instruction.data),
29834511 .va_arg => function.extraData(VaArg, instruction.data).type,
2984 .@"llvm.fma." => function.extraData(FusedMultiplyAdd, instruction.data).a.typeOf(function_index, builder),
29854512 };
29864513 }
29874514
......@@ -3023,12 +4550,14 @@ pub const Function = struct {
30234550 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };
30244551 }
30254552
3026 pub fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value {
4553 fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value {
30274554 assert(wip.builder.useLibLlvm());
3028 return wip.llvm.instructions.items[@intFromEnum(self)];
4555 const llvm_value = wip.llvm.instructions.items[@intFromEnum(self)];
4556 const global = wip.builder.llvm.replacements.get(llvm_value) orelse return llvm_value;
4557 return global.toLlvm(wip.builder);
30294558 }
30304559
3031 fn llvmName(self: Instruction.Index, wip: *const WipFunction) [*:0]const u8 {
4560 fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 {
30324561 return if (wip.builder.strip)
30334562 ""
30344563 else
......@@ -3074,12 +4603,6 @@ pub const Function = struct {
30744603 mask: Value,
30754604 };
30764605
3077 pub const FusedMultiplyAdd = struct {
3078 a: Value,
3079 b: Value,
3080 c: Value,
3081 };
3082
30834606 pub const ExtractValue = struct {
30844607 val: Value,
30854608 indices_len: u32,
......@@ -3107,15 +4630,70 @@ pub const Function = struct {
31074630 };
31084631
31094632 pub const Load = struct {
4633 info: MemoryAccessInfo,
31104634 type: Type,
31114635 ptr: Value,
3112 info: MemoryAccessInfo,
31134636 };
31144637
31154638 pub const Store = struct {
4639 info: MemoryAccessInfo,
31164640 val: Value,
31174641 ptr: Value,
4642 };
4643
4644 pub const CmpXchg = struct {
4645 info: MemoryAccessInfo,
4646 ptr: Value,
4647 cmp: Value,
4648 new: Value,
4649
4650 pub const Kind = enum { strong, weak };
4651 };
4652
4653 pub const AtomicRmw = struct {
31184654 info: MemoryAccessInfo,
4655 ptr: Value,
4656 val: Value,
4657
4658 pub const Operation = enum(u5) {
4659 xchg,
4660 add,
4661 sub,
4662 @"and",
4663 nand,
4664 @"or",
4665 xor,
4666 max,
4667 min,
4668 umax,
4669 umin,
4670 fadd,
4671 fsub,
4672 fmax,
4673 fmin,
4674 none = std.math.maxInt(u5),
4675
4676 fn toLlvm(self: Operation) llvm.AtomicRMWBinOp {
4677 return switch (self) {
4678 .xchg => .Xchg,
4679 .add => .Add,
4680 .sub => .Sub,
4681 .@"and" => .And,
4682 .nand => .Nand,
4683 .@"or" => .Or,
4684 .xor => .Xor,
4685 .max => .Max,
4686 .min => .Min,
4687 .umax => .UMax,
4688 .umin => .UMin,
4689 .fadd => .FAdd,
4690 .fsub => .FSub,
4691 .fmax => .FMax,
4692 .fmin => .FMin,
4693 .none => unreachable,
4694 };
4695 }
4696 };
31194697 };
31204698
31214699 pub const GetElementPtr = struct {
......@@ -3487,24 +5065,7 @@ pub const WipFunction = struct {
34875065 switch (tag) {
34885066 .fneg,
34895067 .@"fneg fast",
3490 .@"llvm.ceil.",
3491 .@"llvm.cos.",
3492 .@"llvm.exp.",
3493 .@"llvm.exp2.",
3494 .@"llvm.fabs.",
3495 .@"llvm.floor.",
3496 .@"llvm.log.",
3497 .@"llvm.log10.",
3498 .@"llvm.log2.",
3499 .@"llvm.round.",
3500 .@"llvm.sin.",
3501 .@"llvm.sqrt.",
3502 .@"llvm.trunc.",
35035068 => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()),
3504 .@"llvm.bitreverse.",
3505 .@"llvm.bswap.",
3506 .@"llvm.ctpop.",
3507 => assert(val.typeOfWip(self).scalarType(self.builder).isInteger(self.builder)),
35085069 else => unreachable,
35095070 }
35105071 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
......@@ -3513,43 +5074,10 @@ pub const WipFunction = struct {
35135074 switch (tag) {
35145075 .fneg => self.llvm.builder.setFastMath(false),
35155076 .@"fneg fast" => self.llvm.builder.setFastMath(true),
3516 .@"llvm.ceil.",
3517 .@"llvm.cos.",
3518 .@"llvm.exp.",
3519 .@"llvm.exp2.",
3520 .@"llvm.fabs.",
3521 .@"llvm.floor.",
3522 .@"llvm.log.",
3523 .@"llvm.log10.",
3524 .@"llvm.log2.",
3525 .@"llvm.round.",
3526 .@"llvm.sin.",
3527 .@"llvm.sqrt.",
3528 .@"llvm.trunc.",
3529 .@"llvm.bitreverse.",
3530 .@"llvm.bswap.",
3531 .@"llvm.ctpop.",
3532 => {},
35335077 else => unreachable,
35345078 }
35355079 self.llvm.instructions.appendAssumeCapacity(switch (tag) {
35365080 .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg,
3537 .@"llvm.ceil." => &llvm.Builder.buildCeil,
3538 .@"llvm.cos." => &llvm.Builder.buildCos,
3539 .@"llvm.exp." => &llvm.Builder.buildExp,
3540 .@"llvm.exp2." => &llvm.Builder.buildExp2,
3541 .@"llvm.fabs." => &llvm.Builder.buildFAbs,
3542 .@"llvm.floor." => &llvm.Builder.buildFloor,
3543 .@"llvm.log." => &llvm.Builder.buildLog,
3544 .@"llvm.log10." => &llvm.Builder.buildLog10,
3545 .@"llvm.log2." => &llvm.Builder.buildLog2,
3546 .@"llvm.round." => &llvm.Builder.buildRound,
3547 .@"llvm.sin." => &llvm.Builder.buildSin,
3548 .@"llvm.sqrt." => &llvm.Builder.buildSqrt,
3549 .@"llvm.trunc." => &llvm.Builder.buildFTrunc,
3550 .@"llvm.bitreverse." => &llvm.Builder.buildBitReverse,
3551 .@"llvm.bswap." => &llvm.Builder.buildBSwap,
3552 .@"llvm.ctpop." => &llvm.Builder.buildCTPop,
35535081 else => unreachable,
35545082 }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self)));
35555083 }
......@@ -3593,20 +5121,6 @@ pub const WipFunction = struct {
35935121 .@"frem fast",
35945122 .fsub,
35955123 .@"fsub fast",
3596 .@"llvm.maxnum.",
3597 .@"llvm.minnum.",
3598 .@"llvm.sadd.sat.",
3599 .@"llvm.smax.",
3600 .@"llvm.smin.",
3601 .@"llvm.smul.fix.sat.",
3602 .@"llvm.sshl.sat.",
3603 .@"llvm.ssub.sat.",
3604 .@"llvm.uadd.sat.",
3605 .@"llvm.umax.",
3606 .@"llvm.umin.",
3607 .@"llvm.umul.fix.sat.",
3608 .@"llvm.ushl.sat.",
3609 .@"llvm.usub.sat.",
36105124 .lshr,
36115125 .@"lshr exact",
36125126 .mul,
......@@ -3627,9 +5141,6 @@ pub const WipFunction = struct {
36275141 .urem,
36285142 .xor,
36295143 => assert(lhs.typeOfWip(self) == rhs.typeOfWip(self)),
3630 .@"llvm.ctlz.",
3631 .@"llvm.cttz.",
3632 => assert(lhs.typeOfWip(self).scalarType(self.builder).isInteger(self.builder) and rhs.typeOfWip(self) == .i1),
36335144 else => unreachable,
36345145 }
36355146 try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0);
......@@ -3665,22 +5176,6 @@ pub const WipFunction = struct {
36655176 .fmul, .@"fmul fast" => &llvm.Builder.buildFMul,
36665177 .frem, .@"frem fast" => &llvm.Builder.buildFRem,
36675178 .fsub, .@"fsub fast" => &llvm.Builder.buildFSub,
3668 .@"llvm.maxnum." => &llvm.Builder.buildMaxNum,
3669 .@"llvm.minnum." => &llvm.Builder.buildMinNum,
3670 .@"llvm.ctlz." => &llvm.Builder.buildCTLZ,
3671 .@"llvm.cttz." => &llvm.Builder.buildCTTZ,
3672 .@"llvm.sadd.sat." => &llvm.Builder.buildSAddSat,
3673 .@"llvm.smax." => &llvm.Builder.buildSMax,
3674 .@"llvm.smin." => &llvm.Builder.buildSMin,
3675 .@"llvm.smul.fix.sat." => &llvm.Builder.buildSMulFixSat,
3676 .@"llvm.sshl.sat." => &llvm.Builder.buildSShlSat,
3677 .@"llvm.ssub.sat." => &llvm.Builder.buildSSubSat,
3678 .@"llvm.uadd.sat." => &llvm.Builder.buildUAddSat,
3679 .@"llvm.umax." => &llvm.Builder.buildUMax,
3680 .@"llvm.umin." => &llvm.Builder.buildUMin,
3681 .@"llvm.umul.fix.sat." => &llvm.Builder.buildUMulFixSat,
3682 .@"llvm.ushl.sat." => &llvm.Builder.buildUShlSat,
3683 .@"llvm.usub.sat." => &llvm.Builder.buildUSubSat,
36845179 .lshr => &llvm.Builder.buildLShr,
36855180 .@"lshr exact" => &llvm.Builder.buildLShrExact,
36865181 .mul => &llvm.Builder.buildMul,
......@@ -3934,21 +5429,21 @@ pub const WipFunction = struct {
39345429
39355430 pub fn load(
39365431 self: *WipFunction,
3937 kind: MemoryAccessKind,
5432 access_kind: MemoryAccessKind,
39385433 ty: Type,
39395434 ptr: Value,
39405435 alignment: Alignment,
39415436 name: []const u8,
39425437 ) Allocator.Error!Value {
3943 return self.loadAtomic(kind, ty, ptr, .system, .none, alignment, name);
5438 return self.loadAtomic(access_kind, ty, ptr, .system, .none, alignment, name);
39445439 }
39455440
39465441 pub fn loadAtomic(
39475442 self: *WipFunction,
3948 kind: MemoryAccessKind,
5443 access_kind: MemoryAccessKind,
39495444 ty: Type,
39505445 ptr: Value,
3951 scope: SyncScope,
5446 sync_scope: SyncScope,
39525447 ordering: AtomicOrdering,
39535448 alignment: Alignment,
39545449 name: []const u8,
......@@ -3957,22 +5452,21 @@ pub const WipFunction = struct {
39575452 try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0);
39585453 const instruction = try self.addInst(name, .{
39595454 .tag = switch (ordering) {
3960 .none => switch (kind) {
3961 .normal => .load,
3962 .@"volatile" => .@"load volatile",
3963 },
3964 else => switch (kind) {
3965 .normal => .@"load atomic",
3966 .@"volatile" => .@"load atomic volatile",
3967 },
5455 .none => .load,
5456 else => .@"load atomic",
39685457 },
39695458 .data = self.addExtraAssumeCapacity(Instruction.Load{
5459 .info = .{
5460 .access_kind = access_kind,
5461 .sync_scope = switch (ordering) {
5462 .none => .system,
5463 else => sync_scope,
5464 },
5465 .success_ordering = ordering,
5466 .alignment = alignment,
5467 },
39705468 .type = ty,
39715469 .ptr = ptr,
3972 .info = .{ .scope = switch (ordering) {
3973 .none => .system,
3974 else => scope,
3975 }, .ordering = ordering, .alignment = alignment },
39765470 }),
39775471 });
39785472 if (self.builder.useLibLlvm()) {
......@@ -3981,7 +5475,8 @@ pub const WipFunction = struct {
39815475 ptr.toLlvm(self),
39825476 instruction.llvmName(self),
39835477 );
3984 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
5478 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5479 if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm());
39855480 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
39865481 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
39875482 }
......@@ -4000,10 +5495,10 @@ pub const WipFunction = struct {
40005495
40015496 pub fn storeAtomic(
40025497 self: *WipFunction,
4003 kind: MemoryAccessKind,
5498 access_kind: MemoryAccessKind,
40045499 val: Value,
40055500 ptr: Value,
4006 scope: SyncScope,
5501 sync_scope: SyncScope,
40075502 ordering: AtomicOrdering,
40085503 alignment: Alignment,
40095504 ) Allocator.Error!Instruction.Index {
......@@ -4011,31 +5506,27 @@ pub const WipFunction = struct {
40115506 try self.ensureUnusedExtraCapacity(1, Instruction.Store, 0);
40125507 const instruction = try self.addInst(null, .{
40135508 .tag = switch (ordering) {
4014 .none => switch (kind) {
4015 .normal => .store,
4016 .@"volatile" => .@"store volatile",
4017 },
4018 else => switch (kind) {
4019 .normal => .@"store atomic",
4020 .@"volatile" => .@"store atomic volatile",
4021 },
5509 .none => .store,
5510 else => .@"store atomic",
40225511 },
40235512 .data = self.addExtraAssumeCapacity(Instruction.Store{
5513 .info = .{
5514 .access_kind = access_kind,
5515 .sync_scope = switch (ordering) {
5516 .none => .system,
5517 else => sync_scope,
5518 },
5519 .success_ordering = ordering,
5520 .alignment = alignment,
5521 },
40245522 .val = val,
40255523 .ptr = ptr,
4026 .info = .{ .scope = switch (ordering) {
4027 .none => .system,
4028 else => scope,
4029 }, .ordering = ordering, .alignment = alignment },
40305524 }),
40315525 });
40325526 if (self.builder.useLibLlvm()) {
40335527 const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self));
4034 switch (kind) {
4035 .normal => {},
4036 .@"volatile" => llvm_instruction.setVolatile(.True),
4037 }
4038 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
5528 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5529 if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm());
40395530 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
40405531 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
40415532 }
......@@ -4044,7 +5535,7 @@ pub const WipFunction = struct {
40445535
40455536 pub fn fence(
40465537 self: *WipFunction,
4047 scope: SyncScope,
5538 sync_scope: SyncScope,
40485539 ordering: AtomicOrdering,
40495540 ) Allocator.Error!Instruction.Index {
40505541 assert(ordering != .none);
......@@ -4052,21 +5543,130 @@ pub const WipFunction = struct {
40525543 const instruction = try self.addInst(null, .{
40535544 .tag = .fence,
40545545 .data = @bitCast(MemoryAccessInfo{
4055 .scope = scope,
4056 .ordering = ordering,
4057 .alignment = undefined,
5546 .sync_scope = sync_scope,
5547 .success_ordering = ordering,
40585548 }),
40595549 });
40605550 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
40615551 self.llvm.builder.buildFence(
4062 @enumFromInt(@intFromEnum(ordering)),
4063 llvm.Bool.fromBool(scope == .singlethread),
5552 ordering.toLlvm(),
5553 llvm.Bool.fromBool(sync_scope == .singlethread),
40645554 "",
40655555 ),
40665556 );
40675557 return instruction;
40685558 }
40695559
5560 pub fn cmpxchg(
5561 self: *WipFunction,
5562 kind: Instruction.CmpXchg.Kind,
5563 access_kind: MemoryAccessKind,
5564 ptr: Value,
5565 cmp: Value,
5566 new: Value,
5567 sync_scope: SyncScope,
5568 success_ordering: AtomicOrdering,
5569 failure_ordering: AtomicOrdering,
5570 alignment: Alignment,
5571 name: []const u8,
5572 ) Allocator.Error!Value {
5573 assert(ptr.typeOfWip(self).isPointer(self.builder));
5574 const ty = cmp.typeOfWip(self);
5575 assert(ty == new.typeOfWip(self));
5576 assert(success_ordering != .none);
5577 assert(failure_ordering != .none);
5578
5579 _ = try self.builder.structType(.normal, &.{ ty, .i1 });
5580 try self.ensureUnusedExtraCapacity(1, Instruction.CmpXchg, 0);
5581 const instruction = try self.addInst(name, .{
5582 .tag = switch (kind) {
5583 .strong => .cmpxchg,
5584 .weak => .@"cmpxchg weak",
5585 },
5586 .data = self.addExtraAssumeCapacity(Instruction.CmpXchg{
5587 .info = .{
5588 .access_kind = access_kind,
5589 .sync_scope = sync_scope,
5590 .success_ordering = success_ordering,
5591 .failure_ordering = failure_ordering,
5592 .alignment = alignment,
5593 },
5594 .ptr = ptr,
5595 .cmp = cmp,
5596 .new = new,
5597 }),
5598 });
5599 if (self.builder.useLibLlvm()) {
5600 const llvm_instruction = self.llvm.builder.buildAtomicCmpXchg(
5601 ptr.toLlvm(self),
5602 cmp.toLlvm(self),
5603 new.toLlvm(self),
5604 success_ordering.toLlvm(),
5605 failure_ordering.toLlvm(),
5606 llvm.Bool.fromBool(sync_scope == .singlethread),
5607 );
5608 if (kind == .weak) llvm_instruction.setWeak(.True);
5609 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5610 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5611 const llvm_name = instruction.llvmName(self);
5612 if (llvm_name.len > 0) llvm_instruction.setValueName(
5613 llvm_name.ptr,
5614 @intCast(llvm_name.len),
5615 );
5616 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5617 }
5618 return instruction.toValue();
5619 }
5620
5621 pub fn atomicrmw(
5622 self: *WipFunction,
5623 access_kind: MemoryAccessKind,
5624 operation: Instruction.AtomicRmw.Operation,
5625 ptr: Value,
5626 val: Value,
5627 sync_scope: SyncScope,
5628 ordering: AtomicOrdering,
5629 alignment: Alignment,
5630 name: []const u8,
5631 ) Allocator.Error!Value {
5632 assert(ptr.typeOfWip(self).isPointer(self.builder));
5633 assert(ordering != .none);
5634
5635 try self.ensureUnusedExtraCapacity(1, Instruction.AtomicRmw, 0);
5636 const instruction = try self.addInst(name, .{
5637 .tag = .atomicrmw,
5638 .data = self.addExtraAssumeCapacity(Instruction.AtomicRmw{
5639 .info = .{
5640 .access_kind = access_kind,
5641 .atomic_rmw_operation = operation,
5642 .sync_scope = sync_scope,
5643 .success_ordering = ordering,
5644 .alignment = alignment,
5645 },
5646 .ptr = ptr,
5647 .val = val,
5648 }),
5649 });
5650 if (self.builder.useLibLlvm()) {
5651 const llvm_instruction = self.llvm.builder.buildAtomicRmw(
5652 operation.toLlvm(),
5653 ptr.toLlvm(self),
5654 val.toLlvm(self),
5655 ordering.toLlvm(),
5656 llvm.Bool.fromBool(sync_scope == .singlethread),
5657 );
5658 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5659 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5660 const llvm_name = instruction.llvmName(self);
5661 if (llvm_name.len > 0) llvm_instruction.setValueName(
5662 llvm_name.ptr,
5663 @intCast(llvm_name.len),
5664 );
5665 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5666 }
5667 return instruction.toValue();
5668 }
5669
40705670 pub fn gep(
40715671 self: *WipFunction,
40725672 kind: Instruction.GetElementPtr.Kind,
......@@ -4239,25 +5839,19 @@ pub const WipFunction = struct {
42395839
42405840 pub fn fcmp(
42415841 self: *WipFunction,
5842 fast: FastMathKind,
42425843 cond: FloatCondition,
42435844 lhs: Value,
42445845 rhs: Value,
42455846 name: []const u8,
42465847 ) Allocator.Error!Value {
4247 return self.cmpTag(switch (cond) {
4248 inline else => |tag| @field(Instruction.Tag, "fcmp " ++ @tagName(tag)),
4249 }, @intFromEnum(cond), lhs, rhs, name);
4250 }
4251
4252 pub fn fcmpFast(
4253 self: *WipFunction,
4254 cond: FloatCondition,
4255 lhs: Value,
4256 rhs: Value,
4257 name: []const u8,
4258 ) Allocator.Error!Value {
4259 return self.cmpTag(switch (cond) {
4260 inline else => |tag| @field(Instruction.Tag, "fcmp fast " ++ @tagName(tag)),
5848 return self.cmpTag(switch (fast) {
5849 inline else => |fast_tag| switch (cond) {
5850 inline else => |cond_tag| @field(Instruction.Tag, "fcmp " ++ switch (fast_tag) {
5851 .normal => "",
5852 .fast => "fast ",
5853 } ++ @tagName(cond_tag)),
5854 },
42615855 }, @intFromEnum(cond), lhs, rhs, name);
42625856 }
42635857
......@@ -4315,22 +5909,16 @@ pub const WipFunction = struct {
43155909
43165910 pub fn select(
43175911 self: *WipFunction,
5912 fast: FastMathKind,
43185913 cond: Value,
43195914 lhs: Value,
43205915 rhs: Value,
43215916 name: []const u8,
43225917 ) Allocator.Error!Value {
4323 return self.selectTag(.select, cond, lhs, rhs, name);
4324 }
4325
4326 pub fn selectFast(
4327 self: *WipFunction,
4328 cond: Value,
4329 lhs: Value,
4330 rhs: Value,
4331 name: []const u8,
4332 ) Allocator.Error!Value {
4333 return self.selectTag(.@"select fast", cond, lhs, rhs, name);
5918 return self.selectTag(switch (fast) {
5919 .normal => .select,
5920 .fast => .@"select fast",
5921 }, cond, lhs, rhs, name);
43345922 }
43355923
43365924 pub fn call(
......@@ -4354,7 +5942,16 @@ pub const WipFunction = struct {
43545942 .void => null,
43555943 else => name,
43565944 }, .{
4357 .tag = .call,
5945 .tag = switch (kind) {
5946 .normal => .call,
5947 .fast => .@"call fast",
5948 .musttail => .@"musttail call",
5949 .musttail_fast => .@"musttail call fast",
5950 .notail => .@"notail call",
5951 .notail_fast => .@"notail call fast",
5952 .tail => .@"tail call",
5953 .tail_fast => .@"tail call fast",
5954 },
43585955 .data = self.addExtraAssumeCapacity(Instruction.Call{
43595956 .info = .{ .call_conv = call_conv },
43605957 .attributes = function_attributes,
......@@ -4396,7 +5993,7 @@ pub const WipFunction = struct {
43965993 else => instruction.llvmName(self),
43975994 },
43985995 );
4399 llvm_instruction.setInstructionCallConv(@enumFromInt(@intFromEnum(call_conv)));
5996 llvm_instruction.setInstructionCallConv(call_conv.toLlvm());
44005997 llvm_instruction.setTailCallKind(switch (kind) {
44015998 .normal, .fast => .None,
44025999 .musttail, .musttail_fast => .MustTail,
......@@ -4404,9 +6001,8 @@ pub const WipFunction = struct {
44046001 .tail, .tail_fast => .Tail,
44056002 });
44066003 for (0.., function_attributes.slice(self.builder)) |index, attributes| {
4407 const attribute_index = @as(llvm.AttributeIndex, @intCast(index)) -% 1;
44086004 for (attributes.slice(self.builder)) |attribute| llvm_instruction.addCallSiteAttribute(
4409 attribute_index,
6005 @as(llvm.AttributeIndex, @intCast(index)) -% 1,
44106006 attribute.toLlvm(self.builder),
44116007 );
44126008 }
......@@ -4419,7 +6015,7 @@ pub const WipFunction = struct {
44196015 self: *WipFunction,
44206016 function_attributes: FunctionAttributes,
44216017 ty: Type,
4422 kind: Constant.Asm.Info,
6018 kind: Constant.Assembly.Info,
44236019 assembly: String,
44246020 constraints: String,
44256021 args: []const Value,
......@@ -4429,6 +6025,80 @@ pub const WipFunction = struct {
44296025 return self.call(.normal, CallConv.default, function_attributes, ty, callee, args, name);
44306026 }
44316027
6028 pub fn callIntrinsic(
6029 self: *WipFunction,
6030 fast: FastMathKind,
6031 function_attributes: FunctionAttributes,
6032 id: Intrinsic,
6033 overload: []const Type,
6034 args: []const Value,
6035 name: []const u8,
6036 ) Allocator.Error!Value {
6037 const intrinsic = try self.builder.getIntrinsic(id, overload);
6038 return self.call(
6039 fast.toCallKind(),
6040 CallConv.default,
6041 function_attributes,
6042 intrinsic.typeOf(self.builder),
6043 intrinsic.toValue(self.builder),
6044 args,
6045 name,
6046 );
6047 }
6048
6049 pub fn callMemCpy(
6050 self: *WipFunction,
6051 dst: Value,
6052 dst_align: Alignment,
6053 src: Value,
6054 src_align: Alignment,
6055 len: Value,
6056 kind: MemoryAccessKind,
6057 ) Allocator.Error!Instruction.Index {
6058 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
6059 var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })};
6060 const value = try self.callIntrinsic(
6061 .normal,
6062 try self.builder.fnAttrs(&.{
6063 .none,
6064 .none,
6065 try self.builder.attrs(&dst_attrs),
6066 try self.builder.attrs(&src_attrs),
6067 }),
6068 .memcpy,
6069 &.{ dst.typeOfWip(self), src.typeOfWip(self), len.typeOfWip(self) },
6070 &.{ dst, src, len, switch (kind) {
6071 .normal => Value.false,
6072 .@"volatile" => Value.true,
6073 } },
6074 undefined,
6075 );
6076 return value.unwrap().instruction;
6077 }
6078
6079 pub fn callMemSet(
6080 self: *WipFunction,
6081 dst: Value,
6082 dst_align: Alignment,
6083 val: Value,
6084 len: Value,
6085 kind: MemoryAccessKind,
6086 ) Allocator.Error!Instruction.Index {
6087 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
6088 const value = try self.callIntrinsic(
6089 .normal,
6090 try self.builder.fnAttrs(&.{ .none, .none, try self.builder.attrs(&dst_attrs) }),
6091 .memset,
6092 &.{ dst.typeOfWip(self), len.typeOfWip(self) },
6093 &.{ dst, val, len, switch (kind) {
6094 .normal => Value.false,
6095 .@"volatile" => Value.true,
6096 } },
6097 undefined,
6098 );
6099 return value.unwrap().instruction;
6100 }
6101
44326102 pub fn vaArg(self: *WipFunction, list: Value, ty: Type, name: []const u8) Allocator.Error!Value {
44336103 try self.ensureUnusedExtraCapacity(1, Instruction.VaArg, 0);
44346104 const instruction = try self.addInst(name, .{
......@@ -4448,53 +6118,6 @@ pub const WipFunction = struct {
44486118 return instruction.toValue();
44496119 }
44506120
4451 pub fn fusedMultiplyAdd(self: *WipFunction, a: Value, b: Value, c: Value) Allocator.Error!Value {
4452 assert(a.typeOfWip(self) == b.typeOfWip(self) and a.typeOfWip(self) == c.typeOfWip(self));
4453 try self.ensureUnusedExtraCapacity(1, Instruction.FusedMultiplyAdd, 0);
4454 const instruction = try self.addInst("", .{
4455 .tag = .@"llvm.fma.",
4456 .data = self.addExtraAssumeCapacity(Instruction.FusedMultiplyAdd{
4457 .a = a,
4458 .b = b,
4459 .c = c,
4460 }),
4461 });
4462 if (self.builder.useLibLlvm()) {
4463 self.llvm.instructions.appendAssumeCapacity(llvm.Builder.buildFMA(
4464 self.llvm.builder,
4465 a.toLlvm(self),
4466 b.toLlvm(self),
4467 c.toLlvm(self),
4468 instruction.llvmName(self),
4469 ));
4470 }
4471 return instruction.toValue();
4472 }
4473
4474 pub const WipUnimplemented = struct {
4475 instruction: Instruction.Index,
4476
4477 pub fn finish(self: WipUnimplemented, val: *llvm.Value, wip: *WipFunction) Value {
4478 assert(wip.builder.useLibLlvm());
4479 wip.llvm.instructions.items[@intFromEnum(self.instruction)] = val;
4480 return self.instruction.toValue();
4481 }
4482 };
4483
4484 pub fn unimplemented(
4485 self: *WipFunction,
4486 ty: Type,
4487 name: []const u8,
4488 ) Allocator.Error!WipUnimplemented {
4489 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
4490 const instruction = try self.addInst(name, .{
4491 .tag = .unimplemented,
4492 .data = @intFromEnum(ty),
4493 });
4494 if (self.builder.useLibLlvm()) _ = self.llvm.instructions.addOneAssumeCapacity();
4495 return .{ .instruction = instruction };
4496 }
4497
44986121 pub fn finish(self: *WipFunction) Allocator.Error!void {
44996122 const gpa = self.builder.gpa;
45006123 const function = self.function.ptr(self.builder);
......@@ -4697,22 +6320,6 @@ pub const WipFunction = struct {
46976320 .@"icmp ugt",
46986321 .@"icmp ule",
46996322 .@"icmp ult",
4700 .@"llvm.maxnum.",
4701 .@"llvm.minnum.",
4702 .@"llvm.ctlz.",
4703 .@"llvm.cttz.",
4704 .@"llvm.sadd.sat.",
4705 .@"llvm.smax.",
4706 .@"llvm.smin.",
4707 .@"llvm.smul.fix.sat.",
4708 .@"llvm.sshl.sat.",
4709 .@"llvm.ssub.sat.",
4710 .@"llvm.uadd.sat.",
4711 .@"llvm.umax.",
4712 .@"llvm.umin.",
4713 .@"llvm.umul.fix.sat.",
4714 .@"llvm.ushl.sat.",
4715 .@"llvm.usub.sat.",
47166323 .lshr,
47176324 .@"lshr exact",
47186325 .mul,
......@@ -4775,19 +6382,19 @@ pub const WipFunction = struct {
47756382 .arg,
47766383 .block,
47776384 => unreachable,
6385 .atomicrmw => {
6386 const extra = self.extraData(Instruction.AtomicRmw, instruction.data);
6387 instruction.data = wip_extra.addExtra(Instruction.AtomicRmw{
6388 .info = extra.info,
6389 .ptr = instructions.map(extra.ptr),
6390 .val = instructions.map(extra.val),
6391 });
6392 },
47786393 .br,
47796394 .fence,
47806395 .@"ret void",
4781 .unimplemented,
47826396 .@"unreachable",
47836397 => {},
4784 .extractelement => {
4785 const extra = self.extraData(Instruction.ExtractElement, instruction.data);
4786 instruction.data = wip_extra.addExtra(Instruction.ExtractElement{
4787 .val = instructions.map(extra.val),
4788 .index = instructions.map(extra.index),
4789 });
4790 },
47916398 .br_cond => {
47926399 const extra = self.extraData(Instruction.BrCond, instruction.data);
47936400 instruction.data = wip_extra.addExtra(Instruction.BrCond{
......@@ -4816,6 +6423,24 @@ pub const WipFunction = struct {
48166423 });
48176424 wip_extra.appendMappedValues(args, instructions);
48186425 },
6426 .cmpxchg,
6427 .@"cmpxchg weak",
6428 => {
6429 const extra = self.extraData(Instruction.CmpXchg, instruction.data);
6430 instruction.data = wip_extra.addExtra(Instruction.CmpXchg{
6431 .info = extra.info,
6432 .ptr = instructions.map(extra.ptr),
6433 .cmp = instructions.map(extra.cmp),
6434 .new = instructions.map(extra.new),
6435 });
6436 },
6437 .extractelement => {
6438 const extra = self.extraData(Instruction.ExtractElement, instruction.data);
6439 instruction.data = wip_extra.addExtra(Instruction.ExtractElement{
6440 .val = instructions.map(extra.val),
6441 .index = instructions.map(extra.index),
6442 });
6443 },
48196444 .extractvalue => {
48206445 var extra = self.extraDataTrail(Instruction.ExtractValue, instruction.data);
48216446 const indices = extra.trail.next(extra.data.indices_len, u32, self);
......@@ -4828,22 +6453,6 @@ pub const WipFunction = struct {
48286453 .fneg,
48296454 .@"fneg fast",
48306455 .ret,
4831 .@"llvm.ceil.",
4832 .@"llvm.cos.",
4833 .@"llvm.exp.",
4834 .@"llvm.exp2.",
4835 .@"llvm.fabs.",
4836 .@"llvm.floor.",
4837 .@"llvm.log.",
4838 .@"llvm.log10.",
4839 .@"llvm.log2.",
4840 .@"llvm.round.",
4841 .@"llvm.sin.",
4842 .@"llvm.sqrt.",
4843 .@"llvm.trunc.",
4844 .@"llvm.bitreverse.",
4845 .@"llvm.bswap.",
4846 .@"llvm.ctpop.",
48476456 => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))),
48486457 .getelementptr,
48496458 .@"getelementptr inbounds",
......@@ -4877,8 +6486,6 @@ pub const WipFunction = struct {
48776486 },
48786487 .load,
48796488 .@"load atomic",
4880 .@"load atomic volatile",
4881 .@"load volatile",
48826489 => {
48836490 const extra = self.extraData(Instruction.Load, instruction.data);
48846491 instruction.data = wip_extra.addExtra(Instruction.Load{
......@@ -4920,8 +6527,6 @@ pub const WipFunction = struct {
49206527 },
49216528 .store,
49226529 .@"store atomic",
4923 .@"store atomic volatile",
4924 .@"store volatile",
49256530 => {
49266531 const extra = self.extraData(Instruction.Store, instruction.data);
49276532 instruction.data = wip_extra.addExtra(Instruction.Store{
......@@ -4949,14 +6554,6 @@ pub const WipFunction = struct {
49496554 .type = extra.type,
49506555 });
49516556 },
4952 .@"llvm.fma." => {
4953 const extra = self.extraData(Instruction.FusedMultiplyAdd, instruction.data);
4954 instruction.data = wip_extra.addExtra(Instruction.FusedMultiplyAdd{
4955 .a = instructions.map(extra.a),
4956 .b = instructions.map(extra.b),
4957 .c = instructions.map(extra.c),
4958 });
4959 },
49606557 }
49616558 function.instructions.appendAssumeCapacity(instruction);
49626559 names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip)
......@@ -5365,6 +6962,24 @@ pub const FloatCondition = enum(u4) {
53656962 ult = 12,
53666963 ule = 13,
53676964 une = 14,
6965
6966 fn toLlvm(self: FloatCondition) llvm.RealPredicate {
6967 return switch (self) {
6968 .oeq => .OEQ,
6969 .ogt => .OGT,
6970 .oge => .OGE,
6971 .olt => .OLT,
6972 .ole => .OLE,
6973 .one => .ONE,
6974 .ord => .ORD,
6975 .uno => .UNO,
6976 .ueq => .UEQ,
6977 .ugt => .UGT,
6978 .uge => .UGE,
6979 .ult => .ULT,
6980 .uno => .UNE,
6981 };
6982 }
53686983};
53696984
53706985pub const IntegerCondition = enum(u6) {
......@@ -5378,11 +6993,34 @@ pub const IntegerCondition = enum(u6) {
53786993 sge = 39,
53796994 slt = 40,
53806995 sle = 41,
6996
6997 fn toLlvm(self: IntegerCondition) llvm.IntPredicate {
6998 return switch (self) {
6999 .eq => .EQ,
7000 .ne => .NE,
7001 .ugt => .UGT,
7002 .uge => .UGE,
7003 .ult => .ULT,
7004 .sgt => .SGT,
7005 .sge => .SGE,
7006 .slt => .SLT,
7007 .sle => .SLE,
7008 };
7009 }
53817010};
53827011
53837012pub const MemoryAccessKind = enum(u1) {
53847013 normal,
53857014 @"volatile",
7015
7016 pub fn format(
7017 self: MemoryAccessKind,
7018 comptime prefix: []const u8,
7019 _: std.fmt.FormatOptions,
7020 writer: anytype,
7021 ) @TypeOf(writer).Error!void {
7022 if (self != .normal) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
7023 }
53867024};
53877025
53887026pub const SyncScope = enum(u1) {
......@@ -5396,7 +7034,7 @@ pub const SyncScope = enum(u1) {
53967034 writer: anytype,
53977035 ) @TypeOf(writer).Error!void {
53987036 if (self != .system) try writer.print(
5399 \\{s} syncscope("{s}")
7037 \\{s}syncscope("{s}")
54007038 , .{ prefix, @tagName(self) });
54017039 }
54027040};
......@@ -5416,15 +7054,30 @@ pub const AtomicOrdering = enum(u3) {
54167054 _: std.fmt.FormatOptions,
54177055 writer: anytype,
54187056 ) @TypeOf(writer).Error!void {
5419 if (self != .none) try writer.print("{s} {s}", .{ prefix, @tagName(self) });
7057 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
7058 }
7059
7060 fn toLlvm(self: AtomicOrdering) llvm.AtomicOrdering {
7061 return switch (self) {
7062 .none => .NotAtomic,
7063 .unordered => .Unordered,
7064 .monotonic => .Monotonic,
7065 .acquire => .Acquire,
7066 .release => .Release,
7067 .acq_rel => .AcquireRelease,
7068 .seq_cst => .SequentiallyConsistent,
7069 };
54207070 }
54217071};
54227072
54237073const MemoryAccessInfo = packed struct(u32) {
5424 scope: SyncScope,
5425 ordering: AtomicOrdering,
5426 alignment: Alignment,
5427 _: u22 = undefined,
7074 access_kind: MemoryAccessKind = .normal,
7075 atomic_rmw_operation: Function.Instruction.AtomicRmw.Operation = .none,
7076 sync_scope: SyncScope,
7077 success_ordering: AtomicOrdering,
7078 failure_ordering: AtomicOrdering = .none,
7079 alignment: Alignment = .default,
7080 _: u13 = undefined,
54287081};
54297082
54307083pub const FastMath = packed struct(u32) {
......@@ -5447,6 +7100,18 @@ pub const FastMath = packed struct(u32) {
54477100 };
54487101};
54497102
7103pub const FastMathKind = enum {
7104 normal,
7105 fast,
7106
7107 pub fn toCallKind(self: FastMathKind) Function.Instruction.Call.Kind {
7108 return switch (self) {
7109 .normal => .normal,
7110 .fast => .fast,
7111 };
7112 }
7113};
7114
54507115pub const Constant = enum(u32) {
54517116 false,
54527117 true,
......@@ -5516,6 +7181,7 @@ pub const Constant = enum(u32) {
55167181 @"and",
55177182 @"or",
55187183 xor,
7184 select,
55197185 @"asm",
55207186 @"asm sideeffect",
55217187 @"asm alignstack",
......@@ -5627,7 +7293,13 @@ pub const Constant = enum(u32) {
56277293 rhs: Constant,
56287294 };
56297295
5630 pub const Asm = extern struct {
7296 pub const Select = extern struct {
7297 cond: Constant,
7298 lhs: Constant,
7299 rhs: Constant,
7300 };
7301
7302 pub const Assembly = extern struct {
56317303 type: Type,
56327304 assembly: String,
56337305 constraints: String,
......@@ -5651,7 +7323,7 @@ pub const Constant = enum(u32) {
56517323 }
56527324
56537325 pub fn toValue(self: Constant) Value {
5654 return @enumFromInt(@intFromEnum(Value.first_constant) + @intFromEnum(self));
7326 return @enumFromInt(Value.first_constant + @intFromEnum(self));
56557327 }
56567328
56577329 pub fn typeOf(self: Constant, builder: *Builder) Type {
......@@ -5758,6 +7430,7 @@ pub const Constant = enum(u32) {
57587430 .@"or",
57597431 .xor,
57607432 => builder.constantExtraData(Binary, item.data).lhs.typeOf(builder),
7433 .select => builder.constantExtraData(Select, item.data).lhs.typeOf(builder),
57617434 .@"asm",
57627435 .@"asm sideeffect",
57637436 .@"asm alignstack",
......@@ -5852,7 +7525,7 @@ pub const Constant = enum(u32) {
58527525 }
58537526 },
58547527 .global => |global| switch (global.ptrConst(builder).kind) {
5855 .alias => |alias| cur = alias.ptrConst(builder).init,
7528 .alias => |alias| cur = alias.ptrConst(builder).aliasee,
58567529 .variable, .function => return global,
58577530 .replaced => unreachable,
58587531 },
......@@ -5926,9 +7599,34 @@ pub const Constant = enum(u32) {
59267599 .bfloat => 16,
59277600 else => unreachable,
59287601 } }),
5929 .float => try writer.print("0x{X:0>16}", .{
5930 @as(u64, @bitCast(@as(f64, @as(f32, @bitCast(item.data))))),
5931 }),
7602 .float => {
7603 const Float = struct {
7604 fn Repr(comptime T: type) type {
7605 return packed struct(std.meta.Int(.unsigned, @bitSizeOf(T))) {
7606 mantissa: std.meta.Int(.unsigned, std.math.floatMantissaBits(T)),
7607 exponent: std.meta.Int(.unsigned, std.math.floatExponentBits(T)),
7608 sign: u1,
7609 };
7610 }
7611 };
7612 const Exponent32 = std.meta.FieldType(Float.Repr(f32), .exponent);
7613 const Exponent64 = std.meta.FieldType(Float.Repr(f64), .exponent);
7614 const repr: Float.Repr(f32) = @bitCast(item.data);
7615 try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){
7616 .mantissa = std.math.shl(
7617 std.meta.FieldType(Float.Repr(f64), .mantissa),
7618 repr.mantissa,
7619 std.math.floatMantissaBits(f64) - std.math.floatMantissaBits(f32),
7620 ),
7621 .exponent = switch (repr.exponent) {
7622 std.math.minInt(Exponent32) => std.math.minInt(Exponent64),
7623 else => @as(Exponent64, repr.exponent) +
7624 (std.math.floatExponentMax(f64) - std.math.floatExponentMax(f32)),
7625 std.math.maxInt(Exponent32) => std.math.maxInt(Exponent64),
7626 },
7627 .sign = repr.sign,
7628 }))});
7629 },
59327630 .double => {
59337631 const extra = data.builder.constantExtraData(Double, item.data);
59347632 try writer.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });
......@@ -6122,6 +7820,15 @@ pub const Constant = enum(u32) {
61227820 extra.rhs.fmt(data.builder),
61237821 });
61247822 },
7823 .select => |tag| {
7824 const extra = data.builder.constantExtraData(Select, item.data);
7825 try writer.print("{s} ({%}, {%}, {%})", .{
7826 @tagName(tag),
7827 extra.cond.fmt(data.builder),
7828 extra.lhs.fmt(data.builder),
7829 extra.rhs.fmt(data.builder),
7830 });
7831 },
61257832 .@"asm",
61267833 .@"asm sideeffect",
61277834 .@"asm alignstack",
......@@ -6139,7 +7846,7 @@ pub const Constant = enum(u32) {
61397846 .@"asm alignstack inteldialect unwind",
61407847 .@"asm sideeffect alignstack inteldialect unwind",
61417848 => |tag| {
6142 const extra = data.builder.constantExtraData(Asm, item.data);
7849 const extra = data.builder.constantExtraData(Assembly, item.data);
61437850 try writer.print("{s} {\"}, {\"}", .{
61447851 @tagName(tag),
61457852 extra.assembly.fmt(data.builder),
......@@ -6157,27 +7864,31 @@ pub const Constant = enum(u32) {
61577864
61587865 pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value {
61597866 assert(builder.useLibLlvm());
6160 return switch (self.unwrap()) {
7867 const llvm_value = switch (self.unwrap()) {
61617868 .constant => |constant| builder.llvm.constants.items[constant],
6162 .global => |global| global.toLlvm(builder),
7869 .global => |global| return global.toLlvm(builder),
61637870 };
7871 const global = builder.llvm.replacements.get(llvm_value) orelse return llvm_value;
7872 return global.toLlvm(builder);
61647873 }
61657874};
61667875
61677876pub const Value = enum(u32) {
61687877 none = std.math.maxInt(u31),
7878 false = first_constant + @intFromEnum(Constant.false),
7879 true = first_constant + @intFromEnum(Constant.true),
61697880 _,
61707881
6171 const first_constant: Value = @enumFromInt(1 << 31);
7882 const first_constant = 1 << 31;
61727883
61737884 pub fn unwrap(self: Value) union(enum) {
61747885 instruction: Function.Instruction.Index,
61757886 constant: Constant,
61767887 } {
6177 return if (@intFromEnum(self) < @intFromEnum(first_constant))
7888 return if (@intFromEnum(self) < first_constant)
61787889 .{ .instruction = @enumFromInt(@intFromEnum(self)) }
61797890 else
6180 .{ .constant = @enumFromInt(@intFromEnum(self) - @intFromEnum(first_constant)) };
7891 .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) };
61817892 }
61827893
61837894 pub fn typeOfWip(self: Value, wip: *const WipFunction) Type {
......@@ -6295,6 +8006,7 @@ pub fn init(options: Options) InitError!Builder {
62958006 .types = .{},
62968007 .globals = .{},
62978008 .constants = .{},
8009 .replacements = .{},
62988010 };
62998011 errdefer self.deinit();
63008012
......@@ -6304,7 +8016,7 @@ pub fn init(options: Options) InitError!Builder {
63048016 if (options.name.len > 0) self.source_filename = try self.string(options.name);
63058017 self.initializeLLVMTarget(options.target.cpu.arch);
63068018 if (self.useLibLlvm()) self.llvm.module = llvm.Module.createWithName(
6307 (self.source_filename.slice(&self) orelse "").ptr,
8019 (self.source_filename.slice(&self) orelse ""),
63088020 self.llvm.context,
63098021 );
63108022
......@@ -6349,8 +8061,11 @@ pub fn init(options: Options) InitError!Builder {
63498061 inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits|
63508062 assert(self.intTypeAssumeCapacity(bits) ==
63518063 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));
6352 inline for (.{0}) |addr_space|
6353 assert(self.ptrTypeAssumeCapacity(@enumFromInt(addr_space)) == .ptr);
8064 inline for (.{ 0, 4 }) |addr_space_index| {
8065 const addr_space: AddrSpace = @enumFromInt(addr_space_index);
8066 assert(self.ptrTypeAssumeCapacity(addr_space) ==
8067 @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space})));
8068 }
63548069 }
63558070
63568071 {
......@@ -6371,6 +8086,20 @@ pub fn init(options: Options) InitError!Builder {
63718086}
63728087
63738088pub fn deinit(self: *Builder) void {
8089 if (self.useLibLlvm()) {
8090 var replacement_it = self.llvm.replacements.keyIterator();
8091 while (replacement_it.next()) |replacement| replacement.*.deleteGlobalValue();
8092 self.llvm.replacements.deinit(self.gpa);
8093 self.llvm.constants.deinit(self.gpa);
8094 self.llvm.globals.deinit(self.gpa);
8095 self.llvm.types.deinit(self.gpa);
8096 self.llvm.attributes.deinit(self.gpa);
8097 if (self.llvm.attribute_kind_ids) |attribute_kind_ids| self.gpa.destroy(attribute_kind_ids);
8098 if (self.llvm.di_builder) |di_builder| di_builder.dispose();
8099 if (self.llvm.module) |module| module.dispose();
8100 self.llvm.context.dispose();
8101 }
8102
63748103 self.module_asm.deinit(self.gpa);
63758104
63768105 self.string_map.deinit(self.gpa);
......@@ -6400,16 +8129,6 @@ pub fn deinit(self: *Builder) void {
64008129 self.constant_extra.deinit(self.gpa);
64018130 self.constant_limbs.deinit(self.gpa);
64028131
6403 if (self.useLibLlvm()) {
6404 self.llvm.constants.deinit(self.gpa);
6405 self.llvm.globals.deinit(self.gpa);
6406 self.llvm.types.deinit(self.gpa);
6407 self.llvm.attributes.deinit(self.gpa);
6408 if (self.llvm.attribute_kind_ids) |attribute_kind_ids| self.gpa.destroy(attribute_kind_ids);
6409 if (self.llvm.di_builder) |di_builder| di_builder.dispose();
6410 if (self.llvm.module) |module| module.dispose();
6411 self.llvm.context.dispose();
6412 }
64138132 self.* = undefined;
64148133}
64158134
......@@ -6763,16 +8482,16 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde
67638482 gop.value_ptr.* = {};
67648483 if (self.useLibLlvm()) self.llvm.attributes.appendAssumeCapacity(switch (attribute) {
67658484 else => llvm_attr: {
6766 const kind_id = &self.llvm.attribute_kind_ids.?[@intFromEnum(attribute)];
6767 if (kind_id.* == 0) {
8485 const llvm_kind_id = attribute.getKind().toLlvm(self);
8486 if (llvm_kind_id.* == 0) {
67688487 const name = @tagName(attribute);
6769 kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len);
6770 assert(kind_id.* != 0);
8488 llvm_kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len);
8489 assert(llvm_kind_id.* != 0);
67718490 }
67728491 break :llvm_attr switch (attribute) {
67738492 else => switch (attribute) {
67748493 inline else => |value| self.llvm.context.createEnumAttribute(
6775 kind_id.*,
8494 llvm_kind_id.*,
67768495 switch (@TypeOf(value)) {
67778496 void => 0,
67788497 u32 => value,
......@@ -6806,7 +8525,7 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde
68068525 .inalloca,
68078526 .sret,
68088527 .elementtype,
6809 => |ty| self.llvm.context.createTypeAttribute(kind_id.*, ty.toLlvm(self)),
8528 => |ty| self.llvm.context.createTypeAttribute(llvm_kind_id.*, ty.toLlvm(self)),
68108529 .string, .none => unreachable,
68118530 };
68128531 },
......@@ -6866,10 +8585,10 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo
68668585 const global_gop = self.globals.getOrPutAssumeCapacity(id);
68678586 if (!global_gop.found_existing) {
68688587 global_gop.value_ptr.* = global;
6869 global_gop.value_ptr.updateAttributes();
6870 const index: Global.Index = @enumFromInt(global_gop.index);
6871 index.updateName(self);
6872 return index;
8588 const global_index: Global.Index = @enumFromInt(global_gop.index);
8589 global_index.updateDsoLocal(self);
8590 global_index.updateName(self);
8591 return global_index;
68738592 }
68748593
68758594 const unique_gop = self.next_unique_global_id.getOrPutAssumeCapacity(name);
......@@ -6883,17 +8602,221 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index {
68838602 return @enumFromInt(self.globals.getIndex(name) orelse return null);
68848603}
68858604
8605pub fn addAlias(
8606 self: *Builder,
8607 name: String,
8608 ty: Type,
8609 addr_space: AddrSpace,
8610 aliasee: Constant,
8611) Allocator.Error!Alias.Index {
8612 assert(!name.isAnon());
8613 try self.ensureUnusedTypeCapacity(1, NoExtra, 0);
8614 try self.ensureUnusedGlobalCapacity(name);
8615 try self.aliases.ensureUnusedCapacity(self.gpa, 1);
8616 return self.addAliasAssumeCapacity(name, ty, addr_space, aliasee);
8617}
8618
8619pub fn addAliasAssumeCapacity(
8620 self: *Builder,
8621 name: String,
8622 ty: Type,
8623 addr_space: AddrSpace,
8624 aliasee: Constant,
8625) Alias.Index {
8626 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(self.llvm.module.?.addAlias(
8627 ty.toLlvm(self),
8628 @intFromEnum(addr_space),
8629 aliasee.toLlvm(self),
8630 name.slice(self).?,
8631 ));
8632 const alias_index: Alias.Index = @enumFromInt(self.aliases.items.len);
8633 self.aliases.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8634 .addr_space = addr_space,
8635 .type = ty,
8636 .kind = .{ .alias = alias_index },
8637 }), .aliasee = aliasee });
8638 return alias_index;
8639}
8640
8641pub fn addVariable(
8642 self: *Builder,
8643 name: String,
8644 ty: Type,
8645 addr_space: AddrSpace,
8646) Allocator.Error!Variable.Index {
8647 assert(!name.isAnon());
8648 try self.ensureUnusedTypeCapacity(1, NoExtra, 0);
8649 try self.ensureUnusedGlobalCapacity(name);
8650 try self.variables.ensureUnusedCapacity(self.gpa, 1);
8651 return self.addVariableAssumeCapacity(ty, name, addr_space);
8652}
8653
8654pub fn addVariableAssumeCapacity(
8655 self: *Builder,
8656 ty: Type,
8657 name: String,
8658 addr_space: AddrSpace,
8659) Variable.Index {
8660 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(
8661 self.llvm.module.?.addGlobalInAddressSpace(
8662 ty.toLlvm(self),
8663 name.slice(self).?,
8664 @intFromEnum(addr_space),
8665 ),
8666 );
8667 const variable_index: Variable.Index = @enumFromInt(self.variables.items.len);
8668 self.variables.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8669 .addr_space = addr_space,
8670 .type = ty,
8671 .kind = .{ .variable = variable_index },
8672 }) });
8673 return variable_index;
8674}
8675
8676pub fn addFunction(
8677 self: *Builder,
8678 ty: Type,
8679 name: String,
8680 addr_space: AddrSpace,
8681) Allocator.Error!Function.Index {
8682 assert(!name.isAnon());
8683 try self.ensureUnusedTypeCapacity(1, NoExtra, 0);
8684 try self.ensureUnusedGlobalCapacity(name);
8685 try self.functions.ensureUnusedCapacity(self.gpa, 1);
8686 return self.addFunctionAssumeCapacity(ty, name, addr_space);
8687}
8688
8689pub fn addFunctionAssumeCapacity(
8690 self: *Builder,
8691 ty: Type,
8692 name: String,
8693 addr_space: AddrSpace,
8694) Function.Index {
8695 assert(ty.isFunction(self));
8696 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(
8697 self.llvm.module.?.addFunctionInAddressSpace(
8698 name.slice(self).?,
8699 ty.toLlvm(self),
8700 @intFromEnum(addr_space),
8701 ),
8702 );
8703 const function_index: Function.Index = @enumFromInt(self.functions.items.len);
8704 self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8705 .addr_space = addr_space,
8706 .type = ty,
8707 .kind = .{ .function = function_index },
8708 }) });
8709 return function_index;
8710}
8711
8712pub fn getIntrinsic(
8713 self: *Builder,
8714 id: Intrinsic,
8715 overload: []const Type,
8716) Allocator.Error!Function.Index {
8717 const ExpectedContents = extern union {
8718 name: [expected_intrinsic_name_len]u8,
8719 attrs: extern struct {
8720 params: [expected_args_len]Type,
8721 fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes,
8722 attrs: [expected_attrs_len]Attribute.Index,
8723 fields: [expected_fields_len]Type,
8724 },
8725 };
8726 var stack align(@max(@alignOf(std.heap.StackFallbackAllocator(0)), @alignOf(ExpectedContents))) =
8727 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
8728 const allocator = stack.get();
8729
8730 const name = name: {
8731 var buffer = std.ArrayList(u8).init(allocator);
8732 defer buffer.deinit();
8733
8734 try buffer.writer().print("llvm.{s}", .{@tagName(id)});
8735 for (overload) |ty| try buffer.writer().print(".{m}", .{ty.fmt(self)});
8736 break :name try self.string(buffer.items);
8737 };
8738 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;
8739
8740 const signature = Intrinsic.signatures.get(id);
8741 const param_types = try allocator.alloc(Type, signature.params.len);
8742 defer allocator.free(param_types);
8743 const function_attributes = try allocator.alloc(
8744 Attributes,
8745 FunctionAttributes.params_index + (signature.params.len - signature.ret_len),
8746 );
8747 defer allocator.free(function_attributes);
8748
8749 var attributes: struct {
8750 builder: *Builder,
8751 list: std.ArrayList(Attribute.Index),
8752
8753 fn deinit(state: *@This()) void {
8754 state.list.deinit();
8755 state.* = undefined;
8756 }
8757
8758 fn get(state: *@This(), attributes: []const Attribute) Allocator.Error!Attributes {
8759 try state.list.resize(attributes.len);
8760 for (state.list.items, attributes) |*item, attribute|
8761 item.* = try state.builder.attr(attribute);
8762 return state.builder.attrs(state.list.items);
8763 }
8764 } = .{ .builder = self, .list = std.ArrayList(Attribute.Index).init(allocator) };
8765 defer attributes.deinit();
8766
8767 var overload_index: usize = 0;
8768 function_attributes[FunctionAttributes.function_index] = try attributes.get(signature.attrs);
8769 function_attributes[FunctionAttributes.return_index] = .none; // needed for void return
8770 for (0.., param_types, signature.params) |param_index, *param_type, signature_param| {
8771 switch (signature_param.kind) {
8772 .type => |ty| param_type.* = ty,
8773 .overloaded => {
8774 param_type.* = overload[overload_index];
8775 overload_index += 1;
8776 },
8777 .matches, .matches_scalar, .matches_changed_scalar => {},
8778 }
8779 function_attributes[
8780 if (param_index < signature.ret_len)
8781 FunctionAttributes.return_index
8782 else
8783 FunctionAttributes.params_index + (param_index - signature.ret_len)
8784 ] = try attributes.get(signature_param.attrs);
8785 }
8786 assert(overload_index == overload.len);
8787 for (param_types, signature.params) |*param_type, signature_param| {
8788 param_type.* = switch (signature_param.kind) {
8789 .type, .overloaded => continue,
8790 .matches => |param_index| param_types[param_index],
8791 .matches_scalar => |param_index| param_types[param_index].scalarType(self),
8792 .matches_changed_scalar => |info| try param_types[info.index]
8793 .changeScalar(info.scalar, self),
8794 };
8795 }
8796
8797 const function_index = try self.addFunction(try self.fnType(switch (signature.ret_len) {
8798 0 => .void,
8799 1 => param_types[0],
8800 else => try self.structType(.normal, param_types[0..signature.ret_len]),
8801 }, param_types[signature.ret_len..], .normal), name, .default);
8802 function_index.ptr(self).attributes = try self.fnAttrs(function_attributes);
8803 return function_index;
8804}
8805
68868806pub fn intConst(self: *Builder, ty: Type, value: anytype) Allocator.Error!Constant {
8807 const int_value = switch (@typeInfo(@TypeOf(value))) {
8808 .Int, .ComptimeInt => value,
8809 .Enum => @intFromEnum(value),
8810 else => @compileError("intConst expected an integral value, got " ++ @typeName(@TypeOf(value))),
8811 };
68878812 var limbs: [
6888 switch (@typeInfo(@TypeOf(value))) {
8813 switch (@typeInfo(@TypeOf(int_value))) {
68898814 .Int => |info| std.math.big.int.calcTwosCompLimbCount(info.bits),
6890 .ComptimeInt => std.math.big.int.calcLimbLen(value),
6891 else => @compileError(
6892 "intConst expected an integral value, got " ++ @typeName(@TypeOf(value)),
6893 ),
8815 .ComptimeInt => std.math.big.int.calcLimbLen(int_value),
8816 else => unreachable,
68948817 }
68958818 ]std.math.big.Limb = undefined;
6896 return self.bigIntConst(ty, std.math.big.int.Mutable.init(&limbs, value).toConst());
8819 return self.bigIntConst(ty, std.math.big.int.Mutable.init(&limbs, int_value).toConst());
68978820}
68988821
68998822pub fn intValue(self: *Builder, ty: Type, value: anytype) Allocator.Error!Value {
......@@ -7301,27 +9224,75 @@ pub fn binValue(self: *Builder, tag: Constant.Tag, lhs: Constant, rhs: Constant)
73019224 return (try self.binConst(tag, lhs, rhs)).toValue();
73029225}
73039226
9227pub fn selectConst(
9228 self: *Builder,
9229 cond: Constant,
9230 lhs: Constant,
9231 rhs: Constant,
9232) Allocator.Error!Constant {
9233 try self.ensureUnusedConstantCapacity(1, Constant.Select, 0);
9234 return self.selectConstAssumeCapacity(cond, lhs, rhs);
9235}
9236
9237pub fn selectValue(self: *Builder, cond: Constant, lhs: Constant, rhs: Constant) Allocator.Error!Value {
9238 return (try self.selectConst(cond, lhs, rhs)).toValue();
9239}
9240
73049241pub fn asmConst(
73059242 self: *Builder,
73069243 ty: Type,
7307 info: Constant.Asm.Info,
9244 info: Constant.Assembly.Info,
73089245 assembly: String,
73099246 constraints: String,
73109247) Allocator.Error!Constant {
7311 try self.ensureUnusedConstantCapacity(1, Constant.Asm, 0);
9248 try self.ensureUnusedConstantCapacity(1, Constant.Assembly, 0);
73129249 return self.asmConstAssumeCapacity(ty, info, assembly, constraints);
73139250}
73149251
73159252pub fn asmValue(
73169253 self: *Builder,
73179254 ty: Type,
7318 info: Constant.Asm.Info,
9255 info: Constant.Assembly.Info,
73199256 assembly: String,
73209257 constraints: String,
73219258) Allocator.Error!Value {
73229259 return (try self.asmConst(ty, info, assembly, constraints)).toValue();
73239260}
73249261
9262pub fn verify(self: *Builder) error{}!bool {
9263 if (self.useLibLlvm()) {
9264 var error_message: [*:0]const u8 = undefined;
9265 // verifyModule always allocs the error_message even if there is no error
9266 defer llvm.disposeMessage(error_message);
9267
9268 if (self.llvm.module.?.verify(.ReturnStatus, &error_message).toBool()) {
9269 log.err("failed verification of LLVM module:\n{s}\n", .{error_message});
9270 return false;
9271 }
9272 }
9273 return true;
9274}
9275
9276pub fn writeBitcodeToFile(self: *Builder, path: []const u8) Allocator.Error!bool {
9277 const path_z = try self.gpa.dupeZ(u8, path);
9278 defer self.gpa.free(path_z);
9279 return self.writeBitcodeToFileZ(path_z);
9280}
9281
9282pub fn writeBitcodeToFileZ(self: *Builder, path: [*:0]const u8) bool {
9283 if (self.useLibLlvm()) {
9284 const error_code = self.llvm.module.?.writeBitcodeToFile(path);
9285 if (error_code != 0) {
9286 log.err("failed dumping LLVM module to \"{s}\": {d}", .{ path, error_code });
9287 return false;
9288 }
9289 } else {
9290 log.err("writing bitcode without libllvm not implemented", .{});
9291 return false;
9292 }
9293 return true;
9294}
9295
73259296pub fn dump(self: *Builder) void {
73269297 if (self.useLibLlvm())
73279298 self.llvm.module.?.dump()
......@@ -7413,7 +9384,7 @@ pub fn printUnbuffered(
74139384 if (variable.global.getReplacement(self) != .none) continue;
74149385 const global = variable.global.ptrConst(self);
74159386 try writer.print(
7416 \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{,}
9387 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }
74179388 \\
74189389 , .{
74199390 variable.global.fmt(self),
......@@ -7434,557 +9405,521 @@ pub fn printUnbuffered(
74349405 need_newline = true;
74359406 }
74369407
7437 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};
7438 defer attribute_groups.deinit(self.gpa);
7439
7440 if (self.functions.items.len > 0) {
9408 if (self.aliases.items.len > 0) {
74419409 if (need_newline) try writer.writeByte('\n');
7442 for (0.., self.functions.items) |function_i, function| {
7443 if (function_i > 0) try writer.writeByte('\n');
7444 const function_index: Function.Index = @enumFromInt(function_i);
7445 if (function.global.getReplacement(self) != .none) continue;
7446 const global = function.global.ptrConst(self);
7447 const params_len = global.type.functionParameters(self).len;
7448 const function_attributes = function.attributes.func(self);
7449 if (function_attributes != .none) try writer.print(
7450 \\; Function Attrs:{}
7451 \\
7452 , .{function_attributes.fmt(self)});
9410 for (self.aliases.items) |alias| {
9411 if (alias.global.getReplacement(self) != .none) continue;
9412 const global = alias.global.ptrConst(self);
74539413 try writer.print(
7454 \\{s}{}{}{}{}{}{"} {} {}(
9414 \\{} ={}{}{}{}{ }{} alias {%}, {%}
9415 \\
74559416 , .{
7456 if (function.instructions.len > 0) "define" else "declare",
9417 alias.global.fmt(self),
74579418 global.linkage,
74589419 global.preemption,
74599420 global.visibility,
74609421 global.dll_storage_class,
7461 function.call_conv,
7462 function.attributes.ret(self).fmt(self),
7463 global.type.functionReturn(self).fmt(self),
7464 function.global.fmt(self),
9422 alias.thread_local,
9423 global.unnamed_addr,
9424 global.type.fmt(self),
9425 alias.aliasee.fmt(self),
74659426 });
7466 for (0..params_len) |arg| {
7467 if (arg > 0) try writer.writeAll(", ");
7468 try writer.print(
7469 \\{%}{"}
7470 , .{
7471 global.type.functionParameters(self)[arg].fmt(self),
7472 function.attributes.param(arg, self).fmt(self),
7473 });
7474 if (function.instructions.len > 0)
7475 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)});
7476 }
7477 switch (global.type.functionKind(self)) {
7478 .normal => {},
7479 .vararg => {
7480 if (params_len > 0) try writer.writeAll(", ");
7481 try writer.writeAll("...");
7482 },
7483 }
7484 try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space });
7485 if (function_attributes != .none) try writer.print(" #{d}", .{
7486 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
9427 }
9428 need_newline = true;
9429 }
9430
9431 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};
9432 defer attribute_groups.deinit(self.gpa);
9433
9434 for (0.., self.functions.items) |function_i, function| {
9435 if (function.global.getReplacement(self) != .none) continue;
9436 if (need_newline) try writer.writeByte('\n');
9437 const function_index: Function.Index = @enumFromInt(function_i);
9438 const global = function.global.ptrConst(self);
9439 const params_len = global.type.functionParameters(self).len;
9440 const function_attributes = function.attributes.func(self);
9441 if (function_attributes != .none) try writer.print(
9442 \\; Function Attrs:{}
9443 \\
9444 , .{function_attributes.fmt(self)});
9445 try writer.print(
9446 \\{s}{}{}{}{}{}{"} {} {}(
9447 , .{
9448 if (function.instructions.len > 0) "define" else "declare",
9449 global.linkage,
9450 global.preemption,
9451 global.visibility,
9452 global.dll_storage_class,
9453 function.call_conv,
9454 function.attributes.ret(self).fmt(self),
9455 global.type.functionReturn(self).fmt(self),
9456 function.global.fmt(self),
9457 });
9458 for (0..params_len) |arg| {
9459 if (arg > 0) try writer.writeAll(", ");
9460 try writer.print(
9461 \\{%}{"}
9462 , .{
9463 global.type.functionParameters(self)[arg].fmt(self),
9464 function.attributes.param(arg, self).fmt(self),
74879465 });
7488 try writer.print("{}", .{function.alignment});
7489 if (function.instructions.len > 0) {
7490 var block_incoming_len: u32 = undefined;
7491 try writer.writeAll(" {\n");
7492 for (params_len..function.instructions.len) |instruction_i| {
7493 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
7494 const instruction = function.instructions.get(@intFromEnum(instruction_index));
7495 switch (instruction.tag) {
7496 .add,
7497 .@"add nsw",
7498 .@"add nuw",
7499 .@"add nuw nsw",
7500 .@"and",
7501 .ashr,
7502 .@"ashr exact",
7503 .fadd,
7504 .@"fadd fast",
7505 .@"fcmp false",
7506 .@"fcmp fast false",
7507 .@"fcmp fast oeq",
7508 .@"fcmp fast oge",
7509 .@"fcmp fast ogt",
7510 .@"fcmp fast ole",
7511 .@"fcmp fast olt",
7512 .@"fcmp fast one",
7513 .@"fcmp fast ord",
7514 .@"fcmp fast true",
7515 .@"fcmp fast ueq",
7516 .@"fcmp fast uge",
7517 .@"fcmp fast ugt",
7518 .@"fcmp fast ule",
7519 .@"fcmp fast ult",
7520 .@"fcmp fast une",
7521 .@"fcmp fast uno",
7522 .@"fcmp oeq",
7523 .@"fcmp oge",
7524 .@"fcmp ogt",
7525 .@"fcmp ole",
7526 .@"fcmp olt",
7527 .@"fcmp one",
7528 .@"fcmp ord",
7529 .@"fcmp true",
7530 .@"fcmp ueq",
7531 .@"fcmp uge",
7532 .@"fcmp ugt",
7533 .@"fcmp ule",
7534 .@"fcmp ult",
7535 .@"fcmp une",
7536 .@"fcmp uno",
7537 .fdiv,
7538 .@"fdiv fast",
7539 .fmul,
7540 .@"fmul fast",
7541 .frem,
7542 .@"frem fast",
7543 .fsub,
7544 .@"fsub fast",
7545 .@"icmp eq",
7546 .@"icmp ne",
7547 .@"icmp sge",
7548 .@"icmp sgt",
7549 .@"icmp sle",
7550 .@"icmp slt",
7551 .@"icmp uge",
7552 .@"icmp ugt",
7553 .@"icmp ule",
7554 .@"icmp ult",
7555 .lshr,
7556 .@"lshr exact",
7557 .mul,
7558 .@"mul nsw",
7559 .@"mul nuw",
7560 .@"mul nuw nsw",
7561 .@"or",
7562 .sdiv,
7563 .@"sdiv exact",
7564 .srem,
7565 .shl,
7566 .@"shl nsw",
7567 .@"shl nuw",
7568 .@"shl nuw nsw",
7569 .sub,
7570 .@"sub nsw",
7571 .@"sub nuw",
7572 .@"sub nuw nsw",
7573 .udiv,
7574 .@"udiv exact",
7575 .urem,
7576 .xor,
7577 => |tag| {
7578 const extra =
7579 function.extraData(Function.Instruction.Binary, instruction.data);
7580 try writer.print(" %{} = {s} {%}, {}\n", .{
7581 instruction_index.name(&function).fmt(self),
7582 @tagName(tag),
7583 extra.lhs.fmt(function_index, self),
7584 extra.rhs.fmt(function_index, self),
7585 });
7586 },
7587 .addrspacecast,
7588 .bitcast,
7589 .fpext,
7590 .fptosi,
7591 .fptoui,
7592 .fptrunc,
7593 .inttoptr,
7594 .ptrtoint,
7595 .sext,
7596 .sitofp,
7597 .trunc,
7598 .uitofp,
7599 .zext,
7600 => |tag| {
7601 const extra =
7602 function.extraData(Function.Instruction.Cast, instruction.data);
7603 try writer.print(" %{} = {s} {%} to {%}\n", .{
7604 instruction_index.name(&function).fmt(self),
7605 @tagName(tag),
7606 extra.val.fmt(function_index, self),
7607 extra.type.fmt(self),
7608 });
7609 },
7610 .alloca,
7611 .@"alloca inalloca",
7612 => |tag| {
7613 const extra =
7614 function.extraData(Function.Instruction.Alloca, instruction.data);
7615 try writer.print(" %{} = {s} {%}{,%}{,}{,}\n", .{
7616 instruction_index.name(&function).fmt(self),
7617 @tagName(tag),
7618 extra.type.fmt(self),
7619 extra.len.fmt(function_index, self),
7620 extra.info.alignment,
7621 extra.info.addr_space,
7622 });
7623 },
7624 .arg => unreachable,
7625 .block => {
7626 block_incoming_len = instruction.data;
7627 const name = instruction_index.name(&function);
7628 if (@intFromEnum(instruction_index) > params_len)
7629 try writer.writeByte('\n');
7630 try writer.print("{}:\n", .{name.fmt(self)});
7631 },
7632 .br => |tag| {
7633 const target: Function.Block.Index = @enumFromInt(instruction.data);
7634 try writer.print(" {s} {%}\n", .{
7635 @tagName(tag), target.toInst(&function).fmt(function_index, self),
7636 });
7637 },
7638 .br_cond => {
7639 const extra =
7640 function.extraData(Function.Instruction.BrCond, instruction.data);
7641 try writer.print(" br {%}, {%}, {%}\n", .{
7642 extra.cond.fmt(function_index, self),
7643 extra.then.toInst(&function).fmt(function_index, self),
7644 extra.@"else".toInst(&function).fmt(function_index, self),
7645 });
7646 },
7647 .call,
7648 .@"call fast",
7649 .@"musttail call",
7650 .@"musttail call fast",
7651 .@"notail call",
7652 .@"notail call fast",
7653 .@"tail call",
7654 .@"tail call fast",
7655 => |tag| {
7656 var extra =
7657 function.extraDataTrail(Function.Instruction.Call, instruction.data);
7658 const args = extra.trail.next(extra.data.args_len, Value, &function);
7659 try writer.writeAll(" ");
7660 const ret_ty = extra.data.ty.functionReturn(self);
7661 switch (ret_ty) {
7662 .void => {},
7663 else => try writer.print("%{} = ", .{
7664 instruction_index.name(&function).fmt(self),
7665 }),
7666 .none => unreachable,
7667 }
7668 try writer.print("{s}{}{}{} {%} {}(", .{
7669 @tagName(tag),
7670 extra.data.info.call_conv,
7671 extra.data.attributes.ret(self).fmt(self),
7672 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),
7673 switch (extra.data.ty.functionKind(self)) {
7674 .normal => ret_ty,
7675 .vararg => extra.data.ty,
7676 }.fmt(self),
7677 extra.data.callee.fmt(function_index, self),
7678 });
7679 for (0.., args) |arg_index, arg| {
7680 if (arg_index > 0) try writer.writeAll(", ");
7681 try writer.print("{%}{} {}", .{
7682 arg.typeOf(function_index, self).fmt(self),
7683 extra.data.attributes.param(arg_index, self).fmt(self),
7684 arg.fmt(function_index, self),
7685 });
7686 }
7687 try writer.writeByte(')');
7688 const call_function_attributes = extra.data.attributes.func(self);
7689 if (call_function_attributes != .none) try writer.print(" #{d}", .{
7690 (try attribute_groups.getOrPutValue(
7691 self.gpa,
7692 call_function_attributes,
7693 {},
7694 )).index,
7695 });
7696 try writer.writeByte('\n');
7697 },
7698 .extractelement => |tag| {
7699 const extra = function.extraData(
7700 Function.Instruction.ExtractElement,
7701 instruction.data,
7702 );
7703 try writer.print(" %{} = {s} {%}, {%}\n", .{
7704 instruction_index.name(&function).fmt(self),
7705 @tagName(tag),
7706 extra.val.fmt(function_index, self),
7707 extra.index.fmt(function_index, self),
7708 });
7709 },
7710 .extractvalue => |tag| {
7711 var extra = function.extraDataTrail(
7712 Function.Instruction.ExtractValue,
7713 instruction.data,
7714 );
7715 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
7716 try writer.print(" %{} = {s} {%}", .{
7717 instruction_index.name(&function).fmt(self),
7718 @tagName(tag),
7719 extra.data.val.fmt(function_index, self),
7720 });
7721 for (indices) |index| try writer.print(", {d}", .{index});
7722 try writer.writeByte('\n');
7723 },
7724 .fence => |tag| {
7725 const info: MemoryAccessInfo = @bitCast(instruction.data);
7726 try writer.print(" {s}{}{}", .{ @tagName(tag), info.scope, info.ordering });
7727 },
7728 .fneg,
7729 .@"fneg fast",
7730 .ret,
7731 .@"llvm.ceil.",
7732 .@"llvm.cos.",
7733 .@"llvm.exp.",
7734 .@"llvm.exp2.",
7735 .@"llvm.fabs.",
7736 .@"llvm.floor.",
7737 .@"llvm.log.",
7738 .@"llvm.log10.",
7739 .@"llvm.log2.",
7740 .@"llvm.round.",
7741 .@"llvm.sin.",
7742 .@"llvm.sqrt.",
7743 .@"llvm.trunc.",
7744 .@"llvm.bitreverse.",
7745 .@"llvm.bswap.",
7746 .@"llvm.ctpop.",
7747 => |tag| {
7748 const val: Value = @enumFromInt(instruction.data);
7749 try writer.print(" {s} {%}\n", .{
7750 @tagName(tag),
7751 val.fmt(function_index, self),
7752 });
7753 },
7754 .getelementptr,
7755 .@"getelementptr inbounds",
7756 => |tag| {
7757 var extra = function.extraDataTrail(
7758 Function.Instruction.GetElementPtr,
7759 instruction.data,
7760 );
7761 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
7762 try writer.print(" %{} = {s} {%}, {%}", .{
7763 instruction_index.name(&function).fmt(self),
7764 @tagName(tag),
7765 extra.data.type.fmt(self),
7766 extra.data.base.fmt(function_index, self),
7767 });
7768 for (indices) |index| try writer.print(", {%}", .{
7769 index.fmt(function_index, self),
7770 });
7771 try writer.writeByte('\n');
7772 },
7773 .insertelement => |tag| {
7774 const extra = function.extraData(
7775 Function.Instruction.InsertElement,
7776 instruction.data,
7777 );
7778 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
7779 instruction_index.name(&function).fmt(self),
7780 @tagName(tag),
7781 extra.val.fmt(function_index, self),
7782 extra.elem.fmt(function_index, self),
7783 extra.index.fmt(function_index, self),
7784 });
7785 },
7786 .insertvalue => |tag| {
7787 var extra = function.extraDataTrail(
7788 Function.Instruction.InsertValue,
7789 instruction.data,
7790 );
7791 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
7792 try writer.print(" %{} = {s} {%}, {%}", .{
7793 instruction_index.name(&function).fmt(self),
7794 @tagName(tag),
7795 extra.data.val.fmt(function_index, self),
7796 extra.data.elem.fmt(function_index, self),
7797 });
7798 for (indices) |index| try writer.print(", {d}", .{index});
7799 try writer.writeByte('\n');
7800 },
7801 .@"llvm.maxnum.",
7802 .@"llvm.minnum.",
7803 .@"llvm.ctlz.",
7804 .@"llvm.cttz.",
7805 .@"llvm.sadd.sat.",
7806 .@"llvm.smax.",
7807 .@"llvm.smin.",
7808 .@"llvm.smul.fix.sat.",
7809 .@"llvm.sshl.sat.",
7810 .@"llvm.ssub.sat.",
7811 .@"llvm.uadd.sat.",
7812 .@"llvm.umax.",
7813 .@"llvm.umin.",
7814 .@"llvm.umul.fix.sat.",
7815 .@"llvm.ushl.sat.",
7816 .@"llvm.usub.sat.",
7817 => |tag| {
7818 const extra =
7819 function.extraData(Function.Instruction.Binary, instruction.data);
7820 const ty = instruction_index.typeOf(function_index, self);
7821 try writer.print(" %{} = call {%} @{s}{m}({%}, {%}{s})\n", .{
7822 instruction_index.name(&function).fmt(self),
7823 ty.fmt(self),
7824 @tagName(tag),
7825 ty.fmt(self),
7826 extra.lhs.fmt(function_index, self),
7827 extra.rhs.fmt(function_index, self),
7828 switch (tag) {
7829 .@"llvm.smul.fix.sat.",
7830 .@"llvm.umul.fix.sat.",
7831 => ", i32 0",
7832 else => "",
7833 },
7834 });
7835 },
7836 .load,
7837 .@"load atomic",
7838 .@"load atomic volatile",
7839 .@"load volatile",
7840 => |tag| {
7841 const extra =
7842 function.extraData(Function.Instruction.Load, instruction.data);
7843 try writer.print(" %{} = {s} {%}, {%}{}{}{,}\n", .{
7844 instruction_index.name(&function).fmt(self),
7845 @tagName(tag),
7846 extra.type.fmt(self),
7847 extra.ptr.fmt(function_index, self),
7848 extra.info.scope,
7849 extra.info.ordering,
7850 extra.info.alignment,
7851 });
7852 },
7853 .phi,
7854 .@"phi fast",
7855 => |tag| {
7856 var extra =
7857 function.extraDataTrail(Function.Instruction.Phi, instruction.data);
7858 const vals = extra.trail.next(block_incoming_len, Value, &function);
7859 const blocks =
7860 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
7861 try writer.print(" %{} = {s} {%} ", .{
7862 instruction_index.name(&function).fmt(self),
7863 @tagName(tag),
7864 vals[0].typeOf(function_index, self).fmt(self),
7865 });
7866 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
7867 if (incoming_index > 0) try writer.writeAll(", ");
7868 try writer.print("[ {}, {} ]", .{
7869 incoming_val.fmt(function_index, self),
7870 incoming_block.toInst(&function).fmt(function_index, self),
7871 });
7872 }
9466 if (function.instructions.len > 0)
9467 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)})
9468 else
9469 try writer.print(" %{d}", .{arg});
9470 }
9471 switch (global.type.functionKind(self)) {
9472 .normal => {},
9473 .vararg => {
9474 if (params_len > 0) try writer.writeAll(", ");
9475 try writer.writeAll("...");
9476 },
9477 }
9478 try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });
9479 if (function_attributes != .none) try writer.print(" #{d}", .{
9480 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
9481 });
9482 try writer.print("{ }", .{function.alignment});
9483 if (function.instructions.len > 0) {
9484 var block_incoming_len: u32 = undefined;
9485 try writer.writeAll(" {\n");
9486 for (params_len..function.instructions.len) |instruction_i| {
9487 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
9488 const instruction = function.instructions.get(@intFromEnum(instruction_index));
9489 switch (instruction.tag) {
9490 .add,
9491 .@"add nsw",
9492 .@"add nuw",
9493 .@"add nuw nsw",
9494 .@"and",
9495 .ashr,
9496 .@"ashr exact",
9497 .fadd,
9498 .@"fadd fast",
9499 .@"fcmp false",
9500 .@"fcmp fast false",
9501 .@"fcmp fast oeq",
9502 .@"fcmp fast oge",
9503 .@"fcmp fast ogt",
9504 .@"fcmp fast ole",
9505 .@"fcmp fast olt",
9506 .@"fcmp fast one",
9507 .@"fcmp fast ord",
9508 .@"fcmp fast true",
9509 .@"fcmp fast ueq",
9510 .@"fcmp fast uge",
9511 .@"fcmp fast ugt",
9512 .@"fcmp fast ule",
9513 .@"fcmp fast ult",
9514 .@"fcmp fast une",
9515 .@"fcmp fast uno",
9516 .@"fcmp oeq",
9517 .@"fcmp oge",
9518 .@"fcmp ogt",
9519 .@"fcmp ole",
9520 .@"fcmp olt",
9521 .@"fcmp one",
9522 .@"fcmp ord",
9523 .@"fcmp true",
9524 .@"fcmp ueq",
9525 .@"fcmp uge",
9526 .@"fcmp ugt",
9527 .@"fcmp ule",
9528 .@"fcmp ult",
9529 .@"fcmp une",
9530 .@"fcmp uno",
9531 .fdiv,
9532 .@"fdiv fast",
9533 .fmul,
9534 .@"fmul fast",
9535 .frem,
9536 .@"frem fast",
9537 .fsub,
9538 .@"fsub fast",
9539 .@"icmp eq",
9540 .@"icmp ne",
9541 .@"icmp sge",
9542 .@"icmp sgt",
9543 .@"icmp sle",
9544 .@"icmp slt",
9545 .@"icmp uge",
9546 .@"icmp ugt",
9547 .@"icmp ule",
9548 .@"icmp ult",
9549 .lshr,
9550 .@"lshr exact",
9551 .mul,
9552 .@"mul nsw",
9553 .@"mul nuw",
9554 .@"mul nuw nsw",
9555 .@"or",
9556 .sdiv,
9557 .@"sdiv exact",
9558 .srem,
9559 .shl,
9560 .@"shl nsw",
9561 .@"shl nuw",
9562 .@"shl nuw nsw",
9563 .sub,
9564 .@"sub nsw",
9565 .@"sub nuw",
9566 .@"sub nuw nsw",
9567 .udiv,
9568 .@"udiv exact",
9569 .urem,
9570 .xor,
9571 => |tag| {
9572 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
9573 try writer.print(" %{} = {s} {%}, {}\n", .{
9574 instruction_index.name(&function).fmt(self),
9575 @tagName(tag),
9576 extra.lhs.fmt(function_index, self),
9577 extra.rhs.fmt(function_index, self),
9578 });
9579 },
9580 .addrspacecast,
9581 .bitcast,
9582 .fpext,
9583 .fptosi,
9584 .fptoui,
9585 .fptrunc,
9586 .inttoptr,
9587 .ptrtoint,
9588 .sext,
9589 .sitofp,
9590 .trunc,
9591 .uitofp,
9592 .zext,
9593 => |tag| {
9594 const extra = function.extraData(Function.Instruction.Cast, instruction.data);
9595 try writer.print(" %{} = {s} {%} to {%}\n", .{
9596 instruction_index.name(&function).fmt(self),
9597 @tagName(tag),
9598 extra.val.fmt(function_index, self),
9599 extra.type.fmt(self),
9600 });
9601 },
9602 .alloca,
9603 .@"alloca inalloca",
9604 => |tag| {
9605 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
9606 try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{
9607 instruction_index.name(&function).fmt(self),
9608 @tagName(tag),
9609 extra.type.fmt(self),
9610 extra.len.fmt(function_index, self),
9611 extra.info.alignment,
9612 extra.info.addr_space,
9613 });
9614 },
9615 .arg => unreachable,
9616 .atomicrmw => |tag| {
9617 const extra =
9618 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
9619 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{
9620 instruction_index.name(&function).fmt(self),
9621 @tagName(tag),
9622 extra.info.access_kind,
9623 @tagName(extra.info.atomic_rmw_operation),
9624 extra.ptr.fmt(function_index, self),
9625 extra.val.fmt(function_index, self),
9626 extra.info.sync_scope,
9627 extra.info.success_ordering,
9628 extra.info.alignment,
9629 });
9630 },
9631 .block => {
9632 block_incoming_len = instruction.data;
9633 const name = instruction_index.name(&function);
9634 if (@intFromEnum(instruction_index) > params_len)
78739635 try writer.writeByte('\n');
7874 },
7875 .@"ret void",
7876 .@"unreachable",
7877 => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),
7878 .select,
7879 .@"select fast",
7880 => |tag| {
7881 const extra =
7882 function.extraData(Function.Instruction.Select, instruction.data);
7883 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
7884 instruction_index.name(&function).fmt(self),
7885 @tagName(tag),
7886 extra.cond.fmt(function_index, self),
7887 extra.lhs.fmt(function_index, self),
7888 extra.rhs.fmt(function_index, self),
7889 });
7890 },
7891 .shufflevector => |tag| {
7892 const extra = function.extraData(
7893 Function.Instruction.ShuffleVector,
7894 instruction.data,
7895 );
7896 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
7897 instruction_index.name(&function).fmt(self),
7898 @tagName(tag),
7899 extra.lhs.fmt(function_index, self),
7900 extra.rhs.fmt(function_index, self),
7901 extra.mask.fmt(function_index, self),
7902 });
7903 },
7904 .store,
7905 .@"store atomic",
7906 .@"store atomic volatile",
7907 .@"store volatile",
7908 => |tag| {
7909 const extra =
7910 function.extraData(Function.Instruction.Store, instruction.data);
7911 try writer.print(" {s} {%}, {%}{}{}{,}\n", .{
7912 @tagName(tag),
7913 extra.val.fmt(function_index, self),
7914 extra.ptr.fmt(function_index, self),
7915 extra.info.scope,
7916 extra.info.ordering,
7917 extra.info.alignment,
7918 });
7919 },
7920 .@"switch" => |tag| {
7921 var extra =
7922 function.extraDataTrail(Function.Instruction.Switch, instruction.data);
7923 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
7924 const blocks =
7925 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
7926 try writer.print(" {s} {%}, {%} [\n", .{
7927 @tagName(tag),
7928 extra.data.val.fmt(function_index, self),
7929 extra.data.default.toInst(&function).fmt(function_index, self),
7930 });
7931 for (vals, blocks) |case_val, case_block| try writer.print(
7932 " {%}, {%}\n",
7933 .{
7934 case_val.fmt(self),
7935 case_block.toInst(&function).fmt(function_index, self),
7936 },
7937 );
7938 try writer.writeAll(" ]\n");
7939 },
7940 .unimplemented => |tag| {
7941 const ty: Type = @enumFromInt(instruction.data);
7942 if (true) {
7943 try writer.writeAll(" ");
7944 switch (ty) {
7945 .none, .void => {},
7946 else => try writer.print("%{} = ", .{
7947 instruction_index.name(&function).fmt(self),
7948 }),
7949 }
7950 try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) });
7951 } else switch (ty) {
7952 .none, .void => {},
7953 else => try writer.print(" %{} = load {%}, ptr undef\n", .{
7954 instruction_index.name(&function).fmt(self),
7955 ty.fmt(self),
7956 }),
7957 }
7958 },
7959 .va_arg => |tag| {
7960 const extra =
7961 function.extraData(Function.Instruction.VaArg, instruction.data);
7962 try writer.print(" %{} = {s} {%}, {%}\n", .{
9636 try writer.print("{}:\n", .{name.fmt(self)});
9637 },
9638 .br => |tag| {
9639 const target: Function.Block.Index = @enumFromInt(instruction.data);
9640 try writer.print(" {s} {%}\n", .{
9641 @tagName(tag), target.toInst(&function).fmt(function_index, self),
9642 });
9643 },
9644 .br_cond => {
9645 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
9646 try writer.print(" br {%}, {%}, {%}\n", .{
9647 extra.cond.fmt(function_index, self),
9648 extra.then.toInst(&function).fmt(function_index, self),
9649 extra.@"else".toInst(&function).fmt(function_index, self),
9650 });
9651 },
9652 .call,
9653 .@"call fast",
9654 .@"musttail call",
9655 .@"musttail call fast",
9656 .@"notail call",
9657 .@"notail call fast",
9658 .@"tail call",
9659 .@"tail call fast",
9660 => |tag| {
9661 var extra =
9662 function.extraDataTrail(Function.Instruction.Call, instruction.data);
9663 const args = extra.trail.next(extra.data.args_len, Value, &function);
9664 try writer.writeAll(" ");
9665 const ret_ty = extra.data.ty.functionReturn(self);
9666 switch (ret_ty) {
9667 .void => {},
9668 else => try writer.print("%{} = ", .{
79639669 instruction_index.name(&function).fmt(self),
7964 @tagName(tag),
7965 extra.list.fmt(function_index, self),
7966 extra.type.fmt(self),
9670 }),
9671 .none => unreachable,
9672 }
9673 try writer.print("{s}{}{}{} {%} {}(", .{
9674 @tagName(tag),
9675 extra.data.info.call_conv,
9676 extra.data.attributes.ret(self).fmt(self),
9677 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),
9678 switch (extra.data.ty.functionKind(self)) {
9679 .normal => ret_ty,
9680 .vararg => extra.data.ty,
9681 }.fmt(self),
9682 extra.data.callee.fmt(function_index, self),
9683 });
9684 for (0.., args) |arg_index, arg| {
9685 if (arg_index > 0) try writer.writeAll(", ");
9686 try writer.print("{%}{} {}", .{
9687 arg.typeOf(function_index, self).fmt(self),
9688 extra.data.attributes.param(arg_index, self).fmt(self),
9689 arg.fmt(function_index, self),
79679690 });
7968 },
7969 .@"llvm.fma." => {
7970 const extra =
7971 function.extraData(Function.Instruction.FusedMultiplyAdd, instruction.data);
7972 const ty = instruction_index.typeOf(function_index, self);
7973 try writer.print(" %{} = call {%} @llvm.fma.{m}({%}, {%}, {%})\n", .{
7974 instruction_index.name(&function).fmt(self),
7975 ty.fmt(self),
7976 ty.fmt(self),
7977 extra.a.fmt(function_index, self),
7978 extra.b.fmt(function_index, self),
7979 extra.c.fmt(function_index, self),
9691 }
9692 try writer.writeByte(')');
9693 const call_function_attributes = extra.data.attributes.func(self);
9694 if (call_function_attributes != .none) try writer.print(" #{d}", .{
9695 (try attribute_groups.getOrPutValue(
9696 self.gpa,
9697 call_function_attributes,
9698 {},
9699 )).index,
9700 });
9701 try writer.writeByte('\n');
9702 },
9703 .cmpxchg,
9704 .@"cmpxchg weak",
9705 => |tag| {
9706 const extra =
9707 function.extraData(Function.Instruction.CmpXchg, instruction.data);
9708 try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{
9709 instruction_index.name(&function).fmt(self),
9710 @tagName(tag),
9711 extra.info.access_kind,
9712 extra.ptr.fmt(function_index, self),
9713 extra.cmp.fmt(function_index, self),
9714 extra.new.fmt(function_index, self),
9715 extra.info.sync_scope,
9716 extra.info.success_ordering,
9717 extra.info.failure_ordering,
9718 extra.info.alignment,
9719 });
9720 },
9721 .extractelement => |tag| {
9722 const extra =
9723 function.extraData(Function.Instruction.ExtractElement, instruction.data);
9724 try writer.print(" %{} = {s} {%}, {%}\n", .{
9725 instruction_index.name(&function).fmt(self),
9726 @tagName(tag),
9727 extra.val.fmt(function_index, self),
9728 extra.index.fmt(function_index, self),
9729 });
9730 },
9731 .extractvalue => |tag| {
9732 var extra = function.extraDataTrail(
9733 Function.Instruction.ExtractValue,
9734 instruction.data,
9735 );
9736 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9737 try writer.print(" %{} = {s} {%}", .{
9738 instruction_index.name(&function).fmt(self),
9739 @tagName(tag),
9740 extra.data.val.fmt(function_index, self),
9741 });
9742 for (indices) |index| try writer.print(", {d}", .{index});
9743 try writer.writeByte('\n');
9744 },
9745 .fence => |tag| {
9746 const info: MemoryAccessInfo = @bitCast(instruction.data);
9747 try writer.print(" {s}{ }{ }", .{
9748 @tagName(tag),
9749 info.sync_scope,
9750 info.success_ordering,
9751 });
9752 },
9753 .fneg,
9754 .@"fneg fast",
9755 => |tag| {
9756 const val: Value = @enumFromInt(instruction.data);
9757 try writer.print(" %{} = {s} {%}\n", .{
9758 instruction_index.name(&function).fmt(self),
9759 @tagName(tag),
9760 val.fmt(function_index, self),
9761 });
9762 },
9763 .getelementptr,
9764 .@"getelementptr inbounds",
9765 => |tag| {
9766 var extra = function.extraDataTrail(
9767 Function.Instruction.GetElementPtr,
9768 instruction.data,
9769 );
9770 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
9771 try writer.print(" %{} = {s} {%}, {%}", .{
9772 instruction_index.name(&function).fmt(self),
9773 @tagName(tag),
9774 extra.data.type.fmt(self),
9775 extra.data.base.fmt(function_index, self),
9776 });
9777 for (indices) |index| try writer.print(", {%}", .{
9778 index.fmt(function_index, self),
9779 });
9780 try writer.writeByte('\n');
9781 },
9782 .insertelement => |tag| {
9783 const extra =
9784 function.extraData(Function.Instruction.InsertElement, instruction.data);
9785 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
9786 instruction_index.name(&function).fmt(self),
9787 @tagName(tag),
9788 extra.val.fmt(function_index, self),
9789 extra.elem.fmt(function_index, self),
9790 extra.index.fmt(function_index, self),
9791 });
9792 },
9793 .insertvalue => |tag| {
9794 var extra =
9795 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);
9796 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9797 try writer.print(" %{} = {s} {%}, {%}", .{
9798 instruction_index.name(&function).fmt(self),
9799 @tagName(tag),
9800 extra.data.val.fmt(function_index, self),
9801 extra.data.elem.fmt(function_index, self),
9802 });
9803 for (indices) |index| try writer.print(", {d}", .{index});
9804 try writer.writeByte('\n');
9805 },
9806 .load,
9807 .@"load atomic",
9808 => |tag| {
9809 const extra = function.extraData(Function.Instruction.Load, instruction.data);
9810 try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{
9811 instruction_index.name(&function).fmt(self),
9812 @tagName(tag),
9813 extra.info.access_kind,
9814 extra.type.fmt(self),
9815 extra.ptr.fmt(function_index, self),
9816 extra.info.sync_scope,
9817 extra.info.success_ordering,
9818 extra.info.alignment,
9819 });
9820 },
9821 .phi,
9822 .@"phi fast",
9823 => |tag| {
9824 var extra = function.extraDataTrail(Function.Instruction.Phi, instruction.data);
9825 const vals = extra.trail.next(block_incoming_len, Value, &function);
9826 const blocks =
9827 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
9828 try writer.print(" %{} = {s} {%} ", .{
9829 instruction_index.name(&function).fmt(self),
9830 @tagName(tag),
9831 vals[0].typeOf(function_index, self).fmt(self),
9832 });
9833 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
9834 if (incoming_index > 0) try writer.writeAll(", ");
9835 try writer.print("[ {}, {} ]", .{
9836 incoming_val.fmt(function_index, self),
9837 incoming_block.toInst(&function).fmt(function_index, self),
79809838 });
7981 },
7982 }
9839 }
9840 try writer.writeByte('\n');
9841 },
9842 .ret => |tag| {
9843 const val: Value = @enumFromInt(instruction.data);
9844 try writer.print(" {s} {%}\n", .{
9845 @tagName(tag),
9846 val.fmt(function_index, self),
9847 });
9848 },
9849 .@"ret void",
9850 .@"unreachable",
9851 => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),
9852 .select,
9853 .@"select fast",
9854 => |tag| {
9855 const extra = function.extraData(Function.Instruction.Select, instruction.data);
9856 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
9857 instruction_index.name(&function).fmt(self),
9858 @tagName(tag),
9859 extra.cond.fmt(function_index, self),
9860 extra.lhs.fmt(function_index, self),
9861 extra.rhs.fmt(function_index, self),
9862 });
9863 },
9864 .shufflevector => |tag| {
9865 const extra =
9866 function.extraData(Function.Instruction.ShuffleVector, instruction.data);
9867 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
9868 instruction_index.name(&function).fmt(self),
9869 @tagName(tag),
9870 extra.lhs.fmt(function_index, self),
9871 extra.rhs.fmt(function_index, self),
9872 extra.mask.fmt(function_index, self),
9873 });
9874 },
9875 .store,
9876 .@"store atomic",
9877 => |tag| {
9878 const extra = function.extraData(Function.Instruction.Store, instruction.data);
9879 try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{
9880 @tagName(tag),
9881 extra.info.access_kind,
9882 extra.val.fmt(function_index, self),
9883 extra.ptr.fmt(function_index, self),
9884 extra.info.sync_scope,
9885 extra.info.success_ordering,
9886 extra.info.alignment,
9887 });
9888 },
9889 .@"switch" => |tag| {
9890 var extra =
9891 function.extraDataTrail(Function.Instruction.Switch, instruction.data);
9892 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
9893 const blocks =
9894 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
9895 try writer.print(" {s} {%}, {%} [\n", .{
9896 @tagName(tag),
9897 extra.data.val.fmt(function_index, self),
9898 extra.data.default.toInst(&function).fmt(function_index, self),
9899 });
9900 for (vals, blocks) |case_val, case_block| try writer.print(
9901 " {%}, {%}\n",
9902 .{
9903 case_val.fmt(self),
9904 case_block.toInst(&function).fmt(function_index, self),
9905 },
9906 );
9907 try writer.writeAll(" ]\n");
9908 },
9909 .va_arg => |tag| {
9910 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);
9911 try writer.print(" %{} = {s} {%}, {%}\n", .{
9912 instruction_index.name(&function).fmt(self),
9913 @tagName(tag),
9914 extra.list.fmt(function_index, self),
9915 extra.type.fmt(self),
9916 });
9917 },
79839918 }
7984 try writer.writeByte('}');
79859919 }
7986 try writer.writeByte('\n');
9920 try writer.writeByte('}');
79879921 }
9922 try writer.writeByte('\n');
79889923 need_newline = true;
79899924 }
79909925
......@@ -8080,7 +10015,7 @@ fn fnTypeAssumeCapacity(
808010015 gop.key_ptr.* = {};
808110016 gop.value_ptr.* = {};
808210017 self.type_items.appendAssumeCapacity(.{
8083 .tag = .function,
10018 .tag = tag,
808410019 .data = self.addTypeExtraAssumeCapacity(Type.Function{
808510020 .ret = ret,
808610021 .params_len = @intCast(params.len),
......@@ -9378,7 +11313,7 @@ fn icmpConstAssumeCapacity(
937811313 .data = self.addConstantExtraAssumeCapacity(data),
937911314 });
938011315 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
9381 llvm.constICmp(@enumFromInt(@intFromEnum(cond)), lhs.toLlvm(self), rhs.toLlvm(self)),
11316 llvm.constICmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)),
938211317 );
938311318 }
938411319 return @enumFromInt(gop.index);
......@@ -9415,7 +11350,7 @@ fn fcmpConstAssumeCapacity(
941511350 .data = self.addConstantExtraAssumeCapacity(data),
941611351 });
941711352 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
9418 llvm.constFCmp(@enumFromInt(@intFromEnum(cond)), lhs.toLlvm(self), rhs.toLlvm(self)),
11353 llvm.constFCmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)),
941911354 );
942011355 }
942111356 return @enumFromInt(gop.index);
......@@ -9601,16 +11536,52 @@ fn binConstAssumeCapacity(
960111536 return @enumFromInt(gop.index);
960211537}
960311538
11539comptime {
11540 _ = &selectValue;
11541}
11542
11543fn selectConstAssumeCapacity(self: *Builder, cond: Constant, lhs: Constant, rhs: Constant) Constant {
11544 const Adapter = struct {
11545 builder: *const Builder,
11546 pub fn hash(_: @This(), key: Constant.Select) u32 {
11547 return @truncate(std.hash.Wyhash.hash(
11548 std.hash.uint32(@intFromEnum(Constant.Tag.select)),
11549 std.mem.asBytes(&key),
11550 ));
11551 }
11552 pub fn eql(ctx: @This(), lhs_key: Constant.Select, _: void, rhs_index: usize) bool {
11553 if (ctx.builder.constant_items.items(.tag)[rhs_index] != .select) return false;
11554 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
11555 const rhs_extra = ctx.builder.constantExtraData(Constant.Select, rhs_data);
11556 return std.meta.eql(lhs_key, rhs_extra);
11557 }
11558 };
11559 const data = Constant.Select{ .cond = cond, .lhs = lhs, .rhs = rhs };
11560 const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self });
11561 if (!gop.found_existing) {
11562 gop.key_ptr.* = {};
11563 gop.value_ptr.* = {};
11564 self.constant_items.appendAssumeCapacity(.{
11565 .tag = .select,
11566 .data = self.addConstantExtraAssumeCapacity(data),
11567 });
11568 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
11569 cond.toLlvm(self).constSelect(lhs.toLlvm(self), rhs.toLlvm(self)),
11570 );
11571 }
11572 return @enumFromInt(gop.index);
11573}
11574
960411575fn asmConstAssumeCapacity(
960511576 self: *Builder,
960611577 ty: Type,
9607 info: Constant.Asm.Info,
11578 info: Constant.Assembly.Info,
960811579 assembly: String,
960911580 constraints: String,
961011581) Constant {
961111582 assert(ty.functionKind(self) == .normal);
961211583
9613 const Key = struct { tag: Constant.Tag, extra: Constant.Asm };
11584 const Key = struct { tag: Constant.Tag, extra: Constant.Assembly };
961411585 const Adapter = struct {
961511586 builder: *const Builder,
961611587 pub fn hash(_: @This(), key: Key) u32 {
......@@ -9622,7 +11593,7 @@ fn asmConstAssumeCapacity(
962211593 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
962311594 if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false;
962411595 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
9625 const rhs_extra = ctx.builder.constantExtraData(Constant.Asm, rhs_data);
11596 const rhs_extra = ctx.builder.constantExtraData(Constant.Assembly, rhs_data);
962611597 return std.meta.eql(lhs_key.extra, rhs_extra);
962711598 }
962811599 };
src/codegen/llvm/bindings.zig+14-315
......@@ -93,17 +93,6 @@ pub const Context = opaque {
9393 pub const constString = LLVMConstStringInContext;
9494 extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) *Value;
9595
96 pub const constStruct = LLVMConstStructInContext;
97 extern fn LLVMConstStructInContext(
98 C: *Context,
99 ConstantVals: [*]const *Value,
100 Count: c_uint,
101 Packed: Bool,
102 ) *Value;
103
104 pub const createBasicBlock = LLVMCreateBasicBlockInContext;
105 extern fn LLVMCreateBasicBlockInContext(C: *Context, Name: [*:0]const u8) *BasicBlock;
106
10796 pub const appendBasicBlock = LLVMAppendBasicBlockInContext;
10897 extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*:0]const u8) *BasicBlock;
10998
......@@ -115,18 +104,18 @@ pub const Context = opaque {
115104};
116105
117106pub const Value = opaque {
118 pub const addAttributeAtIndex = ZigLLVMAddAttributeAtIndex;
119 extern fn ZigLLVMAddAttributeAtIndex(*Value, Idx: AttributeIndex, A: *Attribute) void;
107 pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;
108 extern fn LLVMAddAttributeAtIndex(F: *Value, Idx: AttributeIndex, A: *Attribute) void;
120109
121110 pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex;
122111 extern fn LLVMRemoveEnumAttributeAtIndex(F: *Value, Idx: AttributeIndex, KindID: c_uint) void;
123112
113 pub const removeStringAttributeAtIndex = LLVMRemoveStringAttributeAtIndex;
114 extern fn LLVMRemoveStringAttributeAtIndex(F: *Value, Idx: AttributeIndex, K: [*]const u8, KLen: c_uint) void;
115
124116 pub const getFirstBasicBlock = LLVMGetFirstBasicBlock;
125117 extern fn LLVMGetFirstBasicBlock(Fn: *Value) ?*BasicBlock;
126118
127 pub const appendExistingBasicBlock = LLVMAppendExistingBasicBlock;
128 extern fn LLVMAppendExistingBasicBlock(Fn: *Value, BB: *BasicBlock) void;
129
130119 pub const addIncoming = LLVMAddIncoming;
131120 extern fn LLVMAddIncoming(
132121 PhiNode: *Value,
......@@ -135,9 +124,6 @@ pub const Value = opaque {
135124 Count: c_uint,
136125 ) void;
137126
138 pub const getNextInstruction = LLVMGetNextInstruction;
139 extern fn LLVMGetNextInstruction(Inst: *Value) ?*Value;
140
141127 pub const setGlobalConstant = LLVMSetGlobalConstant;
142128 extern fn LLVMSetGlobalConstant(GlobalVar: *Value, IsConstant: Bool) void;
143129
......@@ -156,33 +142,18 @@ pub const Value = opaque {
156142 pub const setSection = LLVMSetSection;
157143 extern fn LLVMSetSection(Global: *Value, Section: [*:0]const u8) void;
158144
159 pub const deleteGlobal = LLVMDeleteGlobal;
160 extern fn LLVMDeleteGlobal(GlobalVar: *Value) void;
145 pub const removeGlobalValue = ZigLLVMRemoveGlobalValue;
146 extern fn ZigLLVMRemoveGlobalValue(GlobalVal: *Value) void;
161147
162 pub const getNextGlobalAlias = LLVMGetNextGlobalAlias;
163 extern fn LLVMGetNextGlobalAlias(GA: *Value) *Value;
148 pub const eraseGlobalValue = ZigLLVMEraseGlobalValue;
149 extern fn ZigLLVMEraseGlobalValue(GlobalVal: *Value) void;
164150
165 pub const getAliasee = LLVMAliasGetAliasee;
166 extern fn LLVMAliasGetAliasee(Alias: *Value) *Value;
151 pub const deleteGlobalValue = ZigLLVMDeleteGlobalValue;
152 extern fn ZigLLVMDeleteGlobalValue(GlobalVal: *Value) void;
167153
168154 pub const setAliasee = LLVMAliasSetAliasee;
169155 extern fn LLVMAliasSetAliasee(Alias: *Value, Aliasee: *Value) void;
170156
171 pub const constZExtOrBitCast = LLVMConstZExtOrBitCast;
172 extern fn LLVMConstZExtOrBitCast(ConstantVal: *Value, ToType: *Type) *Value;
173
174 pub const constNeg = LLVMConstNeg;
175 extern fn LLVMConstNeg(ConstantVal: *Value) *Value;
176
177 pub const constNSWNeg = LLVMConstNSWNeg;
178 extern fn LLVMConstNSWNeg(ConstantVal: *Value) *Value;
179
180 pub const constNUWNeg = LLVMConstNUWNeg;
181 extern fn LLVMConstNUWNeg(ConstantVal: *Value) *Value;
182
183 pub const constNot = LLVMConstNot;
184 extern fn LLVMConstNot(ConstantVal: *Value) *Value;
185
186157 pub const constAdd = LLVMConstAdd;
187158 extern fn LLVMConstAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;
188159
......@@ -306,9 +277,6 @@ pub const Value = opaque {
306277 pub const setVolatile = LLVMSetVolatile;
307278 extern fn LLVMSetVolatile(MemoryAccessInst: *Value, IsVolatile: Bool) void;
308279
309 pub const setAtomicSingleThread = LLVMSetAtomicSingleThread;
310 extern fn LLVMSetAtomicSingleThread(AtomicInst: *Value, SingleThread: Bool) void;
311
312280 pub const setAlignment = LLVMSetAlignment;
313281 extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void;
314282
......@@ -327,32 +295,17 @@ pub const Value = opaque {
327295 pub const fnSetSubprogram = ZigLLVMFnSetSubprogram;
328296 extern fn ZigLLVMFnSetSubprogram(f: *Value, subprogram: *DISubprogram) void;
329297
330 pub const setValueName = LLVMSetValueName;
331 extern fn LLVMSetValueName(Val: *Value, Name: [*:0]const u8) void;
332
333 pub const setValueName2 = LLVMSetValueName2;
298 pub const setValueName = LLVMSetValueName2;
334299 extern fn LLVMSetValueName2(Val: *Value, Name: [*]const u8, NameLen: usize) void;
335300
336 pub const getValueName = LLVMGetValueName;
337 extern fn LLVMGetValueName(Val: *Value) [*:0]const u8;
338
339301 pub const takeName = ZigLLVMTakeName;
340302 extern fn ZigLLVMTakeName(new_owner: *Value, victim: *Value) void;
341303
342 pub const deleteFunction = LLVMDeleteFunction;
343 extern fn LLVMDeleteFunction(Fn: *Value) void;
344
345 pub const addSretAttr = ZigLLVMAddSretAttr;
346 extern fn ZigLLVMAddSretAttr(fn_ref: *Value, type_val: *Type) void;
347
348 pub const setCallSret = ZigLLVMSetCallSret;
349 extern fn ZigLLVMSetCallSret(Call: *Value, return_type: *Type) void;
350
351304 pub const getParam = LLVMGetParam;
352305 extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
353306
354 pub const setInitializer = LLVMSetInitializer;
355 extern fn LLVMSetInitializer(GlobalVar: *Value, ConstantVal: *Value) void;
307 pub const setInitializer = ZigLLVMSetInitializer;
308 extern fn ZigLLVMSetInitializer(GlobalVar: *Value, ConstantVal: ?*Value) void;
356309
357310 pub const setDLLStorageClass = LLVMSetDLLStorageClass;
358311 extern fn LLVMSetDLLStorageClass(Global: *Value, Class: DLLStorageClass) void;
......@@ -363,21 +316,6 @@ pub const Value = opaque {
363316 pub const replaceAllUsesWith = LLVMReplaceAllUsesWith;
364317 extern fn LLVMReplaceAllUsesWith(OldVal: *Value, NewVal: *Value) void;
365318
366 pub const getLinkage = LLVMGetLinkage;
367 extern fn LLVMGetLinkage(Global: *Value) Linkage;
368
369 pub const getUnnamedAddress = LLVMGetUnnamedAddress;
370 extern fn LLVMGetUnnamedAddress(Global: *Value) Bool;
371
372 pub const getAlignment = LLVMGetAlignment;
373 extern fn LLVMGetAlignment(V: *Value) c_uint;
374
375 pub const addFunctionAttr = ZigLLVMAddFunctionAttr;
376 extern fn ZigLLVMAddFunctionAttr(Fn: *Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void;
377
378 pub const addByValAttr = ZigLLVMAddByValAttr;
379 extern fn ZigLLVMAddByValAttr(Fn: *Value, ArgNo: c_uint, type: *Type) void;
380
381319 pub const attachMetaData = ZigLLVMAttachMetaData;
382320 extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void;
383321
......@@ -389,9 +327,6 @@ pub const Type = opaque {
389327 pub const constNull = LLVMConstNull;
390328 extern fn LLVMConstNull(Ty: *Type) *Value;
391329
392 pub const constAllOnes = LLVMConstAllOnes;
393 extern fn LLVMConstAllOnes(Ty: *Type) *Value;
394
395330 pub const constInt = LLVMConstInt;
396331 extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) *Value;
397332
......@@ -479,39 +414,18 @@ pub const Module = opaque {
479414 pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel;
480415 extern fn ZigLLVMSetModuleCodeModel(module: *Module, code_model: CodeModel) void;
481416
482 pub const addFunction = LLVMAddFunction;
483 extern fn LLVMAddFunction(*Module, Name: [*:0]const u8, FunctionTy: *Type) *Value;
484
485417 pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace;
486418 extern fn ZigLLVMAddFunctionInAddressSpace(*Module, Name: [*:0]const u8, FunctionTy: *Type, AddressSpace: c_uint) *Value;
487419
488 pub const getNamedFunction = LLVMGetNamedFunction;
489 extern fn LLVMGetNamedFunction(*Module, Name: [*:0]const u8) ?*Value;
490
491 pub const getIntrinsicDeclaration = LLVMGetIntrinsicDeclaration;
492 extern fn LLVMGetIntrinsicDeclaration(Mod: *Module, ID: c_uint, ParamTypes: ?[*]const *Type, ParamCount: usize) *Value;
493
494420 pub const printToString = LLVMPrintModuleToString;
495421 extern fn LLVMPrintModuleToString(*Module) [*:0]const u8;
496422
497 pub const addGlobal = LLVMAddGlobal;
498 extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*:0]const u8) *Value;
499
500423 pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace;
501424 extern fn LLVMAddGlobalInAddressSpace(M: *Module, Ty: *Type, Name: [*:0]const u8, AddressSpace: c_uint) *Value;
502425
503 pub const getNamedGlobal = LLVMGetNamedGlobal;
504 extern fn LLVMGetNamedGlobal(M: *Module, Name: [*:0]const u8) ?*Value;
505
506426 pub const dump = LLVMDumpModule;
507427 extern fn LLVMDumpModule(M: *Module) void;
508428
509 pub const getFirstGlobalAlias = LLVMGetFirstGlobalAlias;
510 extern fn LLVMGetFirstGlobalAlias(M: *Module) *Value;
511
512 pub const getLastGlobalAlias = LLVMGetLastGlobalAlias;
513 extern fn LLVMGetLastGlobalAlias(M: *Module) *Value;
514
515429 pub const addAlias = LLVMAddAlias2;
516430 extern fn LLVMAddAlias2(
517431 M: *Module,
......@@ -521,16 +435,6 @@ pub const Module = opaque {
521435 Name: [*:0]const u8,
522436 ) *Value;
523437
524 pub const getNamedGlobalAlias = LLVMGetNamedGlobalAlias;
525 extern fn LLVMGetNamedGlobalAlias(
526 M: *Module,
527 /// Empirically, LLVM will call strlen() on `Name` and so it
528 /// must be both null terminated and also have `NameLen` set
529 /// to the size.
530 Name: [*:0]const u8,
531 NameLen: usize,
532 ) ?*Value;
533
534438 pub const setTarget = LLVMSetTarget;
535439 extern fn LLVMSetTarget(M: *Module, Triple: [*:0]const u8) void;
536440
......@@ -553,9 +457,6 @@ pub const Module = opaque {
553457 extern fn LLVMWriteBitcodeToFile(M: *Module, Path: [*:0]const u8) c_int;
554458};
555459
556pub const lookupIntrinsicID = LLVMLookupIntrinsicID;
557extern fn LLVMLookupIntrinsicID(Name: [*]const u8, NameLen: usize) c_uint;
558
559460pub const disposeMessage = LLVMDisposeMessage;
560461extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;
561462
......@@ -616,12 +517,6 @@ pub const Builder = opaque {
616517 Instr: ?*Value,
617518 ) void;
618519
619 pub const positionBuilderAtEnd = LLVMPositionBuilderAtEnd;
620 extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
621
622 pub const getInsertBlock = LLVMGetInsertBlock;
623 extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
624
625520 pub const buildZExt = LLVMBuildZExt;
626521 extern fn LLVMBuildZExt(
627522 *Builder,
......@@ -630,14 +525,6 @@ pub const Builder = opaque {
630525 Name: [*:0]const u8,
631526 ) *Value;
632527
633 pub const buildZExtOrBitCast = LLVMBuildZExtOrBitCast;
634 extern fn LLVMBuildZExtOrBitCast(
635 *Builder,
636 Val: *Value,
637 DestTy: *Type,
638 Name: [*:0]const u8,
639 ) *Value;
640
641528 pub const buildSExt = LLVMBuildSExt;
642529 extern fn LLVMBuildSExt(
643530 *Builder,
......@@ -646,14 +533,6 @@ pub const Builder = opaque {
646533 Name: [*:0]const u8,
647534 ) *Value;
648535
649 pub const buildSExtOrBitCast = LLVMBuildSExtOrBitCast;
650 extern fn LLVMBuildSExtOrBitCast(
651 *Builder,
652 Val: *Value,
653 DestTy: *Type,
654 Name: [*:0]const u8,
655 ) *Value;
656
657536 pub const buildCall = LLVMBuildCall2;
658537 extern fn LLVMBuildCall2(
659538 *Builder,
......@@ -664,18 +543,6 @@ pub const Builder = opaque {
664543 Name: [*:0]const u8,
665544 ) *Value;
666545
667 pub const buildCallOld = ZigLLVMBuildCall;
668 extern fn ZigLLVMBuildCall(
669 *Builder,
670 *Type,
671 Fn: *Value,
672 Args: [*]const *Value,
673 NumArgs: c_uint,
674 CC: CallConv,
675 attr: CallAttr,
676 Name: [*:0]const u8,
677 ) *Value;
678
679546 pub const buildRetVoid = LLVMBuildRetVoid;
680547 extern fn LLVMBuildRetVoid(*Builder) *Value;
681548
......@@ -694,12 +561,6 @@ pub const Builder = opaque {
694561 pub const buildLoad = LLVMBuildLoad2;
695562 extern fn LLVMBuildLoad2(*Builder, Ty: *Type, PointerVal: *Value, Name: [*:0]const u8) *Value;
696563
697 pub const buildNeg = LLVMBuildNeg;
698 extern fn LLVMBuildNeg(*Builder, V: *Value, Name: [*:0]const u8) *Value;
699
700 pub const buildNot = LLVMBuildNot;
701 extern fn LLVMBuildNot(*Builder, V: *Value, Name: [*:0]const u8) *Value;
702
703564 pub const buildFAdd = LLVMBuildFAdd;
704565 extern fn LLVMBuildFAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
705566
......@@ -712,12 +573,6 @@ pub const Builder = opaque {
712573 pub const buildNUWAdd = LLVMBuildNUWAdd;
713574 extern fn LLVMBuildNUWAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
714575
715 pub const buildSAddSat = ZigLLVMBuildSAddSat;
716 extern fn ZigLLVMBuildSAddSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
717
718 pub const buildUAddSat = ZigLLVMBuildUAddSat;
719 extern fn ZigLLVMBuildUAddSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
720
721576 pub const buildFSub = LLVMBuildFSub;
722577 extern fn LLVMBuildFSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
723578
......@@ -733,12 +588,6 @@ pub const Builder = opaque {
733588 pub const buildNUWSub = LLVMBuildNUWSub;
734589 extern fn LLVMBuildNUWSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
735590
736 pub const buildSSubSat = ZigLLVMBuildSSubSat;
737 extern fn ZigLLVMBuildSSubSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
738
739 pub const buildUSubSat = ZigLLVMBuildUSubSat;
740 extern fn ZigLLVMBuildUSubSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
741
742591 pub const buildFMul = LLVMBuildFMul;
743592 extern fn LLVMBuildFMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
744593
......@@ -751,12 +600,6 @@ pub const Builder = opaque {
751600 pub const buildNUWMul = LLVMBuildNUWMul;
752601 extern fn LLVMBuildNUWMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
753602
754 pub const buildSMulFixSat = ZigLLVMBuildSMulFixSat;
755 extern fn ZigLLVMBuildSMulFixSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
756
757 pub const buildUMulFixSat = ZigLLVMBuildUMulFixSat;
758 extern fn ZigLLVMBuildUMulFixSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
759
760603 pub const buildUDiv = LLVMBuildUDiv;
761604 extern fn LLVMBuildUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
762605
......@@ -799,21 +642,12 @@ pub const Builder = opaque {
799642 pub const buildNSWShl = ZigLLVMBuildNSWShl;
800643 extern fn ZigLLVMBuildNSWShl(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
801644
802 pub const buildSShlSat = ZigLLVMBuildSShlSat;
803 extern fn ZigLLVMBuildSShlSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
804
805 pub const buildUShlSat = ZigLLVMBuildUShlSat;
806 extern fn ZigLLVMBuildUShlSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
807
808645 pub const buildOr = LLVMBuildOr;
809646 extern fn LLVMBuildOr(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
810647
811648 pub const buildXor = LLVMBuildXor;
812649 extern fn LLVMBuildXor(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
813650
814 pub const buildIntCast2 = LLVMBuildIntCast2;
815 extern fn LLVMBuildIntCast2(*Builder, Val: *Value, DestTy: *Type, IsSigned: Bool, Name: [*:0]const u8) *Value;
816
817651 pub const buildBitCast = LLVMBuildBitCast;
818652 extern fn LLVMBuildBitCast(*Builder, Val: *Value, DestTy: *Type, Name: [*:0]const u8) *Value;
819653
......@@ -999,102 +833,6 @@ pub const Builder = opaque {
999833 Name: [*:0]const u8,
1000834 ) *Value;
1001835
1002 pub const buildMemSet = ZigLLVMBuildMemSet;
1003 extern fn ZigLLVMBuildMemSet(
1004 B: *Builder,
1005 Ptr: *Value,
1006 Val: *Value,
1007 Len: *Value,
1008 Align: c_uint,
1009 is_volatile: bool,
1010 ) *Value;
1011
1012 pub const buildMemCpy = ZigLLVMBuildMemCpy;
1013 extern fn ZigLLVMBuildMemCpy(
1014 B: *Builder,
1015 Dst: *Value,
1016 DstAlign: c_uint,
1017 Src: *Value,
1018 SrcAlign: c_uint,
1019 Size: *Value,
1020 is_volatile: bool,
1021 ) *Value;
1022
1023 pub const buildMaxNum = ZigLLVMBuildMaxNum;
1024 extern fn ZigLLVMBuildMaxNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
1025
1026 pub const buildMinNum = ZigLLVMBuildMinNum;
1027 extern fn ZigLLVMBuildMinNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
1028
1029 pub const buildCeil = ZigLLVMBuildCeil;
1030 extern fn ZigLLVMBuildCeil(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1031
1032 pub const buildCos = ZigLLVMBuildCos;
1033 extern fn ZigLLVMBuildCos(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1034
1035 pub const buildExp = ZigLLVMBuildExp;
1036 extern fn ZigLLVMBuildExp(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1037
1038 pub const buildExp2 = ZigLLVMBuildExp2;
1039 extern fn ZigLLVMBuildExp2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1040
1041 pub const buildFAbs = ZigLLVMBuildFAbs;
1042 extern fn ZigLLVMBuildFAbs(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1043
1044 pub const buildFloor = ZigLLVMBuildFloor;
1045 extern fn ZigLLVMBuildFloor(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1046
1047 pub const buildLog = ZigLLVMBuildLog;
1048 extern fn ZigLLVMBuildLog(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1049
1050 pub const buildLog10 = ZigLLVMBuildLog10;
1051 extern fn ZigLLVMBuildLog10(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1052
1053 pub const buildLog2 = ZigLLVMBuildLog2;
1054 extern fn ZigLLVMBuildLog2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1055
1056 pub const buildRound = ZigLLVMBuildRound;
1057 extern fn ZigLLVMBuildRound(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1058
1059 pub const buildSin = ZigLLVMBuildSin;
1060 extern fn ZigLLVMBuildSin(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1061
1062 pub const buildSqrt = ZigLLVMBuildSqrt;
1063 extern fn ZigLLVMBuildSqrt(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1064
1065 pub const buildFTrunc = ZigLLVMBuildFTrunc;
1066 extern fn ZigLLVMBuildFTrunc(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1067
1068 pub const buildBitReverse = ZigLLVMBuildBitReverse;
1069 extern fn ZigLLVMBuildBitReverse(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1070
1071 pub const buildBSwap = ZigLLVMBuildBSwap;
1072 extern fn ZigLLVMBuildBSwap(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1073
1074 pub const buildCTPop = ZigLLVMBuildCTPop;
1075 extern fn ZigLLVMBuildCTPop(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
1076
1077 pub const buildCTLZ = ZigLLVMBuildCTLZ;
1078 extern fn ZigLLVMBuildCTLZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
1079
1080 pub const buildCTTZ = ZigLLVMBuildCTTZ;
1081 extern fn ZigLLVMBuildCTTZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
1082
1083 pub const buildFMA = ZigLLVMBuildFMA;
1084 extern fn ZigLLVMBuildFMA(builder: *Builder, a: *Value, b: *Value, c: *Value, name: [*:0]const u8) *Value;
1085
1086 pub const buildUMax = ZigLLVMBuildUMax;
1087 extern fn ZigLLVMBuildUMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
1088
1089 pub const buildUMin = ZigLLVMBuildUMin;
1090 extern fn ZigLLVMBuildUMin(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
1091
1092 pub const buildSMax = ZigLLVMBuildSMax;
1093 extern fn ZigLLVMBuildSMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
1094
1095 pub const buildSMin = ZigLLVMBuildSMin;
1096 extern fn ZigLLVMBuildSMin(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
1097
1098836 pub const buildExactUDiv = LLVMBuildExactUDiv;
1099837 extern fn LLVMBuildExactUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
1100838
......@@ -1116,39 +854,6 @@ pub const Builder = opaque {
1116854 pub const buildShuffleVector = LLVMBuildShuffleVector;
1117855 extern fn LLVMBuildShuffleVector(*Builder, V1: *Value, V2: *Value, Mask: *Value, Name: [*:0]const u8) *Value;
1118856
1119 pub const buildAndReduce = ZigLLVMBuildAndReduce;
1120 extern fn ZigLLVMBuildAndReduce(B: *Builder, Val: *Value) *Value;
1121
1122 pub const buildOrReduce = ZigLLVMBuildOrReduce;
1123 extern fn ZigLLVMBuildOrReduce(B: *Builder, Val: *Value) *Value;
1124
1125 pub const buildXorReduce = ZigLLVMBuildXorReduce;
1126 extern fn ZigLLVMBuildXorReduce(B: *Builder, Val: *Value) *Value;
1127
1128 pub const buildIntMaxReduce = ZigLLVMBuildIntMaxReduce;
1129 extern fn ZigLLVMBuildIntMaxReduce(B: *Builder, Val: *Value, is_signed: bool) *Value;
1130
1131 pub const buildIntMinReduce = ZigLLVMBuildIntMinReduce;
1132 extern fn ZigLLVMBuildIntMinReduce(B: *Builder, Val: *Value, is_signed: bool) *Value;
1133
1134 pub const buildFPMaxReduce = ZigLLVMBuildFPMaxReduce;
1135 extern fn ZigLLVMBuildFPMaxReduce(B: *Builder, Val: *Value) *Value;
1136
1137 pub const buildFPMinReduce = ZigLLVMBuildFPMinReduce;
1138 extern fn ZigLLVMBuildFPMinReduce(B: *Builder, Val: *Value) *Value;
1139
1140 pub const buildAddReduce = ZigLLVMBuildAddReduce;
1141 extern fn ZigLLVMBuildAddReduce(B: *Builder, Val: *Value) *Value;
1142
1143 pub const buildMulReduce = ZigLLVMBuildMulReduce;
1144 extern fn ZigLLVMBuildMulReduce(B: *Builder, Val: *Value) *Value;
1145
1146 pub const buildFPAddReduce = ZigLLVMBuildFPAddReduce;
1147 extern fn ZigLLVMBuildFPAddReduce(B: *Builder, Acc: *Value, Val: *Value) *Value;
1148
1149 pub const buildFPMulReduce = ZigLLVMBuildFPMulReduce;
1150 extern fn ZigLLVMBuildFPMulReduce(B: *Builder, Acc: *Value, Val: *Value) *Value;
1151
1152857 pub const setFastMath = ZigLLVMSetFastMath;
1153858 extern fn ZigLLVMSetFastMath(B: *Builder, on_state: bool) void;
1154859
......@@ -1563,9 +1268,6 @@ extern fn ZigLLVMWriteImportLibrary(
15631268 kill_at: bool,
15641269) bool;
15651270
1566pub const setCallElemTypeAttr = ZigLLVMSetCallElemTypeAttr;
1567extern fn ZigLLVMSetCallElemTypeAttr(Call: *Value, arg_index: usize, return_type: *Type) void;
1568
15691271pub const Linkage = enum(c_uint) {
15701272 External,
15711273 AvailableExternally,
......@@ -1784,9 +1486,6 @@ pub const DIGlobalVariable = opaque {
17841486pub const DIGlobalVariableExpression = opaque {
17851487 pub const getVariable = ZigLLVMGlobalGetVariable;
17861488 extern fn ZigLLVMGlobalGetVariable(global_variable: *DIGlobalVariableExpression) *DIGlobalVariable;
1787
1788 pub const getExpression = ZigLLVMGlobalGetExpression;
1789 extern fn ZigLLVMGlobalGetExpression(global_variable: *DIGlobalVariableExpression) *DIGlobalExpression;
17901489};
17911490pub const DIType = opaque {
17921491 pub const toScope = ZigLLVMTypeToScope;
src/value.zig+2-2
......@@ -3831,7 +3831,7 @@ pub const Value = struct {
38313831
38323832 /// If the value is represented in-memory as a series of bytes that all
38333833 /// have the same value, return that byte value, otherwise null.
3834 pub fn hasRepeatedByteRepr(val: Value, ty: Type, mod: *Module) !?Value {
3834 pub fn hasRepeatedByteRepr(val: Value, ty: Type, mod: *Module) !?u8 {
38353835 const abi_size = std.math.cast(usize, ty.abiSize(mod)) orelse return null;
38363836 assert(abi_size >= 1);
38373837 const byte_buffer = try mod.gpa.alloc(u8, abi_size);
......@@ -3852,7 +3852,7 @@ pub const Value = struct {
38523852 for (byte_buffer[1..]) |byte| {
38533853 if (byte != first_byte) return null;
38543854 }
3855 return try mod.intValue(Type.u8, first_byte);
3855 return first_byte;
38563856 }
38573857
38583858 pub fn isGenericPoison(val: Value) bool {
src/zig_llvm.cpp+34-436
......@@ -78,30 +78,6 @@
7878
7979using namespace llvm;
8080
81void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) {
82 initializeLoopStrengthReducePass(*unwrap(R));
83}
84
85void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R) {
86 initializeLowerIntrinsicsPass(*unwrap(R));
87}
88
89char *ZigLLVMGetHostCPUName(void) {
90 return strdup((const char *)sys::getHostCPUName().bytes_begin());
91}
92
93char *ZigLLVMGetNativeFeatures(void) {
94 SubtargetFeatures features;
95
96 StringMap<bool> host_features;
97 if (sys::getHostCPUFeatures(host_features)) {
98 for (auto &F : host_features)
99 features.AddFeature(F.first(), F.second);
100 }
101
102 return strdup((const char *)StringRef(features.getString()).bytes_begin());
103}
104
10581#ifndef NDEBUG
10682static const bool assertions_on = true;
10783#else
......@@ -179,14 +155,6 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri
179155 return reinterpret_cast<LLVMTargetMachineRef>(TM);
180156}
181157
182unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD) {
183 return unwrap(TD)->getStackAlignment().value();
184}
185
186unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) {
187 return unwrap(TD)->getProgramAddressSpace();
188}
189
190158namespace {
191159// LLVM's time profiler can provide a hierarchy view of the time spent
192160// in each component. It generates JSON report in Chrome's "Trace Event"
......@@ -410,12 +378,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
410378 return false;
411379}
412380
413ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {
414 return wrap(Type::getTokenTy(*unwrap(context_ref)));
415}
416
417
418ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {
381void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {
419382 static OptBisect opt_bisect;
420383 opt_bisect.setLimit(limit);
421384 unwrap(context_ref)->setOptPassGate(opt_bisect);
......@@ -426,241 +389,23 @@ LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
426389 return wrap(func);
427390}
428391
429LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
430 LLVMValueRef *Args, unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr,
431 const char *Name)
432{
433 FunctionType *FTy = unwrap<FunctionType>(Ty);
434 CallInst *call_inst = unwrap(B)->CreateCall(FTy, unwrap(Fn),
435 ArrayRef(unwrap(Args), NumArgs), Name);
436 call_inst->setCallingConv(static_cast<CallingConv::ID>(CC));
437 switch (attr) {
438 case ZigLLVM_CallAttrAuto:
392void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind) {
393 CallInst::TailCallKind TCK;
394 switch (TailCallKind) {
395 case ZigLLVMTailCallKindNone:
396 TCK = CallInst::TCK_None;
439397 break;
440 case ZigLLVM_CallAttrNeverTail:
441 call_inst->setTailCallKind(CallInst::TCK_NoTail);
398 case ZigLLVMTailCallKindTail:
399 TCK = CallInst::TCK_Tail;
442400 break;
443 case ZigLLVM_CallAttrNeverInline:
444 call_inst->addFnAttr(Attribute::NoInline);
401 case ZigLLVMTailCallKindMustTail:
402 TCK = CallInst::TCK_MustTail;
445403 break;
446 case ZigLLVM_CallAttrAlwaysTail:
447 call_inst->setTailCallKind(CallInst::TCK_MustTail);
404 case ZigLLVMTailCallKindNoTail:
405 TCK = CallInst::TCK_NoTail;
448406 break;
449 case ZigLLVM_CallAttrAlwaysInline:
450 call_inst->addFnAttr(Attribute::AlwaysInline);
451 break;
452 }
453 return wrap(call_inst);
454}
455
456ZIG_EXTERN_C void ZigLLVMSetTailCallKind(LLVMValueRef Call, CallInst::TailCallKind TailCallKind) {
457 unwrap<CallInst>(Call)->setTailCallKind(TailCallKind);
458}
459
460void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A) {
461 if (isa<Function>(unwrap(Val))) {
462 unwrap<Function>(Val)->addAttributeAtIndex(Idx, unwrap(A));
463 } else {
464 unwrap<CallInst>(Val)->addAttributeAtIndex(Idx, unwrap(A));
465407 }
466}
467
468LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
469 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile)
470{
471 CallInst *call_inst = unwrap(B)->CreateMemCpy(unwrap(Dst),
472 MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), isVolatile);
473 return wrap(call_inst);
474}
475
476LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size,
477 unsigned Align, bool isVolatile)
478{
479 CallInst *call_inst = unwrap(B)->CreateMemSet(unwrap(Ptr), unwrap(Val), unwrap(Size),
480 MaybeAlign(Align), isVolatile);
481 return wrap(call_inst);
482}
483
484LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
485 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ceil, unwrap(V), nullptr, name);
486 return wrap(call_inst);
487}
488
489LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
490 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::cos, unwrap(V), nullptr, name);
491 return wrap(call_inst);
492}
493
494LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
495 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp, unwrap(V), nullptr, name);
496 return wrap(call_inst);
497}
498
499LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
500 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp2, unwrap(V), nullptr, name);
501 return wrap(call_inst);
502}
503
504LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
505 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::fabs, unwrap(V), nullptr, name);
506 return wrap(call_inst);
507}
508
509LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
510 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::floor, unwrap(V), nullptr, name);
511 return wrap(call_inst);
512}
513
514LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
515 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log, unwrap(V), nullptr, name);
516 return wrap(call_inst);
517}
518
519LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
520 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log10, unwrap(V), nullptr, name);
521 return wrap(call_inst);
522}
523
524LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
525 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log2, unwrap(V), nullptr, name);
526 return wrap(call_inst);
527}
528
529LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
530 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::round, unwrap(V), nullptr, name);
531 return wrap(call_inst);
532}
533
534LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
535 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sin, unwrap(V), nullptr, name);
536 return wrap(call_inst);
537}
538
539LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
540 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sqrt, unwrap(V), nullptr, name);
541 return wrap(call_inst);
542}
543
544LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
545 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::trunc, unwrap(V), nullptr, name);
546 return wrap(call_inst);
547}
548
549LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
550 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bitreverse, unwrap(V), nullptr, name);
551 return wrap(call_inst);
552}
553
554LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
555 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bswap, unwrap(V), nullptr, name);
556 return wrap(call_inst);
557}
558
559LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
560 CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ctpop, unwrap(V), nullptr, name);
561 return wrap(call_inst);
562}
563
564LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
565 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ctlz, unwrap(LHS), unwrap(RHS), nullptr, name);
566 return wrap(call_inst);
567}
568
569LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
570 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::cttz, unwrap(LHS), unwrap(RHS), nullptr, name);
571 return wrap(call_inst);
572}
573
574LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char *name) {
575 llvm::Type* types[1] = {
576 unwrap(A)->getType(),
577 };
578 llvm::Value* values[3] = {unwrap(A), unwrap(B), unwrap(C)};
579
580 CallInst *call_inst = unwrap(builder)->CreateIntrinsic(Intrinsic::fma, types, values, nullptr, name);
581 return wrap(call_inst);
582}
583
584LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
585 CallInst *call_inst = unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS), name);
586 return wrap(call_inst);
587}
588
589LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
590 CallInst *call_inst = unwrap(B)->CreateMinNum(unwrap(LHS), unwrap(RHS), name);
591 return wrap(call_inst);
592}
593
594LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
595 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umax, unwrap(LHS), unwrap(RHS), nullptr, name);
596 return wrap(call_inst);
597}
598
599LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
600 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umin, unwrap(LHS), unwrap(RHS), nullptr, name);
601 return wrap(call_inst);
602}
603
604LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
605 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smax, unwrap(LHS), unwrap(RHS), nullptr, name);
606 return wrap(call_inst);
607}
608
609LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
610 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smin, unwrap(LHS), unwrap(RHS), nullptr, name);
611 return wrap(call_inst);
612}
613
614LLVMValueRef ZigLLVMBuildSAddSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
615 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::sadd_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
616 return wrap(call_inst);
617}
618
619LLVMValueRef ZigLLVMBuildUAddSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
620 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::uadd_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
621 return wrap(call_inst);
622}
623
624LLVMValueRef ZigLLVMBuildSSubSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
625 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ssub_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
626 return wrap(call_inst);
627}
628
629LLVMValueRef ZigLLVMBuildUSubSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
630 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::usub_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
631 return wrap(call_inst);
632}
633
634LLVMValueRef ZigLLVMBuildSMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
635 llvm::Type* types[1] = {
636 unwrap(LHS)->getType(),
637 };
638 // pass scale = 0 as third argument
639 llvm::Value* values[3] = {unwrap(LHS), unwrap(RHS), unwrap(B)->getInt32(0)};
640
641 CallInst *call_inst = unwrap(B)->CreateIntrinsic(Intrinsic::smul_fix_sat, types, values, nullptr, name);
642 return wrap(call_inst);
643}
644
645LLVMValueRef ZigLLVMBuildUMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
646 llvm::Type* types[1] = {
647 unwrap(LHS)->getType(),
648 };
649 // pass scale = 0 as third argument
650 llvm::Value* values[3] = {unwrap(LHS), unwrap(RHS), unwrap(B)->getInt32(0)};
651
652 CallInst *call_inst = unwrap(B)->CreateIntrinsic(Intrinsic::umul_fix_sat, types, values, nullptr, name);
653 return wrap(call_inst);
654}
655
656LLVMValueRef ZigLLVMBuildSShlSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
657 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::sshl_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
658 return wrap(call_inst);
659}
660
661LLVMValueRef ZigLLVMBuildUShlSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
662 CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ushl_sat, unwrap(LHS), unwrap(RHS), nullptr, name);
663 return wrap(call_inst);
408 unwrap<CallInst>(Call)->setTailCallKind(TCK);
664409}
665410
666411void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram) {
......@@ -1181,82 +926,10 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {
1181926 }
1182927}
1183928
1184void ZigLLVMAddByValAttr(LLVMValueRef Val, unsigned ArgNo, LLVMTypeRef type_val) {
1185 if (isa<Function>(unwrap(Val))) {
1186 Function *func = unwrap<Function>(Val);
1187 AttrBuilder attr_builder(func->getContext());
1188 Type *llvm_type = unwrap<Type>(type_val);
1189 attr_builder.addByValAttr(llvm_type);
1190 func->addParamAttrs(ArgNo, attr_builder);
1191 } else {
1192 CallInst *call = unwrap<CallInst>(Val);
1193 AttrBuilder attr_builder(call->getContext());
1194 Type *llvm_type = unwrap<Type>(type_val);
1195 attr_builder.addByValAttr(llvm_type);
1196 // NOTE: +1 here since index 0 refers to the return value
1197 call->addAttributeAtIndex(ArgNo + 1, attr_builder.getAttribute(Attribute::ByVal));
1198 }
1199}
1200
1201void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) {
1202 Function *func = unwrap<Function>(fn_ref);
1203 AttrBuilder attr_builder(func->getContext());
1204 Type *llvm_type = unwrap<Type>(type_val);
1205 attr_builder.addStructRetAttr(llvm_type);
1206 func->addParamAttrs(0, attr_builder);
1207}
1208
1209void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty) {
1210 Function *func = unwrap<Function>(fn_ref);
1211 AttrBuilder attr_builder(func->getContext());
1212 Type *llvm_type = unwrap<Type>(elem_ty);
1213 attr_builder.addTypeAttr(Attribute::ElementType, llvm_type);
1214 func->addParamAttrs(arg_index, attr_builder);
1215}
1216
1217void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) {
1218 Function *func = unwrap<Function>(fn_ref);
1219 func->addFnAttr(attr_name, attr_value);
1220}
1221
1222929void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
1223930 cl::ParseCommandLineOptions(argc, argv);
1224931}
1225932
1226const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) {
1227 return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin();
1228}
1229
1230const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor) {
1231 return (const char*)Triple::getVendorTypeName((Triple::VendorType)vendor).bytes_begin();
1232}
1233
1234const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os) {
1235 const char* name = (const char*)Triple::getOSTypeName((Triple::OSType)os).bytes_begin();
1236 if (strcmp(name, "macosx") == 0) return "macos";
1237 return name;
1238}
1239
1240const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type) {
1241 return (const char*)Triple::getEnvironmentTypeName((Triple::EnvironmentType)env_type).bytes_begin();
1242}
1243
1244void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type,
1245 ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type,
1246 ZigLLVM_ObjectFormatType *oformat)
1247{
1248 char *native_triple = LLVMGetDefaultTargetTriple();
1249 Triple triple(Triple::normalize(native_triple));
1250
1251 *arch_type = (ZigLLVM_ArchType)triple.getArch();
1252 *vendor_type = (ZigLLVM_VendorType)triple.getVendor();
1253 *os_type = (ZigLLVM_OSType)triple.getOS();
1254 *environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment();
1255 *oformat = (ZigLLVM_ObjectFormatType)triple.getObjectFormat();
1256
1257 free(native_triple);
1258}
1259
1260933void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64) {
1261934 unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);
1262935 unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4);
......@@ -1314,50 +987,6 @@ LLVMValueRef ZigLLVMBuildAllocaInAddressSpace(LLVMBuilderRef builder, LLVMTypeRe
1314987 return wrap(unwrap(builder)->CreateAlloca(unwrap(Ty), AddressSpace, nullptr, Name));
1315988}
1316989
1317void ZigLLVMSetTailCall(LLVMValueRef Call) {
1318 unwrap<CallInst>(Call)->setTailCallKind(CallInst::TCK_MustTail);
1319}
1320
1321void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type) {
1322 CallInst *call_inst = unwrap<CallInst>(Call);
1323 Type *llvm_type = unwrap<Type>(return_type);
1324 call_inst->addParamAttr(AttributeList::ReturnIndex,
1325 Attribute::getWithStructRetType(call_inst->getContext(), llvm_type));
1326}
1327
1328void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type) {
1329 CallInst *call_inst = unwrap<CallInst>(Call);
1330 Type *llvm_type = unwrap<Type>(return_type);
1331 call_inst->addParamAttr(arg_index,
1332 Attribute::get(call_inst->getContext(), Attribute::ElementType, llvm_type));
1333}
1334
1335void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) {
1336 unwrap<Function>(function)->setPrefixData(unwrap<Constant>(data));
1337}
1338
1339void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, ZigLLVM_CallingConv cc) {
1340 unwrap<Function>(function)->setCallingConv(static_cast<CallingConv::ID>(cc));
1341}
1342
1343class MyOStream: public raw_ostream {
1344 public:
1345 MyOStream(void (*_append_diagnostic)(void *, const char *, size_t), void *_context) :
1346 raw_ostream(true), append_diagnostic(_append_diagnostic), context(_context), pos(0) {
1347
1348 }
1349 void write_impl(const char *ptr, size_t len) override {
1350 append_diagnostic(context, ptr, len);
1351 pos += len;
1352 }
1353 uint64_t current_pos() const override {
1354 return pos;
1355 }
1356 void (*append_diagnostic)(void *, const char *, size_t);
1357 void *context;
1358 size_t pos;
1359};
1360
1361990bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch,
1362991 const char *output_lib_path, bool kill_at)
1363992{
......@@ -1489,72 +1118,41 @@ bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disab
14891118 return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
14901119}
14911120
1492inline LLVMAttributeRef wrap(Attribute Attr) {
1493 return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer());
1494}
1495
1496inline Attribute unwrap(LLVMAttributeRef Attr) {
1497 return Attribute::fromRawPointer(Attr);
1498}
1499
1500LLVMValueRef ZigLLVMBuildAndReduce(LLVMBuilderRef B, LLVMValueRef Val) {
1501 return wrap(unwrap(B)->CreateAndReduce(unwrap(Val)));
1502}
1503
1504LLVMValueRef ZigLLVMBuildOrReduce(LLVMBuilderRef B, LLVMValueRef Val) {
1505 return wrap(unwrap(B)->CreateOrReduce(unwrap(Val)));
1506}
1507
1508LLVMValueRef ZigLLVMBuildXorReduce(LLVMBuilderRef B, LLVMValueRef Val) {
1509 return wrap(unwrap(B)->CreateXorReduce(unwrap(Val)));
1510}
1511
1512LLVMValueRef ZigLLVMBuildIntMaxReduce(LLVMBuilderRef B, LLVMValueRef Val, bool is_signed) {
1513 return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Val), is_signed));
1514}
1515
1516LLVMValueRef ZigLLVMBuildIntMinReduce(LLVMBuilderRef B, LLVMValueRef Val, bool is_signed) {
1517 return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Val), is_signed));
1518}
1519
1520LLVMValueRef ZigLLVMBuildFPMaxReduce(LLVMBuilderRef B, LLVMValueRef Val) {
1521 return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Val)));
1522}
1523
1524LLVMValueRef ZigLLVMBuildFPMinReduce(LLVMBuilderRef B, LLVMValueRef Val) {
1525 return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Val)));
1526}
1527
1528LLVMValueRef ZigLLVMBuildAddReduce(LLVMBuilderRef B, LLVMValueRef Val) {
1529 return wrap(unwrap(B)->CreateAddReduce(unwrap(Val)));
1121void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) {
1122 unwrap(new_owner)->takeName(unwrap(victim));
15301123}
15311124
1532LLVMValueRef ZigLLVMBuildMulReduce(LLVMBuilderRef B, LLVMValueRef Val) {
1533 return wrap(unwrap(B)->CreateMulReduce(unwrap(Val)));
1125void ZigLLVMRemoveGlobalValue(LLVMValueRef GlobalVal) {
1126 unwrap<GlobalValue>(GlobalVal)->removeFromParent();
15341127}
15351128
1536LLVMValueRef ZigLLVMBuildFPAddReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val) {
1537 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc), unwrap(Val)));
1129void ZigLLVMEraseGlobalValue(LLVMValueRef GlobalVal) {
1130 unwrap<GlobalValue>(GlobalVal)->eraseFromParent();
15381131}
15391132
1540LLVMValueRef ZigLLVMBuildFPMulReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val) {
1541 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc), unwrap(Val)));
1133void ZigLLVMDeleteGlobalValue(LLVMValueRef GlobalVal) {
1134 auto *GV = unwrap<GlobalValue>(GlobalVal);
1135 assert(GV->getParent() == nullptr);
1136 switch (GV->getValueID()) {
1137#define HANDLE_GLOBAL_VALUE(NAME) \
1138 case Value::NAME##Val: \
1139 delete static_cast<NAME *>(GV); \
1140 break;
1141#include <llvm/IR/Value.def>
1142 default: llvm_unreachable("Expected global value");
1143 }
15421144}
15431145
1544void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) {
1545 unwrap(new_owner)->takeName(unwrap(victim));
1146void ZigLLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal) {
1147 unwrap<GlobalVariable>(GlobalVar)->setInitializer(ConstantVal ? unwrap<Constant>(ConstantVal) : nullptr);
15461148}
15471149
15481150ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
1549 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
1550}
1551
1552ZigLLVMDIGlobalExpression* ZigLLVMGlobalGetExpression(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
1553 return reinterpret_cast<ZigLLVMDIGlobalExpression*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getExpression());
1151 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
15541152}
15551153
15561154void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
1557 unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression));
1155 unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression));
15581156}
15591157
15601158static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");
src/zig_llvm.h+13-105
......@@ -43,13 +43,6 @@ struct ZigLLVMInsertionPoint;
4343struct ZigLLVMDINode;
4444struct ZigLLVMMDString;
4545
46ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
47ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
48
49/// Caller must free memory with LLVMDisposeMessage
50ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void);
51ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void);
52
5346ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
5447 char **error_message, bool is_debug,
5548 bool is_small, bool time_report, bool tsan, bool lto,
......@@ -67,13 +60,20 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co
6760 const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
6861 LLVMCodeModel CodeModel, bool function_sections, enum ZigLLVMABIType float_abi, const char *abi_name);
6962
70ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
71
7263ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit);
7364
7465ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
7566 LLVMTypeRef FunctionTy, unsigned AddressSpace);
7667
68enum ZigLLVMTailCallKind {
69 ZigLLVMTailCallKindNone,
70 ZigLLVMTailCallKindTail,
71 ZigLLVMTailCallKindMustTail,
72 ZigLLVMTailCallKindNoTail,
73};
74
75ZIG_EXTERN_C void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind);
76
7777enum ZigLLVM_CallingConv {
7878 ZigLLVM_C = 0,
7979 ZigLLVM_Fast = 8,
......@@ -122,66 +122,6 @@ enum ZigLLVM_CallingConv {
122122 ZigLLVM_MaxID = 1023,
123123};
124124
125enum ZigLLVM_CallAttr {
126 ZigLLVM_CallAttrAuto,
127 ZigLLVM_CallAttrNeverTail,
128 ZigLLVM_CallAttrNeverInline,
129 ZigLLVM_CallAttrAlwaysTail,
130 ZigLLVM_CallAttrAlwaysInline,
131};
132ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef function_type,
133 LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, enum ZigLLVM_CallingConv CC,
134 enum ZigLLVM_CallAttr attr, const char *Name);
135
136ZIG_EXTERN_C void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A);
137
138ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
139 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);
140
141ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size,
142 unsigned Align, bool isVolatile);
143
144ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
145ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
146ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
147ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
148ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
149ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
150ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
151ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
152ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
153ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
154ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
155ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
156ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
157
158ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
159ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
160ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
161
162ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
163ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
164
165ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char* name);
166
167ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
168ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
169
170ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
171ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
172ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
173ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
174ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUAddSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
175ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSAddSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
176ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUSubSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
177ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSSubSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
178ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name);
179ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name);
180ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUShlSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
181ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSShlSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
182ZIG_EXTERN_C LLVMValueRef LLVMBuildVectorSplat(LLVMBuilderRef B, unsigned elem_count, LLVMValueRef V, const char *Name);
183
184
185125ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
186126 const char *name);
187127ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
......@@ -345,22 +285,10 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBu
345285 struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref);
346286
347287ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
348ZIG_EXTERN_C void ZigLLVMSetTailCall(LLVMValueRef Call);
349ZIG_EXTERN_C void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type);
350ZIG_EXTERN_C void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type);
351ZIG_EXTERN_C void ZigLLVMFunctionSetPrefixData(LLVMValueRef fn, LLVMValueRef data);
352ZIG_EXTERN_C void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, enum ZigLLVM_CallingConv cc);
353
354ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
355ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val);
356ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val);
357ZIG_EXTERN_C void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty);
358ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn);
359288
360289ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);
361290
362291ZIG_EXTERN_C ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression);
363ZIG_EXTERN_C ZigLLVMDIGlobalExpression* ZigLLVMGlobalGetExpression(ZigLLVMDIGlobalVariableExpression *global_variable_expression);
364292ZIG_EXTERN_C void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression);
365293
366294
......@@ -563,19 +491,11 @@ enum ZigLLVM_ObjectFormatType {
563491 ZigLLVM_XCOFF,
564492};
565493
566ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildAndReduce(LLVMBuilderRef B, LLVMValueRef Val);
567ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildOrReduce(LLVMBuilderRef B, LLVMValueRef Val);
568ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildXorReduce(LLVMBuilderRef B, LLVMValueRef Val);
569ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildIntMaxReduce(LLVMBuilderRef B, LLVMValueRef Val, bool is_signed);
570ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildIntMinReduce(LLVMBuilderRef B, LLVMValueRef Val, bool is_signed);
571ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFPMaxReduce(LLVMBuilderRef B, LLVMValueRef Val);
572ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFPMinReduce(LLVMBuilderRef B, LLVMValueRef Val);
573ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildAddReduce(LLVMBuilderRef B, LLVMValueRef Val);
574ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMulReduce(LLVMBuilderRef B, LLVMValueRef Val);
575ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFPAddReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val);
576ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFPMulReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val);
577
578494ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim);
495ZIG_EXTERN_C void ZigLLVMRemoveGlobalValue(LLVMValueRef GlobalVal);
496ZIG_EXTERN_C void ZigLLVMEraseGlobalValue(LLVMValueRef GlobalVal);
497ZIG_EXTERN_C void ZigLLVMDeleteGlobalValue(LLVMValueRef GlobalVal);
498ZIG_EXTERN_C void ZigLLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal);
579499
580500#define ZigLLVM_DIFlags_Zero 0U
581501#define ZigLLVM_DIFlags_Private 1U
......@@ -610,11 +530,6 @@ ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim);
610530#define ZigLLVM_DIFlags_LittleEndian (1U << 28)
611531#define ZigLLVM_DIFlags_AllCallsDescribed (1U << 29)
612532
613ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch);
614ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor);
615ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os);
616ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType abi);
617
618533ZIG_EXTERN_C bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early, bool disable_output);
619534ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output);
620535ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output);
......@@ -625,11 +540,4 @@ ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **fil
625540ZIG_EXTERN_C bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch,
626541 const char *output_lib_path, bool kill_at);
627542
628ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type,
629 enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type,
630 enum ZigLLVM_ObjectFormatType *oformat);
631
632ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD);
633ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD);
634
635543#endif