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 {...@@ -764,7 +764,6 @@ pub const Object = struct {
764 builder: Builder,764 builder: Builder,
765765
766 module: *Module,766 module: *Module,
767 llvm_module: *llvm.Module,
768 di_builder: ?*llvm.DIBuilder,767 di_builder: ?*llvm.DIBuilder,
769 /// One of these mappings:768 /// One of these mappings:
770 /// - *Module.File => *DIFile769 /// - *Module.File => *DIFile
...@@ -824,7 +823,7 @@ pub const Object = struct {...@@ -824,7 +823,7 @@ pub const Object = struct {
824 var builder = try Builder.init(.{823 var builder = try Builder.init(.{
825 .allocator = gpa,824 .allocator = gpa,
826 .use_lib_llvm = options.use_lib_llvm,825 .use_lib_llvm = options.use_lib_llvm,
827 .strip = options.strip,826 .strip = options.strip or !options.use_lib_llvm, // TODO
828 .name = options.root_name,827 .name = options.root_name,
829 .target = options.target,828 .target = options.target,
830 .triple = llvm_target_triple,829 .triple = llvm_target_triple,
...@@ -945,9 +944,8 @@ pub const Object = struct {...@@ -945,9 +944,8 @@ pub const Object = struct {
945 .gpa = gpa,944 .gpa = gpa,
946 .builder = builder,945 .builder = builder,
947 .module = options.module.?,946 .module = options.module.?,
948 .llvm_module = builder.llvm.module.?,
949 .di_map = .{},947 .di_map = .{},
950 .di_builder = builder.llvm.di_builder,948 .di_builder = if (builder.useLibLlvm()) builder.llvm.di_builder else null, // TODO
951 .di_compile_unit = builder.llvm.di_compile_unit,949 .di_compile_unit = builder.llvm.di_compile_unit,
952 .target_machine = target_machine,950 .target_machine = target_machine,
953 .target_data = target_data,951 .target_data = target_data,
...@@ -963,14 +961,17 @@ pub const Object = struct {...@@ -963,14 +961,17 @@ pub const Object = struct {
963 }961 }
964962
965 pub fn deinit(self: *Object, gpa: Allocator) void {963 pub fn deinit(self: *Object, gpa: Allocator) void {
966 self.di_map.deinit(gpa);964 if (self.builder.useLibLlvm()) {
967 self.di_type_map.deinit(gpa);965 self.di_map.deinit(gpa);
968 self.target_data.dispose();966 self.di_type_map.deinit(gpa);
969 self.target_machine.dispose();967 self.target_data.dispose();
968 self.target_machine.dispose();
969 }
970 self.decl_map.deinit(gpa);970 self.decl_map.deinit(gpa);
971 self.named_enum_map.deinit(gpa);971 self.named_enum_map.deinit(gpa);
972 self.type_map.deinit(gpa);972 self.type_map.deinit(gpa);
973 self.extern_collisions.deinit(gpa);973 self.extern_collisions.deinit(gpa);
974 self.builder.deinit();
974 self.* = undefined;975 self.* = undefined;
975 }976 }
976977
...@@ -991,9 +992,8 @@ pub const Object = struct {...@@ -991,9 +992,8 @@ pub const Object = struct {
991 }992 }
992993
993 fn genErrorNameTable(o: *Object) Allocator.Error!void {994 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 // If o.error_name_table is null, then it was not referenced by any instructions.
995 const error_name_table_ptr_global = o.error_name_table;996 if (o.error_name_table == .none) return;
996 if (error_name_table_ptr_global == .none) return;
997997
998 const mod = o.module;998 const mod = o.module;
999999
...@@ -1003,72 +1003,42 @@ pub const Object = struct {...@@ -1003,72 +1003,42 @@ pub const Object = struct {
10031003
1004 // TODO: Address space1004 // TODO: Address space
1005 const slice_ty = Type.slice_const_u8_sentinel_0;1005 const slice_ty = Type.slice_const_u8_sentinel_0;
1006 const slice_alignment = slice_ty.abiAlignment(mod);
1007 const llvm_usize_ty = try o.lowerType(Type.usize);1006 const llvm_usize_ty = try o.lowerType(Type.usize);
1008 const llvm_slice_ty = try o.lowerType(slice_ty);1007 const llvm_slice_ty = try o.lowerType(slice_ty);
1009 const llvm_table_ty = try o.builder.arrayType(error_name_list.len, llvm_slice_ty);1008 const llvm_table_ty = try o.builder.arrayType(error_name_list.len, llvm_slice_ty);
10101009
1011 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);1010 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
1012 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name_nts| {1011 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {
1013 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_nts));1012 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
1014 const str_init = try o.builder.stringNullConst(name);1013 const name_init = try o.builder.stringNullConst(name_string);
1015 const str_ty = str_init.typeOf(&o.builder);1014 const name_variable_index =
1016 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");1015 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
1017 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));1016 try name_variable_index.setInitializer(name_init, &o.builder);
1018 str_llvm_global.setLinkage(.Private);1017 name_variable_index.setLinkage(.private, &o.builder);
1019 str_llvm_global.setGlobalConstant(.True);1018 name_variable_index.setMutability(.constant, &o.builder);
1020 str_llvm_global.setUnnamedAddr(.True);1019 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
1021 str_llvm_global.setAlignment(1);1020 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
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);
10381021
1039 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{1022 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
1040 global_index.toConst(),1023 name_variable_index.toConst(&o.builder),
1041 try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len),1024 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len),
1042 });1025 });
1043 }1026 }
10441027
1045 const error_name_table_init = try o.builder.arrayConst(llvm_table_ty, llvm_errors);1028 const table_variable_index = try o.builder.addVariable(.empty, llvm_table_ty, .default);
1046 const error_name_table_global = o.llvm_module.addGlobal(llvm_table_ty.toLlvm(&o.builder), "");1029 try table_variable_index.setInitializer(
1047 error_name_table_global.setInitializer(error_name_table_init.toLlvm(&o.builder));1030 try o.builder.arrayConst(llvm_table_ty, llvm_errors),
1048 error_name_table_global.setLinkage(.Private);1031 &o.builder,
1049 error_name_table_global.setGlobalConstant(.True);1032 );
1050 error_name_table_global.setUnnamedAddr(.True);1033 table_variable_index.setLinkage(.private, &o.builder);
1051 error_name_table_global.setAlignment(slice_alignment); // TODO: Dont hardcode1034 table_variable_index.setMutability(.constant, &o.builder);
10521035 table_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
1053 var global = Builder.Global{1036 table_variable_index.setAlignment(
1054 .linkage = .private,1037 Builder.Alignment.fromByteUnits(slice_ty.abiAlignment(mod)),
1055 .unnamed_addr = .unnamed_addr,1038 &o.builder,
1056 .type = llvm_table_ty,1039 );
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);
10681040
1069 const error_name_table_ptr = error_name_table_global;1041 try o.error_name_table.setInitializer(table_variable_index.toConst(&o.builder), &o.builder);
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);
1072 }1042 }
10731043
1074 fn genCmpLtErrorsLenFunction(o: *Object) !void {1044 fn genCmpLtErrorsLenFunction(o: *Object) !void {
...@@ -1112,7 +1082,8 @@ pub const Object = struct {...@@ -1112,7 +1082,8 @@ pub const Object = struct {
1112 // Same logic as below but for externs instead of exports.1082 // Same logic as below but for externs instead of exports.
1113 const decl_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue;1083 const decl_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue;
1114 const other_global = object.builder.getGlobal(decl_name) orelse continue;1084 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
1117 try global.replace(other_global, &object.builder);1088 try global.replace(other_global, &object.builder);
1118 }1089 }
...@@ -1120,13 +1091,14 @@ pub const Object = struct {...@@ -1120,13 +1091,14 @@ pub const Object = struct {
11201091
1121 for (mod.decl_exports.keys(), mod.decl_exports.values()) |decl_index, export_list| {1092 for (mod.decl_exports.keys(), mod.decl_exports.values()) |decl_index, export_list| {
1122 const global = object.decl_map.get(decl_index) orelse continue;1093 const global = object.decl_map.get(decl_index) orelse continue;
1094 const global_base = global.toConst().getBase(&object.builder);
1123 for (export_list.items) |exp| {1095 for (export_list.items) |exp| {
1124 // Detect if the LLVM global has already been created as an extern. In such1096 // Detect if the LLVM global has already been created as an extern. In such
1125 // case, we need to replace all uses of it with this exported global.1097 // case, we need to replace all uses of it with this exported global.
1126 const exp_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue;1098 const exp_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue;
11271099
1128 const other_global = object.builder.getGlobal(exp_name) orelse continue;1100 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
1131 try global.takeName(other_global, &object.builder);1103 try global.takeName(other_global, &object.builder);
1132 try other_global.replace(global, &object.builder);1104 try other_global.replace(global, &object.builder);
...@@ -1181,17 +1153,7 @@ pub const Object = struct {...@@ -1181,17 +1153,7 @@ pub const Object = struct {
1181 }1153 }
1182 }1154 }
11831155
1184 if (comp.verbose_llvm_bc) |path| {1156 if (comp.verbose_llvm_bc) |path| _ = try self.builder.writeBitcodeToFile(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 }
11951157
1196 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);1158 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
1197 defer arena_allocator.deinit();1159 defer arena_allocator.deinit();
...@@ -1200,20 +1162,10 @@ pub const Object = struct {...@@ -1200,20 +1162,10 @@ pub const Object = struct {
1200 const mod = comp.bin_file.options.module.?;1162 const mod = comp.bin_file.options.module.?;
1201 const cache_dir = mod.zig_cache_artifact_directory;1163 const cache_dir = mod.zig_cache_artifact_directory;
12021164
1203 if (std.debug.runtime_safety) {1165 if (std.debug.runtime_safety and !try self.builder.verify()) {
1204 var error_message: [*:0]const u8 = undefined;1166 if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path|
1205 // verifyModule always allocs the error_message even if there is no error1167 _ = self.builder.printToFileZ(emit_llvm_ir_path);
1206 defer llvm.disposeMessage(error_message);1168 @panic("LLVM module verification failed");
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 }
1217 }1169 }
12181170
1219 var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|1171 var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|
...@@ -1233,12 +1185,20 @@ pub const Object = struct {...@@ -1233,12 +1185,20 @@ pub const Object = struct {
1233 emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,1185 emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,
1234 });1186 });
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
1236 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.1196 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
1237 // So we call the entire pipeline multiple times if this is requested.1197 // So we call the entire pipeline multiple times if this is requested.
1238 var error_message: [*:0]const u8 = undefined;1198 var error_message: [*:0]const u8 = undefined;
1239 if (emit_asm_path != null and emit_bin_path != null) {1199 if (emit_asm_path != null and emit_bin_path != null) {
1240 if (self.target_machine.emitToFile(1200 if (self.target_machine.emitToFile(
1241 self.llvm_module,1201 self.builder.llvm.module.?,
1242 &error_message,1202 &error_message,
1243 comp.bin_file.options.optimize_mode == .Debug,1203 comp.bin_file.options.optimize_mode == .Debug,
1244 comp.bin_file.options.optimize_mode == .ReleaseSmall,1204 comp.bin_file.options.optimize_mode == .ReleaseSmall,
...@@ -1262,7 +1222,7 @@ pub const Object = struct {...@@ -1262,7 +1222,7 @@ pub const Object = struct {
1262 }1222 }
12631223
1264 if (self.target_machine.emitToFile(1224 if (self.target_machine.emitToFile(
1265 self.llvm_module,1225 self.builder.llvm.module.?,
1266 &error_message,1226 &error_message,
1267 comp.bin_file.options.optimize_mode == .Debug,1227 comp.bin_file.options.optimize_mode == .Debug,
1268 comp.bin_file.options.optimize_mode == .ReleaseSmall,1228 comp.bin_file.options.optimize_mode == .ReleaseSmall,
...@@ -1305,37 +1265,28 @@ pub const Object = struct {...@@ -1305,37 +1265,28 @@ pub const Object = struct {
1305 .err_msg = null,1265 .err_msg = null,
1306 };1266 };
13071267
1308 const function = try o.resolveLlvmFunction(decl_index);1268 const function_index = try o.resolveLlvmFunction(decl_index);
1309 const global = function.ptrConst(&o.builder).global;
1310 const llvm_func = global.toLlvm(&o.builder);
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);
1313 defer attributes.deinit(&o.builder);1271 defer attributes.deinit(&o.builder);
13141272
1315 if (func.analysis(ip).is_noinline) {1273 if (func.analysis(ip).is_noinline) {
1316 try attributes.addFnAttr(.@"noinline", &o.builder);1274 try attributes.addFnAttr(.@"noinline", &o.builder);
1317 o.addFnAttr(llvm_func, "noinline");
1318 } else {1275 } else {
1319 _ = try attributes.removeFnAttr(.@"noinline");1276 _ = try attributes.removeFnAttr(.@"noinline");
1320 Object.removeFnAttr(llvm_func, "noinline");
1321 }1277 }
13221278
1323 if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {1279 if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {
1324 try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder);1280 try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder);
1325 try attributes.addFnAttr(.@"noinline", &o.builder);1281 try attributes.addFnAttr(.@"noinline", &o.builder);
1326 o.addFnAttrInt(llvm_func, "alignstack", alignment);
1327 o.addFnAttr(llvm_func, "noinline");
1328 } else {1282 } else {
1329 _ = try attributes.removeFnAttr(.alignstack);1283 _ = try attributes.removeFnAttr(.alignstack);
1330 Object.removeFnAttr(llvm_func, "alignstack");
1331 }1284 }
13321285
1333 if (func.analysis(ip).is_cold) {1286 if (func.analysis(ip).is_cold) {
1334 try attributes.addFnAttr(.cold, &o.builder);1287 try attributes.addFnAttr(.cold, &o.builder);
1335 o.addFnAttr(llvm_func, "cold");
1336 } else {1288 } else {
1337 _ = try attributes.removeFnAttr(.cold);1289 _ = try attributes.removeFnAttr(.cold);
1338 Object.removeFnAttr(llvm_func, "cold");
1339 }1290 }
13401291
1341 // TODO: disable this if safety is off for the function scope1292 // TODO: disable this if safety is off for the function scope
...@@ -1346,10 +1297,6 @@ pub const Object = struct {...@@ -1346,10 +1297,6 @@ pub const Object = struct {
1346 .kind = try o.builder.string("stack-protector-buffer-size"),1297 .kind = try o.builder.string("stack-protector-buffer-size"),
1347 .value = try o.builder.fmt("{d}", .{ssp_buf_size}),1298 .value = try o.builder.fmt("{d}", .{ssp_buf_size}),
1348 } }, &o.builder);1299 } }, &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);
1353 }1300 }
13541301
1355 // TODO: disable this if safety is off for the function scope1302 // TODO: disable this if safety is off for the function scope
...@@ -1358,26 +1305,21 @@ pub const Object = struct {...@@ -1358,26 +1305,21 @@ pub const Object = struct {
1358 .kind = try o.builder.string("probe-stack"),1305 .kind = try o.builder.string("probe-stack"),
1359 .value = try o.builder.string("__zig_probe_stack"),1306 .value = try o.builder.string("__zig_probe_stack"),
1360 } }, &o.builder);1307 } }, &o.builder);
1361 o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack");
1362 } else if (target.os.tag == .uefi) {1308 } else if (target.os.tag == .uefi) {
1363 try attributes.addFnAttr(.{ .string = .{1309 try attributes.addFnAttr(.{ .string = .{
1364 .kind = try o.builder.string("no-stack-arg-probe"),1310 .kind = try o.builder.string("no-stack-arg-probe"),
1365 .value = .empty,1311 .value = .empty,
1366 } }, &o.builder);1312 } }, &o.builder);
1367 o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
1368 }1313 }
13691314
1370 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| {1315 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
1371 function.ptr(&o.builder).section = try o.builder.string(section);1316 function_index.setSection(try o.builder.string(section), &o.builder);
1372 llvm_func.setSection(section);
1373 }
13741317
1375 var deinit_wip = true;1318 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);
1377 defer if (deinit_wip) wip.deinit();1320 defer if (deinit_wip) wip.deinit();
1378 wip.cursor = .{ .block = try wip.block(0, "Entry") };1321 wip.cursor = .{ .block = try wip.block(0, "Entry") };
13791322
1380 const builder = wip.llvm.builder;
1381 var llvm_arg_i: u32 = 0;1323 var llvm_arg_i: u32 = 0;
13821324
1383 // This gets the LLVM values from the function and stores them in `dg.args`.1325 // This gets the LLVM values from the function and stores them in `dg.args`.
...@@ -1389,14 +1331,8 @@ pub const Object = struct {...@@ -1389,14 +1331,8 @@ pub const Object = struct {
1389 } else .none;1331 } else .none;
13901332
1391 if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) {1333 if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) {
1392 .signed => {1334 .signed => try attributes.addRetAttr(.signext, &o.builder),
1393 try attributes.addRetAttr(.signext, &o.builder);1335 .unsigned => try attributes.addRetAttr(.zeroext, &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 },
1400 };1336 };
14011337
1402 const err_return_tracing = fn_info.return_type.toType().isError(mod) and1338 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
...@@ -1437,7 +1373,7 @@ pub const Object = struct {...@@ -1437,7 +1373,7 @@ pub const Object = struct {
1437 } else {1373 } else {
1438 args.appendAssumeCapacity(param);1374 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);
1441 }1377 }
1442 llvm_arg_i += 1;1378 llvm_arg_i += 1;
1443 },1379 },
...@@ -1447,7 +1383,7 @@ pub const Object = struct {...@@ -1447,7 +1383,7 @@ pub const Object = struct {
1447 const param = wip.arg(llvm_arg_i);1383 const param = wip.arg(llvm_arg_i);
1448 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));1384 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);
1451 llvm_arg_i += 1;1387 llvm_arg_i += 1;
14521388
1453 if (isByRef(param_ty, mod)) {1389 if (isByRef(param_ty, mod)) {
...@@ -1463,7 +1399,6 @@ pub const Object = struct {...@@ -1463,7 +1399,6 @@ pub const Object = struct {
1463 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));1399 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
14641400
1465 try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);1401 try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);
1466 o.addArgAttr(llvm_func, llvm_arg_i, "noundef");
1467 llvm_arg_i += 1;1402 llvm_arg_i += 1;
14681403
1469 if (isByRef(param_ty, mod)) {1404 if (isByRef(param_ty, mod)) {
...@@ -1479,11 +1414,7 @@ pub const Object = struct {...@@ -1479,11 +1414,7 @@ pub const Object = struct {
1479 llvm_arg_i += 1;1414 llvm_arg_i += 1;
14801415
1481 const param_llvm_ty = try o.lowerType(param_ty);1416 const param_llvm_ty = try o.lowerType(param_ty);
1482 const int_llvm_ty = try o.builder.intType(@intCast(param_ty.abiSize(mod) * 8));1417 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
1483 const alignment = Builder.Alignment.fromByteUnits(@max(
1484 param_ty.abiAlignment(mod),
1485 o.target_data.abiAlignmentOfType(int_llvm_ty.toLlvm(&o.builder)),
1486 ));
1487 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);1418 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
1488 _ = try wip.store(.normal, param, arg_ptr, alignment);1419 _ = try wip.store(.normal, param, arg_ptr, alignment);
14891420
...@@ -1500,23 +1431,19 @@ pub const Object = struct {...@@ -1500,23 +1431,19 @@ pub const Object = struct {
1500 if (math.cast(u5, it.zig_index - 1)) |i| {1431 if (math.cast(u5, it.zig_index - 1)) |i| {
1501 if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {1432 if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
1502 try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);1433 try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
1503 o.addArgAttr(llvm_func, llvm_arg_i, "noalias");
1504 }1434 }
1505 }1435 }
1506 if (param_ty.zigTypeTag(mod) != .Optional) {1436 if (param_ty.zigTypeTag(mod) != .Optional) {
1507 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);1437 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
1508 o.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
1509 }1438 }
1510 if (ptr_info.flags.is_const) {1439 if (ptr_info.flags.is_const) {
1511 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);1440 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
1512 o.addArgAttr(llvm_func, llvm_arg_i, "readonly");
1513 }1441 }
1514 const elem_align = Builder.Alignment.fromByteUnits(1442 const elem_align = Builder.Alignment.fromByteUnits(
1515 ptr_info.flags.alignment.toByteUnitsOptional() orelse1443 ptr_info.flags.alignment.toByteUnitsOptional() orelse
1516 @max(ptr_info.child.toType().abiAlignment(mod), 1),1444 @max(ptr_info.child.toType().abiAlignment(mod), 1),
1517 );1445 );
1518 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder);1446 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);
1520 const ptr_param = wip.arg(llvm_arg_i);1447 const ptr_param = wip.arg(llvm_arg_i);
1521 llvm_arg_i += 1;1448 llvm_arg_i += 1;
1522 const len_param = wip.arg(llvm_arg_i);1449 const len_param = wip.arg(llvm_arg_i);
...@@ -1590,7 +1517,7 @@ pub const Object = struct {...@@ -1590,7 +1517,7 @@ pub const Object = struct {
1590 }1517 }
1591 }1518 }
15921519
1593 function.ptr(&o.builder).attributes = try attributes.finish(&o.builder);1520 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
15941521
1595 var di_file: ?*llvm.DIFile = null;1522 var di_file: ?*llvm.DIFile = null;
1596 var di_scope: ?*llvm.DIScope = null;1523 var di_scope: ?*llvm.DIScope = null;
...@@ -1609,7 +1536,7 @@ pub const Object = struct {...@@ -1609,7 +1536,7 @@ pub const Object = struct {
1609 const subprogram = dib.createFunction(1536 const subprogram = dib.createFunction(
1610 di_file.?.toScope(),1537 di_file.?.toScope(),
1611 ip.stringToSlice(decl.name),1538 ip.stringToSlice(decl.name),
1612 llvm_func.getValueName(),1539 function_index.name(&o.builder).slice(&o.builder).?,
1613 di_file.?,1540 di_file.?,
1614 line_number,1541 line_number,
1615 decl_di_ty,1542 decl_di_ty,
...@@ -1622,7 +1549,7 @@ pub const Object = struct {...@@ -1622,7 +1549,7 @@ pub const Object = struct {
1622 );1549 );
1623 try o.di_map.put(gpa, decl, subprogram.toNode());1550 try o.di_map.put(gpa, decl, subprogram.toNode());
16241551
1625 llvm_func.fnSetSubprogram(subprogram);1552 function_index.toLlvm(&o.builder).fnSetSubprogram(subprogram);
16261553
1627 di_scope = subprogram.toScope();1554 di_scope = subprogram.toScope();
1628 }1555 }
...@@ -1633,7 +1560,6 @@ pub const Object = struct {...@@ -1633,7 +1560,6 @@ pub const Object = struct {
1633 .liveness = liveness,1560 .liveness = liveness,
1634 .dg = &dg,1561 .dg = &dg,
1635 .wip = wip,1562 .wip = wip,
1636 .builder = builder,
1637 .ret_ptr = ret_ptr,1563 .ret_ptr = ret_ptr,
1638 .args = args.items,1564 .args = args.items,
1639 .arg_index = 0,1565 .arg_index = 0,
...@@ -1694,8 +1620,7 @@ pub const Object = struct {...@@ -1694,8 +1620,7 @@ pub const Object = struct {
1694 const gpa = mod.gpa;1620 const gpa = mod.gpa;
1695 // If the module does not already have the function, we ignore this function call1621 // If the module does not already have the function, we ignore this function call
1696 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.1622 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
1697 const global = self.decl_map.get(decl_index) orelse return;1623 const global_index = self.decl_map.get(decl_index) orelse return;
1698 const llvm_global = global.toLlvm(&self.builder);
1699 const decl = mod.declPtr(decl_index);1624 const decl = mod.declPtr(decl_index);
1700 if (decl.isExtern(mod)) {1625 if (decl.isExtern(mod)) {
1701 const decl_name = decl_name: {1626 const decl_name = decl_name: {
...@@ -1713,114 +1638,91 @@ pub const Object = struct {...@@ -1713,114 +1638,91 @@ pub const Object = struct {
1713 };1638 };
17141639
1715 if (self.builder.getGlobal(decl_name)) |other_global| {1640 if (self.builder.getGlobal(decl_name)) |other_global| {
1716 if (other_global.toLlvm(&self.builder) != llvm_global) {1641 if (other_global != global_index) {
1717 try self.extern_collisions.put(gpa, decl_index, {});1642 try self.extern_collisions.put(gpa, decl_index, {});
1718 }1643 }
1719 }1644 }
17201645
1721 try global.rename(decl_name, &self.builder);1646 try global_index.rename(decl_name, &self.builder);
1722 global.ptr(&self.builder).unnamed_addr = .default;1647 global_index.setLinkage(.external, &self.builder);
1723 llvm_global.setUnnamedAddr(.False);1648 global_index.setUnnamedAddr(.default, &self.builder);
1724 global.ptr(&self.builder).linkage = .external;1649 if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder);
1725 llvm_global.setLinkage(.External);
1726 if (mod.wantDllExports()) {
1727 global.ptr(&self.builder).dll_storage_class = .default;
1728 llvm_global.setDLLStorageClass(.Default);
1729 }
1730 if (self.di_map.get(decl)) |di_node| {1650 if (self.di_map.get(decl)) |di_node| {
1731 const decl_name_slice = decl_name.slice(&self.builder).?;1651 const decl_name_slice = decl_name.slice(&self.builder).?;
1732 if (try decl.isFunction(mod)) {1652 if (try decl.isFunction(mod)) {
1733 const di_func: *llvm.DISubprogram = @ptrCast(di_node);1653 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 );
1735 di_func.replaceLinkageName(linkage_name);1659 di_func.replaceLinkageName(linkage_name);
1736 } else {1660 } else {
1737 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);1661 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 );
1739 di_global.replaceLinkageName(linkage_name);1667 di_global.replaceLinkageName(linkage_name);
1740 }1668 }
1741 }1669 }
1742 if (decl.val.getVariable(mod)) |decl_var| {1670 if (decl.val.getVariable(mod)) |decl_var| {
1743 if (decl_var.is_threadlocal) {1671 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1744 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =1672 if (decl_var.is_threadlocal) .generaldynamic else .default,
1745 .generaldynamic;1673 &self.builder,
1746 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1674 );
1747 } else {1675 if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder);
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 }
1756 }1676 }
1757 global.ptr(&self.builder).updateAttributes();
1758 } else if (exports.len != 0) {1677 } else if (exports.len != 0) {
1759 const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exports[0].opts.name));1678 const main_exp_name = try self.builder.string(
1760 try global.rename(exp_name, &self.builder);1679 mod.intern_pool.stringToSlice(exports[0].opts.name),
1761 global.ptr(&self.builder).unnamed_addr = .default;1680 );
1762 llvm_global.setUnnamedAddr(.False);1681 try global_index.rename(main_exp_name, &self.builder);
1763 if (mod.wantDllExports()) {1682 global_index.setUnnamedAddr(.default, &self.builder);
1764 global.ptr(&self.builder).dll_storage_class = .dllexport;1683 if (mod.wantDllExports()) global_index.setDllStorageClass(.dllexport, &self.builder);
1765 llvm_global.setDLLStorageClass(.DLLExport);
1766 }
1767 if (self.di_map.get(decl)) |di_node| {1684 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).?;
1769 if (try decl.isFunction(mod)) {1686 if (try decl.isFunction(mod)) {
1770 const di_func: *llvm.DISubprogram = @ptrCast(di_node);1687 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 );
1772 di_func.replaceLinkageName(linkage_name);1693 di_func.replaceLinkageName(linkage_name);
1773 } else {1694 } else {
1774 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);1695 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 );
1776 di_global.replaceLinkageName(linkage_name);1701 di_global.replaceLinkageName(linkage_name);
1777 }1702 }
1778 }1703 }
1779 switch (exports[0].opts.linkage) {1704 global_index.setLinkage(switch (exports[0].opts.linkage) {
1780 .Internal => unreachable,1705 .Internal => unreachable,
1781 .Strong => {1706 .Strong => .external,
1782 global.ptr(&self.builder).linkage = .external;1707 .Weak => .weak_odr,
1783 llvm_global.setLinkage(.External);1708 .LinkOnce => .linkonce_odr,
1784 },1709 }, &self.builder);
1785 .Weak => {1710 global_index.setVisibility(switch (exports[0].opts.visibility) {
1786 global.ptr(&self.builder).linkage = .weak_odr;1711 .default => .default,
1787 llvm_global.setLinkage(.WeakODR);1712 .hidden => .hidden,
1788 },1713 .protected => .protected,
1789 .LinkOnce => {1714 }, &self.builder);
1790 global.ptr(&self.builder).linkage = .linkonce_odr;1715 if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section|
1791 llvm_global.setLinkage(.LinkOnceODR);1716 switch (global_index.ptrConst(&self.builder).kind) {
1792 },1717 inline .variable, .function => |impl_index| impl_index.setSection(
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 =
1811 try self.builder.string(section),1718 try self.builder.string(section),
1812 else => unreachable,1719 &self.builder,
1813 }1720 ),
1814 llvm_global.setSection(section);1721 .alias, .replaced => unreachable,
1815 }1722 };
1816 if (decl.val.getVariable(mod)) |decl_var| {1723 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
1817 if (decl_var.is_threadlocal) {1724 global_index.ptrConst(&self.builder).kind
1818 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =1725 .variable.setThreadLocal(.generaldynamic, &self.builder);
1819 .generaldynamic;
1820 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1821 }
1822 }
1823 global.ptr(&self.builder).updateAttributes();
18241726
1825 // If a Decl is exported more than one time (which is rare),1727 // If a Decl is exported more than one time (which is rare),
1826 // we add aliases for all but the first export.1728 // we add aliases for all but the first export.
...@@ -1829,49 +1731,48 @@ pub const Object = struct {...@@ -1829,49 +1731,48 @@ pub const Object = struct {
1829 // Until then we iterate over existing aliases and make them point1731 // Until then we iterate over existing aliases and make them point
1830 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.1732 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.
1831 for (exports[1..]) |exp| {1733 for (exports[1..]) |exp| {
1832 const exp_name_z = mod.intern_pool.stringToSlice(exp.opts.name);1734 const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exp.opts.name));
18331735 if (self.builder.getGlobal(exp_name)) |global| {
1834 if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| {1736 switch (global.ptrConst(&self.builder).kind) {
1835 alias.setAliasee(llvm_global);1737 .alias => |alias| {
1836 } else {1738 alias.setAliasee(global_index.toConst(), &self.builder);
1837 _ = self.llvm_module.addAlias(1739 continue;
1838 global.ptrConst(&self.builder).type.toLlvm(&self.builder),1740 },
1839 0,1741 .variable, .function => {},
1840 llvm_global,1742 .replaced => unreachable,
1841 exp_name_z,1743 }
1842 );
1843 }1744 }
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);
1844 }1752 }
1845 } else {1753 } else {
1846 const fqn = try self.builder.string(mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)));1754 const fqn = try self.builder.string(
1847 try global.rename(fqn, &self.builder);1755 mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)),
1848 global.ptr(&self.builder).linkage = .internal;1756 );
1849 llvm_global.setLinkage(.Internal);1757 try global_index.rename(fqn, &self.builder);
1850 if (mod.wantDllExports()) {1758 global_index.setLinkage(.internal, &self.builder);
1851 global.ptr(&self.builder).dll_storage_class = .default;1759 if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder);
1852 llvm_global.setDLLStorageClass(.Default);1760 global_index.setUnnamedAddr(.unnamed_addr, &self.builder);
1853 }
1854 global.ptr(&self.builder).unnamed_addr = .unnamed_addr;
1855 llvm_global.setUnnamedAddr(.True);
1856 if (decl.val.getVariable(mod)) |decl_var| {1761 if (decl.val.getVariable(mod)) |decl_var| {
1857 const single_threaded = mod.comp.bin_file.options.single_threaded;1762 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1858 if (decl_var.is_threadlocal and !single_threaded) {1763 if (decl_var.is_threadlocal and !mod.comp.bin_file.options.single_threaded)
1859 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =1764 .generaldynamic
1860 .generaldynamic;1765 else
1861 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1766 .default,
1862 } else {1767 &self.builder,
1863 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =1768 );
1864 .default;
1865 llvm_global.setThreadLocalMode(.NotThreadLocal);
1866 }
1867 }1769 }
1868 global.ptr(&self.builder).updateAttributes();
1869 }1770 }
1870 }1771 }
18711772
1872 pub fn freeDecl(self: *Object, decl_index: Module.Decl.Index) void {1773 pub fn freeDecl(self: *Object, decl_index: Module.Decl.Index) void {
1873 const global = self.decl_map.get(decl_index) orelse return;1774 const global = self.decl_map.get(decl_index) orelse return;
1874 global.toLlvm(&self.builder).deleteGlobal();1775 global.delete(&self.builder);
1875 }1776 }
18761777
1877 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {1778 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {
...@@ -2907,8 +2808,12 @@ pub const Object = struct {...@@ -2907,8 +2808,12 @@ pub const Object = struct {
2907 /// If the llvm function does not exist, create it.2808 /// If the llvm function does not exist, create it.
2908 /// Note that this can be called before the function's semantic analysis has2809 /// Note that this can be called before the function's semantic analysis has
2909 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.2810 /// 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 {
2911 const mod = o.module;2815 const mod = o.module;
2816 const ip = &mod.intern_pool;
2912 const gpa = o.gpa;2817 const gpa = o.gpa;
2913 const decl = mod.declPtr(decl_index);2818 const decl = mod.declPtr(decl_index);
2914 const zig_fn_type = decl.ty;2819 const zig_fn_type = decl.ty;
...@@ -2920,46 +2825,31 @@ pub const Object = struct {...@@ -2920,46 +2825,31 @@ pub const Object = struct {
2920 const target = mod.getTarget();2825 const target = mod.getTarget();
2921 const sret = firstParamSRet(fn_info, mod);2826 const sret = firstParamSRet(fn_info, mod);
29222827
2923 const fn_type = try o.lowerType(zig_fn_type);2828 const function_index = try o.builder.addFunction(
29242829 try o.lowerType(zig_fn_type),
2925 const ip = &mod.intern_pool;2830 try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))),
2926 const fqn = try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod)));2831 toLlvmAddressSpace(decl.@"addrspace", target),
29272832 );
2928 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);2833 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
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 };
29382834
2939 var attributes: Builder.FunctionAttributes.Wip = .{};2835 var attributes: Builder.FunctionAttributes.Wip = .{};
2940 defer attributes.deinit(&o.builder);2836 defer attributes.deinit(&o.builder);
29412837
2942 const is_extern = decl.isExtern(mod);2838 const is_extern = decl.isExtern(mod);
2943 if (!is_extern) {2839 if (!is_extern) {
2944 global.linkage = .internal;2840 function_index.setLinkage(.internal, &o.builder);
2945 llvm_fn.setLinkage(.Internal);2841 function_index.setUnnamedAddr(.unnamed_addr, &o.builder);
2946 global.unnamed_addr = .unnamed_addr;
2947 llvm_fn.setUnnamedAddr(.True);
2948 } else {2842 } else {
2949 if (target.isWasm()) {2843 if (target.isWasm()) {
2950 try attributes.addFnAttr(.{ .string = .{2844 try attributes.addFnAttr(.{ .string = .{
2951 .kind = try o.builder.string("wasm-import-name"),2845 .kind = try o.builder.string("wasm-import-name"),
2952 .value = try o.builder.string(ip.stringToSlice(decl.name)),2846 .value = try o.builder.string(ip.stringToSlice(decl.name)),
2953 } }, &o.builder);2847 } }, &o.builder);
2954 o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
2955 if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {2848 if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
2956 if (!std.mem.eql(u8, lib_name, "c")) {2849 if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{
2957 try attributes.addFnAttr(.{ .string = .{2850 .kind = try o.builder.string("wasm-import-module"),
2958 .kind = try o.builder.string("wasm-import-module"),2851 .value = try o.builder.string(lib_name),
2959 .value = try o.builder.string(lib_name),2852 } }, &o.builder);
2960 } }, &o.builder);
2961 o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
2962 }
2963 }2853 }
2964 }2854 }
2965 }2855 }
...@@ -2969,12 +2859,9 @@ pub const Object = struct {...@@ -2969,12 +2859,9 @@ pub const Object = struct {
2969 // Sret pointers must not be address 02859 // Sret pointers must not be address 0
2970 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);2860 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
2971 try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);2861 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
2975 const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType());2863 const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType());
2976 try attributes.addParamAttr(llvm_arg_i, .{ .sret = raw_llvm_ret_ty }, &o.builder);2864 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
2979 llvm_arg_i += 1;2866 llvm_arg_i += 1;
2980 }2867 }
...@@ -2984,42 +2871,26 @@ pub const Object = struct {...@@ -2984,42 +2871,26 @@ pub const Object = struct {
29842871
2985 if (err_return_tracing) {2872 if (err_return_tracing) {
2986 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);2873 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
2987 o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
2988 llvm_arg_i += 1;2874 llvm_arg_i += 1;
2989 }2875 }
29902876
2991 switch (fn_info.cc) {2877 switch (fn_info.cc) {
2992 .Unspecified, .Inline => {2878 .Unspecified, .Inline => function_index.setCallConv(.fastcc, &o.builder),
2993 function.call_conv = .fastcc;2879 .Naked => try attributes.addFnAttr(.naked, &o.builder),
2994 llvm_fn.setFunctionCallConv(.Fast);
2995 },
2996 .Naked => {
2997 try attributes.addFnAttr(.naked, &o.builder);
2998 o.addFnAttr(llvm_fn, "naked");
2999 },
3000 .Async => {2880 .Async => {
3001 function.call_conv = .fastcc;2881 function_index.setCallConv(.fastcc, &o.builder);
3002 llvm_fn.setFunctionCallConv(.Fast);
3003 @panic("TODO: LLVM backend lower async function");2882 @panic("TODO: LLVM backend lower async function");
3004 },2883 },
3005 else => {2884 else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),
3006 function.call_conv = toLlvmCallConv(fn_info.cc, target);
3007 llvm_fn.setFunctionCallConv(@enumFromInt(@intFromEnum(function.call_conv)));
3008 },
3009 }2885 }
30102886
3011 if (fn_info.alignment.toByteUnitsOptional()) |a| {2887 if (fn_info.alignment.toByteUnitsOptional()) |alignment|
3012 function.alignment = Builder.Alignment.fromByteUnits(a);2888 function_index.setAlignment(Builder.Alignment.fromByteUnits(alignment), &o.builder);
3013 llvm_fn.setAlignment(@intCast(a));
3014 }
30152889
3016 // Function attributes that are independent of analysis results of the function body.2890 // 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) {2893 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
3020 try attributes.addFnAttr(.noreturn, &o.builder);
3021 o.addFnAttr(llvm_fn, "noreturn");
3022 }
30232894
3024 // Add parameter attributes. We handle only the case of extern functions (no body)2895 // Add parameter attributes. We handle only the case of extern functions (no body)
3025 // because functions with bodies are handled in `updateFunc`.2896 // because functions with bodies are handled in `updateFunc`.
...@@ -3031,7 +2902,7 @@ pub const Object = struct {...@@ -3031,7 +2902,7 @@ pub const Object = struct {
3031 const param_index = it.zig_index - 1;2902 const param_index = it.zig_index - 1;
3032 const param_ty = fn_info.param_types.get(ip)[param_index].toType();2903 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
3033 if (!isByRef(param_ty, mod)) {2904 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);
3035 }2906 }
3036 },2907 },
3037 .byref => {2908 .byref => {
...@@ -3039,12 +2910,9 @@ pub const Object = struct {...@@ -3039,12 +2910,9 @@ pub const Object = struct {
3039 const param_llvm_ty = try o.lowerType(param_ty.toType());2910 const param_llvm_ty = try o.lowerType(param_ty.toType());
3040 const alignment =2911 const alignment =
3041 Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod));2912 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);2913 try o.addByRefParamAttrs(&attributes, 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");
3047 },2914 },
2915 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
3048 // No attributes needed for these.2916 // No attributes needed for these.
3049 .no_bits,2917 .no_bits,
3050 .abi_sized_int,2918 .abi_sized_int,
...@@ -3060,43 +2928,33 @@ pub const Object = struct {...@@ -3060,43 +2928,33 @@ pub const Object = struct {
3060 };2928 };
3061 }2929 }
30622930
3063 function.attributes = try attributes.finish(&o.builder);2931 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
30642932 return function_index;
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;
3069 }2933 }
30702934
3071 fn addCommonFnAttributes(2935 fn addCommonFnAttributes(
3072 o: *Object,2936 o: *Object,
3073 attributes: *Builder.FunctionAttributes.Wip,2937 attributes: *Builder.FunctionAttributes.Wip,
3074 llvm_fn: *llvm.Value,
3075 ) Allocator.Error!void {2938 ) Allocator.Error!void {
3076 const comp = o.module.comp;2939 const comp = o.module.comp;
30772940
3078 if (!comp.bin_file.options.red_zone) {2941 if (!comp.bin_file.options.red_zone) {
3079 try attributes.addFnAttr(.noredzone, &o.builder);2942 try attributes.addFnAttr(.noredzone, &o.builder);
3080 o.addFnAttr(llvm_fn, "noredzone");
3081 }2943 }
3082 if (comp.bin_file.options.omit_frame_pointer) {2944 if (comp.bin_file.options.omit_frame_pointer) {
3083 try attributes.addFnAttr(.{ .string = .{2945 try attributes.addFnAttr(.{ .string = .{
3084 .kind = try o.builder.string("frame-pointer"),2946 .kind = try o.builder.string("frame-pointer"),
3085 .value = try o.builder.string("none"),2947 .value = try o.builder.string("none"),
3086 } }, &o.builder);2948 } }, &o.builder);
3087 o.addFnAttrString(llvm_fn, "frame-pointer", "none");
3088 } else {2949 } else {
3089 try attributes.addFnAttr(.{ .string = .{2950 try attributes.addFnAttr(.{ .string = .{
3090 .kind = try o.builder.string("frame-pointer"),2951 .kind = try o.builder.string("frame-pointer"),
3091 .value = try o.builder.string("all"),2952 .value = try o.builder.string("all"),
3092 } }, &o.builder);2953 } }, &o.builder);
3093 o.addFnAttrString(llvm_fn, "frame-pointer", "all");
3094 }2954 }
3095 try attributes.addFnAttr(.nounwind, &o.builder);2955 try attributes.addFnAttr(.nounwind, &o.builder);
3096 o.addFnAttr(llvm_fn, "nounwind");
3097 if (comp.unwind_tables) {2956 if (comp.unwind_tables) {
3098 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);2957 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
3099 o.addFnAttrInt(llvm_fn, "uwtable", 2);
3100 }2958 }
3101 if (comp.bin_file.options.skip_linker_dependencies or2959 if (comp.bin_file.options.skip_linker_dependencies or
3102 comp.bin_file.options.no_builtin)2960 comp.bin_file.options.no_builtin)
...@@ -3107,111 +2965,78 @@ pub const Object = struct {...@@ -3107,111 +2965,78 @@ pub const Object = struct {
3107 // body of memcpy with a call to memcpy, which would then cause a stack2965 // body of memcpy with a call to memcpy, which would then cause a stack
3108 // overflow instead of performing memcpy.2966 // overflow instead of performing memcpy.
3109 try attributes.addFnAttr(.nobuiltin, &o.builder);2967 try attributes.addFnAttr(.nobuiltin, &o.builder);
3110 o.addFnAttr(llvm_fn, "nobuiltin");
3111 }2968 }
3112 if (comp.bin_file.options.optimize_mode == .ReleaseSmall) {2969 if (comp.bin_file.options.optimize_mode == .ReleaseSmall) {
3113 try attributes.addFnAttr(.minsize, &o.builder);2970 try attributes.addFnAttr(.minsize, &o.builder);
3114 try attributes.addFnAttr(.optsize, &o.builder);2971 try attributes.addFnAttr(.optsize, &o.builder);
3115 o.addFnAttr(llvm_fn, "minsize");
3116 o.addFnAttr(llvm_fn, "optsize");
3117 }2972 }
3118 if (comp.bin_file.options.tsan) {2973 if (comp.bin_file.options.tsan) {
3119 try attributes.addFnAttr(.sanitize_thread, &o.builder);2974 try attributes.addFnAttr(.sanitize_thread, &o.builder);
3120 o.addFnAttr(llvm_fn, "sanitize_thread");
3121 }2975 }
3122 if (comp.getTarget().cpu.model.llvm_name) |s| {2976 if (comp.getTarget().cpu.model.llvm_name) |s| {
3123 try attributes.addFnAttr(.{ .string = .{2977 try attributes.addFnAttr(.{ .string = .{
3124 .kind = try o.builder.string("target-cpu"),2978 .kind = try o.builder.string("target-cpu"),
3125 .value = try o.builder.string(s),2979 .value = try o.builder.string(s),
3126 } }, &o.builder);2980 } }, &o.builder);
3127 llvm_fn.addFunctionAttr("target-cpu", s);
3128 }2981 }
3129 if (comp.bin_file.options.llvm_cpu_features) |s| {2982 if (comp.bin_file.options.llvm_cpu_features) |s| {
3130 try attributes.addFnAttr(.{ .string = .{2983 try attributes.addFnAttr(.{ .string = .{
3131 .kind = try o.builder.string("target-features"),2984 .kind = try o.builder.string("target-features"),
3132 .value = try o.builder.string(std.mem.span(s)),2985 .value = try o.builder.string(std.mem.span(s)),
3133 } }, &o.builder);2986 } }, &o.builder);
3134 llvm_fn.addFunctionAttr("target-features", s);
3135 }2987 }
3136 if (comp.getTarget().cpu.arch.isBpf()) {2988 if (comp.getTarget().cpu.arch.isBpf()) {
3137 try attributes.addFnAttr(.{ .string = .{2989 try attributes.addFnAttr(.{ .string = .{
3138 .kind = try o.builder.string("no-builtins"),2990 .kind = try o.builder.string("no-builtins"),
3139 .value = .empty,2991 .value = .empty,
3140 } }, &o.builder);2992 } }, &o.builder);
3141 llvm_fn.addFunctionAttr("no-builtins", "");
3142 }2993 }
3143 }2994 }
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 {
3146 const gop = try o.decl_map.getOrPut(o.gpa, decl_index);3000 const gop = try o.decl_map.getOrPut(o.gpa, decl_index);
3147 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;3001 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;
3148 errdefer assert(o.decl_map.remove(decl_index));3002 errdefer assert(o.decl_map.remove(decl_index));
31493003
3150 const mod = o.module;3004 const mod = o.module;
3151 const decl = mod.declPtr(decl_index);3005 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
3167 const is_extern = decl.isExtern(mod);3006 const is_extern = decl.isExtern(mod);
3168 const name = if (is_extern)3007
3169 try o.builder.string(mod.intern_pool.stringToSlice(decl.name))3008 const variable_index = try o.builder.addVariable(
3170 else3009 try o.builder.string(mod.intern_pool.stringToSlice(
3171 fqn;3010 if (is_extern) decl.name else try decl.getFullyQualifiedName(mod),
3172 const llvm_global = o.llvm_module.addGlobalInAddressSpace(3011 )),
3173 global.type.toLlvm(&o.builder),3012 try o.lowerType(decl.ty),
3174 fqn.slice(&o.builder).?,3013 toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()),
3175 @intFromEnum(global.addr_space),
3176 );3014 );
3015 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
31773016
3178 // This is needed for declarations created by `@extern`.3017 // This is needed for declarations created by `@extern`.
3179 if (is_extern) {3018 if (is_extern) {
3180 global.unnamed_addr = .default;3019 variable_index.setLinkage(.external, &o.builder);
3181 llvm_global.setUnnamedAddr(.False);3020 variable_index.setUnnamedAddr(.default, &o.builder);
3182 global.linkage = .external;
3183 llvm_global.setLinkage(.External);
3184 if (decl.val.getVariable(mod)) |decl_var| {3021 if (decl.val.getVariable(mod)) |decl_var| {
3185 const single_threaded = mod.comp.bin_file.options.single_threaded;3022 const single_threaded = mod.comp.bin_file.options.single_threaded;
3186 if (decl_var.is_threadlocal and !single_threaded) {3023 variable_index.setThreadLocal(
3187 variable.thread_local = .generaldynamic;3024 if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default,
3188 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);3025 &o.builder,
3189 } else {3026 );
3190 variable.thread_local = .default;3027 if (decl_var.is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder);
3191 llvm_global.setThreadLocalMode(.NotThreadLocal);
3192 }
3193 if (decl_var.is_weak_linkage) {
3194 global.linkage = .extern_weak;
3195 llvm_global.setLinkage(.ExternalWeak);
3196 }
3197 }3028 }
3198 } else {3029 } else {
3199 global.linkage = .internal;3030 variable_index.setLinkage(.internal, &o.builder);
3200 llvm_global.setLinkage(.Internal);3031 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
3201 global.unnamed_addr = .unnamed_addr;
3202 llvm_global.setUnnamedAddr(.True);
3203 }3032 }
32043033 return variable_index;
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;
3209 }3034 }
32103035
3211 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {3036 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
3212 const ty = try o.lowerTypeInner(t);3037 const ty = try o.lowerTypeInner(t);
3213 const mod = o.module;3038 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: {
3215 const llvm_ty = ty.toLlvm(&o.builder);3040 const llvm_ty = ty.toLlvm(&o.builder);
3216 if (t.zigTypeTag(mod) == .Opaque) break :check;3041 if (t.zigTypeTag(mod) == .Opaque) break :check;
3217 if (!t.hasRuntimeBits(mod)) break :check;3042 if (!t.hasRuntimeBits(mod)) break :check;
...@@ -4483,69 +4308,6 @@ pub const Object = struct {...@@ -4483,69 +4308,6 @@ pub const Object = struct {
4483 return o.builder.castConst(.inttoptr, try o.builder.intConst(llvm_usize, int), llvm_ptr_ty);4308 return o.builder.castConst(.inttoptr, try o.builder.intConst(llvm_usize, int), llvm_ptr_ty);
4484 }4309 }
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
4549 /// If the operand type of an atomic operation is not byte sized we need to4311 /// If the operand type of an atomic operation is not byte sized we need to
4550 /// widen it before using it and then truncate the result.4312 /// widen it before using it and then truncate the result.
4551 /// RMW exchange of floating-point values is bitcasted to same-sized integer4313 /// RMW exchange of floating-point values is bitcasted to same-sized integer
...@@ -4608,80 +4370,13 @@ pub const Object = struct {...@@ -4608,80 +4370,13 @@ pub const Object = struct {
4608 attributes: *Builder.FunctionAttributes.Wip,4370 attributes: *Builder.FunctionAttributes.Wip,
4609 llvm_arg_i: u32,4371 llvm_arg_i: u32,
4610 alignment: Builder.Alignment,4372 alignment: Builder.Alignment,
4611 byval_attr: bool,4373 byval: 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,
4673 param_llvm_ty: Builder.Type,4374 param_llvm_ty: Builder.Type,
4674 ) Allocator.Error!void {4375 ) Allocator.Error!void {
4675 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);4376 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4676 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);4377 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
4677 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder);4378 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder);
4678 o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");4379 if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder);
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 }
4685 }4380 }
4686};4381};
46874382
...@@ -4712,65 +4407,22 @@ pub const DeclGen = struct {...@@ -4712,65 +4407,22 @@ pub const DeclGen = struct {
4712 if (decl.val.getExternFunc(mod)) |extern_func| {4407 if (decl.val.getExternFunc(mod)) |extern_func| {
4713 _ = try o.resolveLlvmFunction(extern_func.decl);4408 _ = try o.resolveLlvmFunction(extern_func.decl);
4714 } else {4409 } else {
4715 const target = mod.getTarget();4410 const variable_index = try o.resolveGlobalDecl(decl_index);
4716 const variable = try o.resolveGlobalDecl(decl_index);4411 variable_index.setAlignment(
4717 const global = variable.ptrConst(&o.builder).global;4412 Builder.Alignment.fromByteUnits(decl.getAlignment(mod)),
4718 var llvm_global = global.toLlvm(&o.builder);4413 &o.builder,
4719 variable.ptr(&o.builder).alignment = Builder.Alignment.fromByteUnits(decl.getAlignment(mod));4414 );
4720 llvm_global.setAlignment(decl.getAlignment(mod));4415 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
4721 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| {4416 variable_index.setSection(try o.builder.string(section), &o.builder);
4722 variable.ptr(&o.builder).section = try o.builder.string(section);
4723 llvm_global.setSection(section);
4724 }
4725 assert(decl.has_tv);4417 assert(decl.has_tv);
4726 const init_val = if (decl.val.getVariable(mod)) |decl_var| decl_var.init else init_val: {4418 const init_val = if (decl.val.getVariable(mod)) |decl_var| decl_var.init else init_val: {
4727 variable.ptr(&o.builder).mutability = .constant;4419 variable_index.setMutability(.constant, &o.builder);
4728 llvm_global.setGlobalConstant(.True);
4729 break :init_val decl.val.toIntern();4420 break :init_val decl.val.toIntern();
4730 };4421 };
4731 if (init_val != .none) {4422 try variable_index.setInitializer(switch (init_val) {
4732 const llvm_init = try o.lowerValue(init_val);4423 .none => .no_init,
4733 const llvm_init_ty = llvm_init.typeOf(&o.builder);4424 else => try o.lowerValue(init_val),
4734 if (global.ptrConst(&o.builder).type == llvm_init_ty) {4425 }, &o.builder);
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 }
47744426
4775 if (o.di_builder) |dib| {4427 if (o.di_builder) |dib| {
4776 const di_file = try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope);4428 const di_file = try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
...@@ -4780,7 +4432,7 @@ pub const DeclGen = struct {...@@ -4780,7 +4432,7 @@ pub const DeclGen = struct {
4780 const di_global = dib.createGlobalVariableExpression(4432 const di_global = dib.createGlobalVariableExpression(
4781 di_file.toScope(),4433 di_file.toScope(),
4782 mod.intern_pool.stringToSlice(decl.name),4434 mod.intern_pool.stringToSlice(decl.name),
4783 llvm_global.getValueName(),4435 variable_index.name(&o.builder).slice(&o.builder).?,
4784 di_file,4436 di_file,
4785 line_number,4437 line_number,
4786 try o.lowerDebugType(decl.ty, .full),4438 try o.lowerDebugType(decl.ty, .full),
...@@ -4788,7 +4440,8 @@ pub const DeclGen = struct {...@@ -4788,7 +4440,8 @@ pub const DeclGen = struct {
4788 );4440 );
47894441
4790 try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode());4442 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);
4792 }4445 }
4793 }4446 }
4794 }4447 }
...@@ -4800,7 +4453,6 @@ pub const FuncGen = struct {...@@ -4800,7 +4453,6 @@ pub const FuncGen = struct {
4800 air: Air,4453 air: Air,
4801 liveness: Liveness,4454 liveness: Liveness,
4802 wip: Builder.WipFunction,4455 wip: Builder.WipFunction,
4803 builder: *llvm.Builder,
4804 di_scope: ?*llvm.DIScope,4456 di_scope: ?*llvm.DIScope,
4805 di_file: ?*llvm.DIFile,4457 di_file: ?*llvm.DIFile,
4806 base_line: u32,4458 base_line: u32,
...@@ -4889,38 +4541,22 @@ pub const FuncGen = struct {...@@ -4889,38 +4541,22 @@ pub const FuncGen = struct {
4889 // We have an LLVM value but we need to create a global constant and4541 // We have an LLVM value but we need to create a global constant and
4890 // set the value as its initializer, and then return a pointer to the global.4542 // set the value as its initializer, and then return a pointer to the global.
4891 const target = mod.getTarget();4543 const target = mod.getTarget();
4892 const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target);4544 const variable_index = try o.builder.addVariable(
4893 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target);4545 .empty,
4894 const llvm_ty = llvm_val.typeOf(&o.builder);4546 llvm_val.typeOf(&o.builder),
4895 const llvm_alignment = tv.ty.abiAlignment(mod);4547 toLlvmGlobalAddressSpace(.generic, target),
4896 const llvm_global = o.llvm_module.addGlobalInAddressSpace(llvm_ty.toLlvm(&o.builder), "", @intFromEnum(llvm_actual_addrspace));4548 );
4897 llvm_global.setInitializer(llvm_val.toLlvm(&o.builder));4549 try variable_index.setInitializer(llvm_val, &o.builder);
4898 llvm_global.setLinkage(.Private);4550 variable_index.setLinkage(.private, &o.builder);
4899 llvm_global.setGlobalConstant(.True);4551 variable_index.setMutability(.constant, &o.builder);
4900 llvm_global.setUnnamedAddr(.True);4552 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4901 llvm_global.setAlignment(llvm_alignment);4553 variable_index.setAlignment(Builder.Alignment.fromByteUnits(
49024554 tv.ty.abiAlignment(mod),
4903 var global = Builder.Global{4555 ), &o.builder);
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
4920 return o.builder.convConst(4556 return o.builder.convConst(
4921 .unneeded,4557 .unneeded,
4922 global_index.toConst(),4558 variable_index.toConst(&o.builder),
4923 try o.builder.ptrType(llvm_wanted_addrspace),4559 try o.builder.ptrType(toLlvmAddressSpace(.generic, target)),
4924 );4560 );
4925 }4561 }
49264562
...@@ -4947,31 +4583,31 @@ pub const FuncGen = struct {...@@ -4947,31 +4583,31 @@ pub const FuncGen = struct {
49474583
4948 const val: Builder.Value = switch (air_tags[inst]) {4584 const val: Builder.Value = switch (air_tags[inst]) {
4949 // zig fmt: off4585 // zig fmt: off
4950 .add => try self.airAdd(inst, false),4586 .add => try self.airAdd(inst, .normal),
4951 .add_optimized => try self.airAdd(inst, true),4587 .add_optimized => try self.airAdd(inst, .fast),
4952 .add_wrap => try self.airAddWrap(inst),4588 .add_wrap => try self.airAddWrap(inst),
4953 .add_sat => try self.airAddSat(inst),4589 .add_sat => try self.airAddSat(inst),
49544590
4955 .sub => try self.airSub(inst, false),4591 .sub => try self.airSub(inst, .normal),
4956 .sub_optimized => try self.airSub(inst, true),4592 .sub_optimized => try self.airSub(inst, .fast),
4957 .sub_wrap => try self.airSubWrap(inst),4593 .sub_wrap => try self.airSubWrap(inst),
4958 .sub_sat => try self.airSubSat(inst),4594 .sub_sat => try self.airSubSat(inst),
49594595
4960 .mul => try self.airMul(inst, false),4596 .mul => try self.airMul(inst, .normal),
4961 .mul_optimized => try self.airMul(inst, true),4597 .mul_optimized => try self.airMul(inst, .fast),
4962 .mul_wrap => try self.airMulWrap(inst),4598 .mul_wrap => try self.airMulWrap(inst),
4963 .mul_sat => try self.airMulSat(inst),4599 .mul_sat => try self.airMulSat(inst),
49644600
4965 .add_safe => try self.airSafeArithmetic(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),4601 .add_safe => try self.airSafeArithmetic(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"),
4966 .sub_safe => try self.airSafeArithmetic(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),4602 .sub_safe => try self.airSafeArithmetic(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
4967 .mul_safe => try self.airSafeArithmetic(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),4603 .mul_safe => try self.airSafeArithmetic(inst, .@"smul.with.overflow", .@"umul.with.overflow"),
49684604
4969 .div_float => try self.airDivFloat(inst, false),4605 .div_float => try self.airDivFloat(inst, .normal),
4970 .div_trunc => try self.airDivTrunc(inst, false),4606 .div_trunc => try self.airDivTrunc(inst, .normal),
4971 .div_floor => try self.airDivFloor(inst, false),4607 .div_floor => try self.airDivFloor(inst, .normal),
4972 .div_exact => try self.airDivExact(inst, false),4608 .div_exact => try self.airDivExact(inst, .normal),
4973 .rem => try self.airRem(inst, false),4609 .rem => try self.airRem(inst, .normal),
4974 .mod => try self.airMod(inst, false),4610 .mod => try self.airMod(inst, .normal),
4975 .ptr_add => try self.airPtrAdd(inst),4611 .ptr_add => try self.airPtrAdd(inst),
4976 .ptr_sub => try self.airPtrSub(inst),4612 .ptr_sub => try self.airPtrSub(inst),
4977 .shl => try self.airShl(inst),4613 .shl => try self.airShl(inst),
...@@ -4982,16 +4618,16 @@ pub const FuncGen = struct {...@@ -4982,16 +4618,16 @@ pub const FuncGen = struct {
4982 .slice => try self.airSlice(inst),4618 .slice => try self.airSlice(inst),
4983 .mul_add => try self.airMulAdd(inst),4619 .mul_add => try self.airMulAdd(inst),
49844620
4985 .div_float_optimized => try self.airDivFloat(inst, true),4621 .div_float_optimized => try self.airDivFloat(inst, .fast),
4986 .div_trunc_optimized => try self.airDivTrunc(inst, true),4622 .div_trunc_optimized => try self.airDivTrunc(inst, .fast),
4987 .div_floor_optimized => try self.airDivFloor(inst, true),4623 .div_floor_optimized => try self.airDivFloor(inst, .fast),
4988 .div_exact_optimized => try self.airDivExact(inst, true),4624 .div_exact_optimized => try self.airDivExact(inst, .fast),
4989 .rem_optimized => try self.airRem(inst, true),4625 .rem_optimized => try self.airRem(inst, .fast),
4990 .mod_optimized => try self.airMod(inst, true),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"),4628 .add_with_overflow => try self.airOverflow(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"),
4993 .sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),4629 .sub_with_overflow => try self.airOverflow(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
4994 .mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),4630 .mul_with_overflow => try self.airOverflow(inst, .@"smul.with.overflow", .@"umul.with.overflow"),
4995 .shl_with_overflow => try self.airShlWithOverflow(inst),4631 .shl_with_overflow => try self.airShlWithOverflow(inst),
49964632
4997 .bit_and, .bool_and => try self.airAnd(inst),4633 .bit_and, .bool_and => try self.airAnd(inst),
...@@ -5015,25 +4651,25 @@ pub const FuncGen = struct {...@@ -5015,25 +4651,25 @@ pub const FuncGen = struct {
5015 .round => try self.airUnaryOp(inst, .round),4651 .round => try self.airUnaryOp(inst, .round),
5016 .trunc_float => try self.airUnaryOp(inst, .trunc),4652 .trunc_float => try self.airUnaryOp(inst, .trunc),
50174653
5018 .neg => try self.airNeg(inst, false),4654 .neg => try self.airNeg(inst, .normal),
5019 .neg_optimized => try self.airNeg(inst, true),4655 .neg_optimized => try self.airNeg(inst, .fast),
50204656
5021 .cmp_eq => try self.airCmp(inst, .eq, false),4657 .cmp_eq => try self.airCmp(inst, .eq, .normal),
5022 .cmp_gt => try self.airCmp(inst, .gt, false),4658 .cmp_gt => try self.airCmp(inst, .gt, .normal),
5023 .cmp_gte => try self.airCmp(inst, .gte, false),4659 .cmp_gte => try self.airCmp(inst, .gte, .normal),
5024 .cmp_lt => try self.airCmp(inst, .lt, false),4660 .cmp_lt => try self.airCmp(inst, .lt, .normal),
5025 .cmp_lte => try self.airCmp(inst, .lte, false),4661 .cmp_lte => try self.airCmp(inst, .lte, .normal),
5026 .cmp_neq => try self.airCmp(inst, .neq, false),4662 .cmp_neq => try self.airCmp(inst, .neq, .normal),
50274663
5028 .cmp_eq_optimized => try self.airCmp(inst, .eq, true),4664 .cmp_eq_optimized => try self.airCmp(inst, .eq, .fast),
5029 .cmp_gt_optimized => try self.airCmp(inst, .gt, true),4665 .cmp_gt_optimized => try self.airCmp(inst, .gt, .fast),
5030 .cmp_gte_optimized => try self.airCmp(inst, .gte, true),4666 .cmp_gte_optimized => try self.airCmp(inst, .gte, .fast),
5031 .cmp_lt_optimized => try self.airCmp(inst, .lt, true),4667 .cmp_lt_optimized => try self.airCmp(inst, .lt, .fast),
5032 .cmp_lte_optimized => try self.airCmp(inst, .lte, true),4668 .cmp_lte_optimized => try self.airCmp(inst, .lte, .fast),
5033 .cmp_neq_optimized => try self.airCmp(inst, .neq, true),4669 .cmp_neq_optimized => try self.airCmp(inst, .neq, .fast),
50344670
5035 .cmp_vector => try self.airCmpVector(inst, false),4671 .cmp_vector => try self.airCmpVector(inst, .normal),
5036 .cmp_vector_optimized => try self.airCmpVector(inst, true),4672 .cmp_vector_optimized => try self.airCmpVector(inst, .fast),
5037 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),4673 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
50384674
5039 .is_non_null => try self.airIsNonNull(inst, false, .ne),4675 .is_non_null => try self.airIsNonNull(inst, false, .ne),
...@@ -5085,13 +4721,13 @@ pub const FuncGen = struct {...@@ -5085,13 +4721,13 @@ pub const FuncGen = struct {
5085 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),4721 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
5086 .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),4722 .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),
50874723
5088 .int_from_float => try self.airIntFromFloat(inst, false),4724 .int_from_float => try self.airIntFromFloat(inst, .normal),
5089 .int_from_float_optimized => try self.airIntFromFloat(inst, true),4725 .int_from_float_optimized => try self.airIntFromFloat(inst, .fast),
50904726
5091 .array_to_slice => try self.airArrayToSlice(inst),4727 .array_to_slice => try self.airArrayToSlice(inst),
5092 .float_from_int => try self.airFloatFromInt(inst),4728 .float_from_int => try self.airFloatFromInt(inst),
5093 .cmpxchg_weak => try self.airCmpxchg(inst, true),4729 .cmpxchg_weak => try self.airCmpxchg(inst, .weak),
5094 .cmpxchg_strong => try self.airCmpxchg(inst, false),4730 .cmpxchg_strong => try self.airCmpxchg(inst, .strong),
5095 .fence => try self.airFence(inst),4731 .fence => try self.airFence(inst),
5096 .atomic_rmw => try self.airAtomicRmw(inst),4732 .atomic_rmw => try self.airAtomicRmw(inst),
5097 .atomic_load => try self.airAtomicLoad(inst),4733 .atomic_load => try self.airAtomicLoad(inst),
...@@ -5100,11 +4736,11 @@ pub const FuncGen = struct {...@@ -5100,11 +4736,11 @@ pub const FuncGen = struct {
5100 .memcpy => try self.airMemcpy(inst),4736 .memcpy => try self.airMemcpy(inst),
5101 .set_union_tag => try self.airSetUnionTag(inst),4737 .set_union_tag => try self.airSetUnionTag(inst),
5102 .get_union_tag => try self.airGetUnionTag(inst),4738 .get_union_tag => try self.airGetUnionTag(inst),
5103 .clz => try self.airClzCtz(inst, .@"llvm.ctlz."),4739 .clz => try self.airClzCtz(inst, .ctlz),
5104 .ctz => try self.airClzCtz(inst, .@"llvm.cttz."),4740 .ctz => try self.airClzCtz(inst, .cttz),
5105 .popcount => try self.airBitOp(inst, .@"llvm.ctpop."),4741 .popcount => try self.airBitOp(inst, .ctpop),
5106 .byte_swap => try self.airByteSwap(inst),4742 .byte_swap => try self.airByteSwap(inst),
5107 .bit_reverse => try self.airBitOp(inst, .@"llvm.bitreverse."),4743 .bit_reverse => try self.airBitOp(inst, .bitreverse),
5108 .tag_name => try self.airTagName(inst),4744 .tag_name => try self.airTagName(inst),
5109 .error_name => try self.airErrorName(inst),4745 .error_name => try self.airErrorName(inst),
5110 .splat => try self.airSplat(inst),4746 .splat => try self.airSplat(inst),
...@@ -5118,8 +4754,8 @@ pub const FuncGen = struct {...@@ -5118,8 +4754,8 @@ pub const FuncGen = struct {
5118 .is_named_enum_value => try self.airIsNamedEnumValue(inst),4754 .is_named_enum_value => try self.airIsNamedEnumValue(inst),
5119 .error_set_has_value => try self.airErrorSetHasValue(inst),4755 .error_set_has_value => try self.airErrorSetHasValue(inst),
51204756
5121 .reduce => try self.airReduce(inst, false),4757 .reduce => try self.airReduce(inst, .normal),
5122 .reduce_optimized => try self.airReduce(inst, true),4758 .reduce_optimized => try self.airReduce(inst, .fast),
51234759
5124 .atomic_store_unordered => try self.airAtomicStore(inst, .unordered),4760 .atomic_store_unordered => try self.airAtomicStore(inst, .unordered),
5125 .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),4761 .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),
...@@ -5304,10 +4940,7 @@ pub const FuncGen = struct {...@@ -5304,10 +4940,7 @@ pub const FuncGen = struct {
5304 } else {4940 } else {
5305 // LLVM does not allow bitcasting structs so we must allocate4941 // LLVM does not allow bitcasting structs so we must allocate
5306 // a local, store as one type, and then load as another type.4942 // a local, store as one type, and then load as another type.
5307 const alignment = Builder.Alignment.fromByteUnits(@max(4943 const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod));
5308 param_ty.abiAlignment(mod),
5309 o.target_data.abiAlignmentOfType(int_llvm_ty.toLlvm(&o.builder)),
5310 ));
5311 const int_ptr = try self.buildAlloca(int_llvm_ty, alignment);4944 const int_ptr = try self.buildAlloca(int_llvm_ty, alignment);
5312 _ = try self.wip.store(.normal, llvm_arg, int_ptr, alignment);4945 _ = try self.wip.store(.normal, llvm_arg, int_ptr, alignment);
5313 const loaded = try self.wip.load(.normal, int_llvm_ty, int_ptr, alignment, "");4946 const loaded = try self.wip.load(.normal, int_llvm_ty, int_ptr, alignment, "");
...@@ -5483,12 +5116,10 @@ pub const FuncGen = struct {...@@ -5483,12 +5116,10 @@ pub const FuncGen = struct {
5483 // In this case the function return type is honoring the calling convention by having5116 // In this case the function return type is honoring the calling convention by having
5484 // a different LLVM type than the usual one. We solve this here at the callsite5117 // a different LLVM type than the usual one. We solve this here at the callsite
5485 // by using our canonical type, then loading it if necessary.5118 // by using our canonical type, then loading it if necessary.
5486 const alignment = Builder.Alignment.fromByteUnits(@max(5119 const alignment = Builder.Alignment.fromByteUnits(return_type.abiAlignment(mod));
5487 o.target_data.abiAlignmentOfType(abi_ret_ty.toLlvm(&o.builder)),5120 if (o.builder.useLibLlvm())
5488 return_type.abiAlignment(mod),5121 assert(o.target_data.abiSizeOfType(abi_ret_ty.toLlvm(&o.builder)) >=
5489 ));5122 o.target_data.abiSizeOfType(llvm_ret_ty.toLlvm(&o.builder)));
5490 assert(o.target_data.abiSizeOfType(abi_ret_ty.toLlvm(&o.builder)) >=
5491 o.target_data.abiSizeOfType(llvm_ret_ty.toLlvm(&o.builder)));
5492 const rp = try self.buildAlloca(abi_ret_ty, alignment);5123 const rp = try self.buildAlloca(abi_ret_ty, alignment);
5493 _ = try self.wip.store(.normal, call, rp, alignment);5124 _ = try self.wip.store(.normal, call, rp, alignment);
5494 return if (isByRef(return_type, mod))5125 return if (isByRef(return_type, mod))
...@@ -5645,22 +5276,7 @@ pub const FuncGen = struct {...@@ -5645,22 +5276,7 @@ pub const FuncGen = struct {
5645 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));5276 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
5646 const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);5277 const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
56475278
5648 const llvm_fn_name = "llvm.va_copy";5279 _ = try self.wip.callIntrinsic(.normal, .none, .va_copy, &.{}, &.{ dest_list, src_list }, "");
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
5664 return if (isByRef(va_list_ty, mod))5280 return if (isByRef(va_list_ty, mod))
5665 dest_list5281 dest_list
5666 else5282 else
...@@ -5668,25 +5284,10 @@ pub const FuncGen = struct {...@@ -5668,25 +5284,10 @@ pub const FuncGen = struct {
5668 }5284 }
56695285
5670 fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {5286 fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
5671 const o = self.dg.object;
5672 const un_op = self.air.instructions.items(.data)[inst].un_op;5287 const un_op = self.air.instructions.items(.data)[inst].un_op;
5673 const list = try self.resolveInst(un_op);5288 const src_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));
56795289
5680 const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)};5290 _ = try self.wip.callIntrinsic(.normal, .none, .va_end, &.{}, &.{src_list}, "");
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);
5690 return .none;5291 return .none;
5691 }5292 }
56925293
...@@ -5697,44 +5298,30 @@ pub const FuncGen = struct {...@@ -5697,44 +5298,30 @@ pub const FuncGen = struct {
5697 const llvm_va_list_ty = try o.lowerType(va_list_ty);5298 const llvm_va_list_ty = try o.lowerType(va_list_ty);
56985299
5699 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));5300 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
5700 const list = try self.buildAlloca(llvm_va_list_ty, result_alignment);5301 const dest_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);
57175302
5303 _ = try self.wip.callIntrinsic(.normal, .none, .va_start, &.{}, &.{dest_list}, "");
5718 return if (isByRef(va_list_ty, mod))5304 return if (isByRef(va_list_ty, mod))
5719 list5305 dest_list
5720 else5306 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, "");
5722 }5308 }
57235309
5724 fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !Builder.Value {5310 fn airCmp(
5725 self.builder.setFastMath(want_fast_math);5311 self: *FuncGen,
57265312 inst: Air.Inst.Index,
5313 op: math.CompareOperator,
5314 fast: Builder.FastMathKind,
5315 ) !Builder.Value {
5727 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5316 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5728 const lhs = try self.resolveInst(bin_op.lhs);5317 const lhs = try self.resolveInst(bin_op.lhs);
5729 const rhs = try self.resolveInst(bin_op.rhs);5318 const rhs = try self.resolveInst(bin_op.rhs);
5730 const operand_ty = self.typeOf(bin_op.lhs);5319 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);
5733 }5322 }
57345323
5735 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {5324 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
5736 self.builder.setFastMath(want_fast_math);
5737
5738 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5325 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5739 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;5326 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
57405327
...@@ -5743,7 +5330,7 @@ pub const FuncGen = struct {...@@ -5743,7 +5330,7 @@ pub const FuncGen = struct {
5743 const vec_ty = self.typeOf(extra.lhs);5330 const vec_ty = self.typeOf(extra.lhs);
5744 const cmp_op = extra.compareOperator();5331 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);
5747 }5334 }
57485335
5749 fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {5336 fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -5764,10 +5351,11 @@ pub const FuncGen = struct {...@@ -5764,10 +5351,11 @@ pub const FuncGen = struct {
57645351
5765 fn cmp(5352 fn cmp(
5766 self: *FuncGen,5353 self: *FuncGen,
5354 fast: Builder.FastMathKind,
5355 op: math.CompareOperator,
5356 operand_ty: Type,
5767 lhs: Builder.Value,5357 lhs: Builder.Value,
5768 rhs: Builder.Value,5358 rhs: Builder.Value,
5769 operand_ty: Type,
5770 op: math.CompareOperator,
5771 ) Allocator.Error!Builder.Value {5359 ) Allocator.Error!Builder.Value {
5772 const o = self.dg.object;5360 const o = self.dg.object;
5773 const mod = o.module;5361 const mod = o.module;
...@@ -5819,13 +5407,13 @@ pub const FuncGen = struct {...@@ -5819,13 +5407,13 @@ pub const FuncGen = struct {
5819 self.wip.cursor = .{ .block = both_pl_block };5407 self.wip.cursor = .{ .block = both_pl_block };
5820 const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty, true);5408 const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty, true);
5821 const rhs_payload = try self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty, true);5409 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);
5823 _ = try self.wip.br(end_block);5411 _ = try self.wip.br(end_block);
5824 const both_pl_block_end = self.wip.cursor.block;5412 const both_pl_block_end = self.wip.cursor.block;
58255413
5826 self.wip.cursor = .{ .block = end_block };5414 self.wip.cursor = .{ .block = end_block };
5827 const llvm_i1_0 = try o.builder.intValue(.i1, 0);5415 const llvm_i1_0 = Builder.Value.false;
5828 const llvm_i1_1 = try o.builder.intValue(.i1, 1);5416 const llvm_i1_1 = Builder.Value.true;
5829 const incoming_values: [3]Builder.Value = .{5417 const incoming_values: [3]Builder.Value = .{
5830 switch (op) {5418 switch (op) {
5831 .eq => llvm_i1_1,5419 .eq => llvm_i1_1,
...@@ -5848,7 +5436,7 @@ pub const FuncGen = struct {...@@ -5848,7 +5436,7 @@ pub const FuncGen = struct {
5848 );5436 );
5849 return phi.toValue();5437 return phi.toValue();
5850 },5438 },
5851 .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }),5439 .Float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }),
5852 else => unreachable,5440 else => unreachable,
5853 };5441 };
5854 const is_signed = int_ty.isSignedInt(mod);5442 const is_signed = int_ty.isSignedInt(mod);
...@@ -6046,7 +5634,7 @@ pub const FuncGen = struct {...@@ -6046,7 +5634,7 @@ pub const FuncGen = struct {
6046 if (can_elide_load)5634 if (can_elide_load)
6047 return payload_ptr;5635 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);
6050 }5638 }
6051 const load_ty = err_union_llvm_ty.structFields(&o.builder)[offset];5639 const load_ty = err_union_llvm_ty.structFields(&o.builder)[offset];
6052 return fg.wip.load(.normal, load_ty, payload_ptr, payload_alignment, "");5640 return fg.wip.load(.normal, load_ty, payload_ptr, payload_alignment, "");
...@@ -6219,8 +5807,12 @@ pub const FuncGen = struct {...@@ -6219,8 +5807,12 @@ pub const FuncGen = struct {
6219 );5807 );
6220 }5808 }
62215809
6222 fn airIntFromFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {5810 fn airIntFromFloat(
6223 self.builder.setFastMath(want_fast_math);5811 self: *FuncGen,
5812 inst: Air.Inst.Index,
5813 fast: Builder.FastMathKind,
5814 ) !Builder.Value {
5815 _ = fast;
62245816
6225 const o = self.dg.object;5817 const o = self.dg.object;
6226 const mod = o.module;5818 const mod = o.module;
...@@ -6345,7 +5937,7 @@ pub const FuncGen = struct {...@@ -6345,7 +5937,7 @@ pub const FuncGen = struct {
6345 return ptr;5937 return ptr;
63465938
6347 const elem_alignment = Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod));5939 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);
6349 }5941 }
63505942
6351 return self.load(ptr, slice_ty);5943 return self.load(ptr, slice_ty);
...@@ -6385,7 +5977,7 @@ pub const FuncGen = struct {...@@ -6385,7 +5977,7 @@ pub const FuncGen = struct {
6385 try self.wip.gep(.inbounds, array_llvm_ty, array_llvm_val, &indices, "");5977 try self.wip.gep(.inbounds, array_llvm_ty, array_llvm_val, &indices, "");
6386 if (canElideLoad(self, body_tail)) return elem_ptr;5978 if (canElideLoad(self, body_tail)) return elem_ptr;
6387 const elem_alignment = Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod));5979 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);
6389 } else {5981 } else {
6390 const elem_llvm_ty = try o.lowerType(elem_ty);5982 const elem_llvm_ty = try o.lowerType(elem_ty);
6391 if (Air.refToIndex(bin_op.lhs)) |lhs_index| {5983 if (Air.refToIndex(bin_op.lhs)) |lhs_index| {
...@@ -6445,7 +6037,7 @@ pub const FuncGen = struct {...@@ -6445,7 +6037,7 @@ pub const FuncGen = struct {
6445 if (isByRef(elem_ty, mod)) {6037 if (isByRef(elem_ty, mod)) {
6446 if (self.canElideLoad(body_tail)) return ptr;6038 if (self.canElideLoad(body_tail)) return ptr;
6447 const elem_alignment = Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod));6039 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);
6449 }6041 }
64506042
6451 return self.load(ptr, ptr_ty);6043 return self.load(ptr, ptr_ty);
...@@ -6467,7 +6059,7 @@ pub const FuncGen = struct {...@@ -6467,7 +6059,7 @@ pub const FuncGen = struct {
6467 if (elem_ptr.ptrInfo(mod).flags.vector_index != .none) return base_ptr;6059 if (elem_ptr.ptrInfo(mod).flags.vector_index != .none) return base_ptr;
64686060
6469 const llvm_elem_ty = try o.lowerPtrElemTy(elem_ty);6061 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))
6471 // If this is a single-item pointer to an array, we need another index in the GEP.6063 // If this is a single-item pointer to an array, we need another index in the GEP.
6472 &.{ try o.builder.intValue(try o.lowerType(Type.usize), 0), rhs }6064 &.{ try o.builder.intValue(try o.lowerType(Type.usize), 0), rhs }
6473 else6065 else
...@@ -6575,7 +6167,7 @@ pub const FuncGen = struct {...@@ -6575,7 +6167,7 @@ pub const FuncGen = struct {
65756167
6576 assert(llvm_field.alignment != 0);6168 assert(llvm_field.alignment != 0);
6577 const field_alignment = Builder.Alignment.fromByteUnits(llvm_field.alignment);6169 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);
6579 } else {6171 } else {
6580 return self.load(field_ptr, field_ptr_ty);6172 return self.load(field_ptr, field_ptr_ty);
6581 }6173 }
...@@ -6590,7 +6182,7 @@ pub const FuncGen = struct {...@@ -6590,7 +6182,7 @@ pub const FuncGen = struct {
6590 const payload_alignment = Builder.Alignment.fromByteUnits(layout.payload_align);6182 const payload_alignment = Builder.Alignment.fromByteUnits(layout.payload_align);
6591 if (isByRef(field_ty, mod)) {6183 if (isByRef(field_ty, mod)) {
6592 if (canElideLoad(self, body_tail)) return field_ptr;6184 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);
6594 } else {6186 } else {
6595 return self.wip.load(.normal, llvm_field_ty, field_ptr, payload_alignment, "");6187 return self.wip.load(.normal, llvm_field_ty, field_ptr, payload_alignment, "");
6596 }6188 }
...@@ -6638,6 +6230,8 @@ pub const FuncGen = struct {...@@ -6638,6 +6230,8 @@ pub const FuncGen = struct {
6638 }6230 }
66396231
6640 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6232 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6233 if (!self.dg.object.builder.useLibLlvm()) return .none;
6234
6641 const di_scope = self.di_scope orelse return .none;6235 const di_scope = self.di_scope orelse return .none;
6642 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;6236 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
6643 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);6237 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);
...@@ -6646,12 +6240,19 @@ pub const FuncGen = struct {...@@ -6646,12 +6240,19 @@ pub const FuncGen = struct {
6646 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc6240 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc
6647 else6241 else
6648 null;6242 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 );
6650 return .none;6249 return .none;
6651 }6250 }
66526251
6653 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6252 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6654 const o = self.dg.object;6253 const o = self.dg.object;
6254 if (!o.builder.useLibLlvm()) return .none;
6255
6655 const dib = o.di_builder orelse return .none;6256 const dib = o.di_builder orelse return .none;
6656 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;6257 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
66576258
...@@ -6662,7 +6263,7 @@ pub const FuncGen = struct {...@@ -6662,7 +6263,7 @@ pub const FuncGen = struct {
6662 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);6263 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
6663 self.di_file = di_file;6264 self.di_file = di_file;
6664 const line_number = decl.src_line + 1;6265 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
6667 try self.dbg_inlined.append(self.gpa, .{6268 try self.dbg_inlined.append(self.gpa, .{
6668 .loc = @ptrCast(cur_debug_location),6269 .loc = @ptrCast(cur_debug_location),
...@@ -6710,6 +6311,8 @@ pub const FuncGen = struct {...@@ -6710,6 +6311,8 @@ pub const FuncGen = struct {
67106311
6711 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6312 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6712 const o = self.dg.object;6313 const o = self.dg.object;
6314 if (!o.builder.useLibLlvm()) return .none;
6315
6713 if (o.di_builder == null) return .none;6316 if (o.di_builder == null) return .none;
6714 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;6317 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
67156318
...@@ -6725,6 +6328,8 @@ pub const FuncGen = struct {...@@ -6725,6 +6328,8 @@ pub const FuncGen = struct {
67256328
6726 fn airDbgBlockBegin(self: *FuncGen) !Builder.Value {6329 fn airDbgBlockBegin(self: *FuncGen) !Builder.Value {
6727 const o = self.dg.object;6330 const o = self.dg.object;
6331 if (!o.builder.useLibLlvm()) return .none;
6332
6728 const dib = o.di_builder orelse return .none;6333 const dib = o.di_builder orelse return .none;
6729 const old_scope = self.di_scope.?;6334 const old_scope = self.di_scope.?;
6730 try self.dbg_block_stack.append(self.gpa, old_scope);6335 try self.dbg_block_stack.append(self.gpa, old_scope);
...@@ -6735,6 +6340,8 @@ pub const FuncGen = struct {...@@ -6735,6 +6340,8 @@ pub const FuncGen = struct {
67356340
6736 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {6341 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {
6737 const o = self.dg.object;6342 const o = self.dg.object;
6343 if (!o.builder.useLibLlvm()) return .none;
6344
6738 if (o.di_builder == null) return .none;6345 if (o.di_builder == null) return .none;
6739 self.di_scope = self.dbg_block_stack.pop();6346 self.di_scope = self.dbg_block_stack.pop();
6740 return .none;6347 return .none;
...@@ -6742,6 +6349,8 @@ pub const FuncGen = struct {...@@ -6742,6 +6349,8 @@ pub const FuncGen = struct {
67426349
6743 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6350 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6744 const o = self.dg.object;6351 const o = self.dg.object;
6352 if (!o.builder.useLibLlvm()) return .none;
6353
6745 const mod = o.module;6354 const mod = o.module;
6746 const dib = o.di_builder orelse return .none;6355 const dib = o.di_builder orelse return .none;
6747 const pl_op = self.air.instructions.items(.data)[inst].pl_op;6356 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
...@@ -6770,6 +6379,8 @@ pub const FuncGen = struct {...@@ -6770,6 +6379,8 @@ pub const FuncGen = struct {
67706379
6771 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6380 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6772 const o = self.dg.object;6381 const o = self.dg.object;
6382 if (!o.builder.useLibLlvm()) return .none;
6383
6773 const dib = o.di_builder orelse return .none;6384 const dib = o.di_builder orelse return .none;
6774 const pl_op = self.air.instructions.items(.data)[inst].pl_op;6385 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
6775 const operand = try self.resolveInst(pl_op.operand);6386 const operand = try self.resolveInst(pl_op.operand);
...@@ -7374,7 +6985,7 @@ pub const FuncGen = struct {...@@ -7374,7 +6985,7 @@ pub const FuncGen = struct {
7374 const payload_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");6985 const payload_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");
7375 if (isByRef(payload_ty, mod)) {6986 if (isByRef(payload_ty, mod)) {
7376 if (self.canElideLoad(body_tail)) return payload_ptr;6987 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);
7378 }6989 }
7379 const payload_llvm_ty = err_union_llvm_ty.structFields(&o.builder)[offset];6990 const payload_llvm_ty = err_union_llvm_ty.structFields(&o.builder)[offset];
7380 return self.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, "");6991 return self.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, "");
...@@ -7570,40 +7181,18 @@ pub const FuncGen = struct {...@@ -7570,40 +7181,18 @@ pub const FuncGen = struct {
7570 const o = self.dg.object;7181 const o = self.dg.object;
7571 const pl_op = self.air.instructions.items(.data)[inst].pl_op;7182 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
7572 const index = pl_op.payload;7183 const index = pl_op.payload;
7573 const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.size", &.{.i32});7184 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{.i32}, &.{
7574 const args: [1]*llvm.Value = .{7185 try o.builder.intValue(.i32, index),
7575 (try o.builder.intConst(.i32, index)).toLlvm(&o.builder),7186 }, "");
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);
7586 }7187 }
75877188
7588 fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {7189 fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
7589 const o = self.dg.object;7190 const o = self.dg.object;
7590 const pl_op = self.air.instructions.items(.data)[inst].pl_op;7191 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
7591 const index = pl_op.payload;7192 const index = pl_op.payload;
7592 const operand = try self.resolveInst(pl_op.operand);7193 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{.i32}, &.{
7593 const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.grow", &.{.i32});7194 try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),
7594 const args: [2]*llvm.Value = .{7195 }, "");
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);
7607 }7196 }
76087197
7609 fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {7198 fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -7617,13 +7206,11 @@ pub const FuncGen = struct {...@@ -7617,13 +7206,11 @@ pub const FuncGen = struct {
7617 const index = try self.resolveInst(extra.lhs);7206 const index = try self.resolveInst(extra.lhs);
7618 const operand = try self.resolveInst(extra.rhs);7207 const operand = try self.resolveInst(extra.rhs);
76197208
7620 const kind: Builder.MemoryAccessKind = switch (vector_ptr_ty.isVolatilePtr(mod)) {7209 const access_kind: Builder.MemoryAccessKind =
7621 false => .normal,7210 if (vector_ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal;
7622 true => .@"volatile",
7623 };
7624 const elem_llvm_ty = try o.lowerType(vector_ptr_ty.childType(mod));7211 const elem_llvm_ty = try o.lowerType(vector_ptr_ty.childType(mod));
7625 const alignment = Builder.Alignment.fromByteUnits(vector_ptr_ty.ptrAlignment(mod));7212 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
7628 const new_vector = try self.wip.insertElement(loaded, operand, index, "");7215 const new_vector = try self.wip.insertElement(loaded, operand, index, "");
7629 _ = try self.store(vector_ptr, vector_ptr_ty, new_vector, .none);7216 _ = try self.store(vector_ptr, vector_ptr_ty, new_vector, .none);
...@@ -7636,13 +7223,18 @@ pub const FuncGen = struct {...@@ -7636,13 +7223,18 @@ pub const FuncGen = struct {
7636 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7223 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7637 const lhs = try self.resolveInst(bin_op.lhs);7224 const lhs = try self.resolveInst(bin_op.lhs);
7638 const rhs = try self.resolveInst(bin_op.rhs);7225 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 });7229 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, .normal, inst_ty, 2, .{ lhs, rhs });
7642 return self.wip.bin(if (scalar_ty.isSignedInt(mod))7230 return self.wip.callIntrinsic(
7643 .@"llvm.smin."7231 .normal,
7644 else7232 .none,
7645 .@"llvm.umin.", lhs, rhs, "");7233 if (scalar_ty.isSignedInt(mod)) .smin else .umin,
7234 &.{try o.lowerType(inst_ty)},
7235 &.{ lhs, rhs },
7236 "",
7237 );
7646 }7238 }
76477239
7648 fn airMax(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {7240 fn airMax(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -7651,13 +7243,18 @@ pub const FuncGen = struct {...@@ -7651,13 +7243,18 @@ pub const FuncGen = struct {
7651 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7243 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7652 const lhs = try self.resolveInst(bin_op.lhs);7244 const lhs = try self.resolveInst(bin_op.lhs);
7653 const rhs = try self.resolveInst(bin_op.rhs);7245 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 });7249 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, .normal, inst_ty, 2, .{ lhs, rhs });
7657 return self.wip.bin(if (scalar_ty.isSignedInt(mod))7250 return self.wip.callIntrinsic(
7658 .@"llvm.smax."7251 .normal,
7659 else7252 .none,
7660 .@"llvm.umax.", lhs, rhs, "");7253 if (scalar_ty.isSignedInt(mod)) .smax else .umax,
7254 &.{try o.lowerType(inst_ty)},
7255 &.{ lhs, rhs },
7256 "",
7257 );
7661 }7258 }
76627259
7663 fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {7260 fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -7670,9 +7267,7 @@ pub const FuncGen = struct {...@@ -7670,9 +7267,7 @@ pub const FuncGen = struct {
7670 return self.wip.buildAggregate(try o.lowerType(inst_ty), &.{ ptr, len }, "");7267 return self.wip.buildAggregate(try o.lowerType(inst_ty), &.{ ptr, len }, "");
7671 }7268 }
76727269
7673 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {7270 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
7674 self.builder.setFastMath(want_fast_math);
7675
7676 const o = self.dg.object;7271 const o = self.dg.object;
7677 const mod = o.module;7272 const mod = o.module;
7678 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7273 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7681,15 +7276,15 @@ pub const FuncGen = struct {...@@ -7681,15 +7276,15 @@ pub const FuncGen = struct {
7681 const inst_ty = self.typeOfIndex(inst);7276 const inst_ty = self.typeOfIndex(inst);
7682 const scalar_ty = inst_ty.scalarType(mod);7277 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 });
7685 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"add nsw" else .@"add nuw", lhs, rhs, "");7280 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"add nsw" else .@"add nuw", lhs, rhs, "");
7686 }7281 }
76877282
7688 fn airSafeArithmetic(7283 fn airSafeArithmetic(
7689 fg: *FuncGen,7284 fg: *FuncGen,
7690 inst: Air.Inst.Index,7285 inst: Air.Inst.Index,
7691 signed_intrinsic: []const u8,7286 signed_intrinsic: Builder.Intrinsic,
7692 unsigned_intrinsic: []const u8,7287 unsigned_intrinsic: Builder.Intrinsic,
7693 ) !Builder.Value {7288 ) !Builder.Value {
7694 const o = fg.dg.object;7289 const o = fg.dg.object;
7695 const mod = o.module;7290 const mod = o.module;
...@@ -7699,46 +7294,35 @@ pub const FuncGen = struct {...@@ -7699,46 +7294,35 @@ pub const FuncGen = struct {
7699 const rhs = try fg.resolveInst(bin_op.rhs);7294 const rhs = try fg.resolveInst(bin_op.rhs);
7700 const inst_ty = fg.typeOfIndex(inst);7295 const inst_ty = fg.typeOfIndex(inst);
7701 const scalar_ty = inst_ty.scalarType(mod);7296 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)) {7298 const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
7705 true => signed_intrinsic,
7706 false => unsigned_intrinsic,
7707 };
7708 const llvm_inst_ty = try o.lowerType(inst_ty);7299 const llvm_inst_ty = try o.lowerType(inst_ty);
7709 const llvm_ret_ty = try o.builder.structType(.normal, &.{7300 const results =
7710 llvm_inst_ty,7301 try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, "");
7711 try llvm_inst_ty.changeScalar(.i1, &o.builder),7302
7712 });7303 const overflow_bits = try fg.wip.extractValue(results, &.{1}, "");
7713 const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_inst_ty, llvm_inst_ty }, .normal);7304 const overflow_bits_ty = overflow_bits.typeOfWip(&fg.wip);
7714 const llvm_fn = try fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty});7305 const overflow_bit = if (overflow_bits_ty.isVector(&o.builder))
7715 const result_struct = (try fg.wip.unimplemented(llvm_ret_ty, "")).finish(fg.builder.buildCallOld(7306 try fg.wip.callIntrinsic(
7716 llvm_fn_ty.toLlvm(&o.builder),7307 .normal,
7717 llvm_fn,7308 .none,
7718 &[_]*llvm.Value{ lhs.toLlvm(&fg.wip), rhs.toLlvm(&fg.wip) },7309 .@"vector.reduce.or",
7719 2,7310 &.{overflow_bits_ty},
7720 .Fast,7311 &.{overflow_bits},
7721 .Auto,7312 "",
7722 "",7313 )
7723 ), &fg.wip);7314 else
7724 const overflow_bit = try fg.wip.extractValue(result_struct, &.{1}, "");7315 overflow_bits;
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 };
77327316
7733 const fail_block = try fg.wip.block(1, "OverflowFail");7317 const fail_block = try fg.wip.block(1, "OverflowFail");
7734 const ok_block = try fg.wip.block(1, "OverflowOk");7318 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
7737 fg.wip.cursor = .{ .block = fail_block };7321 fg.wip.cursor = .{ .block = fail_block };
7738 try fg.buildSimplePanic(.integer_overflow);7322 try fg.buildSimplePanic(.integer_overflow);
77397323
7740 fg.wip.cursor = .{ .block = ok_block };7324 fg.wip.cursor = .{ .block = ok_block };
7741 return fg.wip.extractValue(result_struct, &.{0}, "");7325 return fg.wip.extractValue(results, &.{0}, "");
7742 }7326 }
77437327
7744 fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {7328 fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -7759,15 +7343,17 @@ pub const FuncGen = struct {...@@ -7759,15 +7343,17 @@ pub const FuncGen = struct {
7759 const scalar_ty = inst_ty.scalarType(mod);7343 const scalar_ty = inst_ty.scalarType(mod);
77607344
7761 if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});7345 if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});
7762 return self.wip.bin(if (scalar_ty.isSignedInt(mod))7346 return self.wip.callIntrinsic(
7763 .@"llvm.sadd.sat."7347 .normal,
7764 else7348 .none,
7765 .@"llvm.uadd.sat.", lhs, rhs, "");7349 if (scalar_ty.isSignedInt(mod)) .@"sadd.sat" else .@"uadd.sat",
7350 &.{try o.lowerType(inst_ty)},
7351 &.{ lhs, rhs },
7352 "",
7353 );
7766 }7354 }
77677355
7768 fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {7356 fn airSub(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
7769 self.builder.setFastMath(want_fast_math);
7770
7771 const o = self.dg.object;7357 const o = self.dg.object;
7772 const mod = o.module;7358 const mod = o.module;
7773 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7359 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7776,7 +7362,7 @@ pub const FuncGen = struct {...@@ -7776,7 +7362,7 @@ pub const FuncGen = struct {
7776 const inst_ty = self.typeOfIndex(inst);7362 const inst_ty = self.typeOfIndex(inst);
7777 const scalar_ty = inst_ty.scalarType(mod);7363 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 });
7780 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"sub nsw" else .@"sub nuw", lhs, rhs, "");7366 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"sub nsw" else .@"sub nuw", lhs, rhs, "");
7781 }7367 }
77827368
...@@ -7798,15 +7384,17 @@ pub const FuncGen = struct {...@@ -7798,15 +7384,17 @@ pub const FuncGen = struct {
7798 const scalar_ty = inst_ty.scalarType(mod);7384 const scalar_ty = inst_ty.scalarType(mod);
77997385
7800 if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});7386 if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});
7801 return self.wip.bin(if (scalar_ty.isSignedInt(mod))7387 return self.wip.callIntrinsic(
7802 .@"llvm.ssub.sat."7388 .normal,
7803 else7389 .none,
7804 .@"llvm.usub.sat.", lhs, rhs, "");7390 if (scalar_ty.isSignedInt(mod)) .@"ssub.sat" else .@"usub.sat",
7391 &.{try o.lowerType(inst_ty)},
7392 &.{ lhs, rhs },
7393 "",
7394 );
7805 }7395 }
78067396
7807 fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {7397 fn airMul(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
7808 self.builder.setFastMath(want_fast_math);
7809
7810 const o = self.dg.object;7398 const o = self.dg.object;
7811 const mod = o.module;7399 const mod = o.module;
7812 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7400 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7815,7 +7403,7 @@ pub const FuncGen = struct {...@@ -7815,7 +7403,7 @@ pub const FuncGen = struct {
7815 const inst_ty = self.typeOfIndex(inst);7403 const inst_ty = self.typeOfIndex(inst);
7816 const scalar_ty = inst_ty.scalarType(mod);7404 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 });
7819 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"mul nsw" else .@"mul nuw", lhs, rhs, "");7407 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"mul nsw" else .@"mul nuw", lhs, rhs, "");
7820 }7408 }
78217409
...@@ -7837,26 +7425,26 @@ pub const FuncGen = struct {...@@ -7837,26 +7425,26 @@ pub const FuncGen = struct {
7837 const scalar_ty = inst_ty.scalarType(mod);7425 const scalar_ty = inst_ty.scalarType(mod);
78387426
7839 if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});7427 if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});
7840 return self.wip.bin(if (scalar_ty.isSignedInt(mod))7428 return self.wip.callIntrinsic(
7841 .@"llvm.smul.fix.sat."7429 .normal,
7842 else7430 .none,
7843 .@"llvm.umul.fix.sat.", lhs, rhs, "");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 );
7844 }7436 }
78457437
7846 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {7438 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
7847 self.builder.setFastMath(want_fast_math);
7848
7849 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7439 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7850 const lhs = try self.resolveInst(bin_op.lhs);7440 const lhs = try self.resolveInst(bin_op.lhs);
7851 const rhs = try self.resolveInst(bin_op.rhs);7441 const rhs = try self.resolveInst(bin_op.rhs);
7852 const inst_ty = self.typeOfIndex(inst);7442 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 });
7855 }7445 }
78567446
7857 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {7447 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
7858 self.builder.setFastMath(want_fast_math);
7859
7860 const o = self.dg.object;7448 const o = self.dg.object;
7861 const mod = o.module;7449 const mod = o.module;
7862 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7450 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7866,15 +7454,13 @@ pub const FuncGen = struct {...@@ -7866,15 +7454,13 @@ pub const FuncGen = struct {
7866 const scalar_ty = inst_ty.scalarType(mod);7454 const scalar_ty = inst_ty.scalarType(mod);
78677455
7868 if (scalar_ty.isRuntimeFloat()) {7456 if (scalar_ty.isRuntimeFloat()) {
7869 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7457 const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7870 return self.buildFloatOp(.trunc, inst_ty, 1, .{result});7458 return self.buildFloatOp(.trunc, fast, inst_ty, 1, .{result});
7871 }7459 }
7872 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .sdiv else .udiv, lhs, rhs, "");7460 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .sdiv else .udiv, lhs, rhs, "");
7873 }7461 }
78747462
7875 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {7463 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
7876 self.builder.setFastMath(want_fast_math);
7877
7878 const o = self.dg.object;7464 const o = self.dg.object;
7879 const mod = o.module;7465 const mod = o.module;
7880 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7466 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7884,8 +7470,8 @@ pub const FuncGen = struct {...@@ -7884,8 +7470,8 @@ pub const FuncGen = struct {
7884 const scalar_ty = inst_ty.scalarType(mod);7470 const scalar_ty = inst_ty.scalarType(mod);
78857471
7886 if (scalar_ty.isRuntimeFloat()) {7472 if (scalar_ty.isRuntimeFloat()) {
7887 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7473 const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7888 return self.buildFloatOp(.floor, inst_ty, 1, .{result});7474 return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result});
7889 }7475 }
7890 if (scalar_ty.isSignedInt(mod)) {7476 if (scalar_ty.isSignedInt(mod)) {
7891 const inst_llvm_ty = try o.lowerType(inst_ty);7477 const inst_llvm_ty = try o.lowerType(inst_ty);
...@@ -7900,15 +7486,13 @@ pub const FuncGen = struct {...@@ -7900,15 +7486,13 @@ pub const FuncGen = struct {
7900 const div_sign_mask = try self.wip.bin(.ashr, div_sign, bit_size_minus_one, "");7486 const div_sign_mask = try self.wip.bin(.ashr, div_sign, bit_size_minus_one, "");
7901 const zero = try o.builder.zeroInitValue(inst_llvm_ty);7487 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
7902 const rem_nonzero = try self.wip.icmp(.ne, rem, zero, "");7488 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, "");
7904 return self.wip.bin(.@"add nsw", div, correction, "");7490 return self.wip.bin(.@"add nsw", div, correction, "");
7905 }7491 }
7906 return self.wip.bin(.udiv, lhs, rhs, "");7492 return self.wip.bin(.udiv, lhs, rhs, "");
7907 }7493 }
79087494
7909 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {7495 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
7910 self.builder.setFastMath(want_fast_math);
7911
7912 const o = self.dg.object;7496 const o = self.dg.object;
7913 const mod = o.module;7497 const mod = o.module;
7914 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7498 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7917,16 +7501,16 @@ pub const FuncGen = struct {...@@ -7917,16 +7501,16 @@ pub const FuncGen = struct {
7917 const inst_ty = self.typeOfIndex(inst);7501 const inst_ty = self.typeOfIndex(inst);
7918 const scalar_ty = inst_ty.scalarType(mod);7502 const scalar_ty = inst_ty.scalarType(mod);
79197503
7920 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7504 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7921 return self.wip.bin(if (scalar_ty.isSignedInt(mod))7505 return self.wip.bin(
7922 .@"sdiv exact"7506 if (scalar_ty.isSignedInt(mod)) .@"sdiv exact" else .@"udiv exact",
7923 else7507 lhs,
7924 .@"udiv exact", lhs, rhs, "");7508 rhs,
7509 "",
7510 );
7925 }7511 }
79267512
7927 fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {7513 fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
7928 self.builder.setFastMath(want_fast_math);
7929
7930 const o = self.dg.object;7514 const o = self.dg.object;
7931 const mod = o.module;7515 const mod = o.module;
7932 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7516 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7935,16 +7519,15 @@ pub const FuncGen = struct {...@@ -7935,16 +7519,15 @@ pub const FuncGen = struct {
7935 const inst_ty = self.typeOfIndex(inst);7519 const inst_ty = self.typeOfIndex(inst);
7936 const scalar_ty = inst_ty.scalarType(mod);7520 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 });
7939 return self.wip.bin(if (scalar_ty.isSignedInt(mod))7524 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
7940 .srem7525 .srem
7941 else7526 else
7942 .urem, lhs, rhs, "");7527 .urem, lhs, rhs, "");
7943 }7528 }
79447529
7945 fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {7530 fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
7946 self.builder.setFastMath(want_fast_math);
7947
7948 const o = self.dg.object;7531 const o = self.dg.object;
7949 const mod = o.module;7532 const mod = o.module;
7950 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7533 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7955,12 +7538,12 @@ pub const FuncGen = struct {...@@ -7955,12 +7538,12 @@ pub const FuncGen = struct {
7955 const scalar_ty = inst_ty.scalarType(mod);7538 const scalar_ty = inst_ty.scalarType(mod);
79567539
7957 if (scalar_ty.isRuntimeFloat()) {7540 if (scalar_ty.isRuntimeFloat()) {
7958 const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });7541 const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs });
7959 const b = try self.buildFloatOp(.add, inst_ty, 2, .{ a, rhs });7542 const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs });
7960 const c = try self.buildFloatOp(.fmod, inst_ty, 2, .{ b, rhs });7543 const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs });
7961 const zero = try o.builder.zeroInitValue(inst_llvm_ty);7544 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
7962 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero });7545 const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero });
7963 return self.wip.select(ltz, c, a, "");7546 return self.wip.select(fast, ltz, c, a, "");
7964 }7547 }
7965 if (scalar_ty.isSignedInt(mod)) {7548 if (scalar_ty.isSignedInt(mod)) {
7966 const bit_size_minus_one = try o.builder.splatValue(inst_llvm_ty, try o.builder.intConst(7549 const bit_size_minus_one = try o.builder.splatValue(inst_llvm_ty, try o.builder.intConst(
...@@ -7974,7 +7557,7 @@ pub const FuncGen = struct {...@@ -7974,7 +7557,7 @@ pub const FuncGen = struct {
7974 const rhs_masked = try self.wip.bin(.@"and", rhs, div_sign_mask, "");7557 const rhs_masked = try self.wip.bin(.@"and", rhs, div_sign_mask, "");
7975 const zero = try o.builder.zeroInitValue(inst_llvm_ty);7558 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
7976 const rem_nonzero = try self.wip.icmp(.ne, rem, zero, "");7559 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, "");
7978 return self.wip.bin(.@"add nsw", rem, correction, "");7561 return self.wip.bin(.@"add nsw", rem, correction, "");
7979 }7562 }
7980 return self.wip.bin(.urem, lhs, rhs, "");7563 return self.wip.bin(.urem, lhs, rhs, "");
...@@ -8028,8 +7611,8 @@ pub const FuncGen = struct {...@@ -8028,8 +7611,8 @@ pub const FuncGen = struct {
8028 fn airOverflow(7611 fn airOverflow(
8029 self: *FuncGen,7612 self: *FuncGen,
8030 inst: Air.Inst.Index,7613 inst: Air.Inst.Index,
8031 signed_intrinsic: []const u8,7614 signed_intrinsic: Builder.Intrinsic,
8032 unsigned_intrinsic: []const u8,7615 unsigned_intrinsic: Builder.Intrinsic,
8033 ) !Builder.Value {7616 ) !Builder.Value {
8034 const o = self.dg.object;7617 const o = self.dg.object;
8035 const mod = o.module;7618 const mod = o.module;
...@@ -8041,48 +7624,30 @@ pub const FuncGen = struct {...@@ -8041,48 +7624,30 @@ pub const FuncGen = struct {
80417624
8042 const lhs_ty = self.typeOf(extra.lhs);7625 const lhs_ty = self.typeOf(extra.lhs);
8043 const scalar_ty = lhs_ty.scalarType(mod);7626 const scalar_ty = lhs_ty.scalarType(mod);
8044 const dest_ty = self.typeOfIndex(inst);7627 const inst_ty = self.typeOfIndex(inst);
8045
8046 const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
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);
8049 const llvm_lhs_ty = try o.lowerType(lhs_ty);7631 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});7635 const result_val = try self.wip.extractValue(results, &.{0}, "");
8052 const llvm_ret_ty = try o.builder.structType(7636 const overflow_bit = try self.wip.extractValue(results, &.{1}, "");
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 );
80697637
8070 const result = try self.wip.extractValue(result_struct, &.{0}, "");7638 const result_index = llvmField(inst_ty, 0, mod).?.index;
8071 const overflow_bit = try self.wip.extractValue(result_struct, &.{1}, "");7639 const overflow_index = llvmField(inst_ty, 1, mod).?.index;
80727640
8073 const result_index = llvmField(dest_ty, 0, mod).?.index;7641 if (isByRef(inst_ty, mod)) {
8074 const overflow_index = llvmField(dest_ty, 1, mod).?.index;7642 const result_alignment = Builder.Alignment.fromByteUnits(inst_ty.abiAlignment(mod));
80757643 const alloca_inst = try self.buildAlloca(llvm_inst_ty, result_alignment);
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);
8079 {7644 {
8080 const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, result_index, "");7645 const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, result_index, "");
8081 _ = try self.wip.store(.normal, result, field_ptr, result_alignment);7646 _ = try self.wip.store(.normal, result_val, field_ptr, result_alignment);
8082 }7647 }
8083 {7648 {
8084 const overflow_alignment = comptime Builder.Alignment.fromByteUnits(1);7649 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, "");
8086 _ = try self.wip.store(.normal, overflow_bit, field_ptr, overflow_alignment);7651 _ = try self.wip.store(.normal, overflow_bit, field_ptr, overflow_alignment);
8087 }7652 }
80887653
...@@ -8090,9 +7655,9 @@ pub const FuncGen = struct {...@@ -8090,9 +7655,9 @@ pub const FuncGen = struct {
8090 }7655 }
80917656
8092 var fields: [2]Builder.Value = undefined;7657 var fields: [2]Builder.Value = undefined;
8093 fields[result_index] = result;7658 fields[result_index] = result_val;
8094 fields[overflow_index] = overflow_bit;7659 fields[overflow_index] = overflow_bit;
8095 return self.wip.buildAggregate(llvm_dest_ty, &fields, "");7660 return self.wip.buildAggregate(llvm_inst_ty, &fields, "");
8096 }7661 }
80977662
8098 fn buildElementwiseCall(7663 fn buildElementwiseCall(
...@@ -8138,30 +7703,20 @@ pub const FuncGen = struct {...@@ -8138,30 +7703,20 @@ pub const FuncGen = struct {
8138 if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) {7703 if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) {
8139 .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function,7704 .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function,
8140 .function => |function| function,7705 .function => |function| function,
8141 else => unreachable,7706 .variable, .replaced => 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()),
8153 };7707 };
81547708 return o.builder.addFunction(
8155 try o.builder.llvm.globals.append(self.gpa, f);7709 try o.builder.fnType(return_type, param_types, .normal),
8156 _ = try o.builder.addGlobal(fn_name, global);7710 fn_name,
8157 try o.builder.functions.append(self.gpa, function);7711 toLlvmAddressSpace(.generic, o.module.getTarget()),
8158 return global.kind.function;7712 );
8159 }7713 }
81607714
8161 /// Creates a floating point comparison by lowering to the appropriate7715 /// Creates a floating point comparison by lowering to the appropriate
8162 /// hardware instruction or softfloat routine for the target7716 /// hardware instruction or softfloat routine for the target
8163 fn buildFloatCmp(7717 fn buildFloatCmp(
8164 self: *FuncGen,7718 self: *FuncGen,
7719 fast: Builder.FastMathKind,
8165 pred: math.CompareOperator,7720 pred: math.CompareOperator,
8166 ty: Type,7721 ty: Type,
8167 params: [2]Builder.Value,7722 params: [2]Builder.Value,
...@@ -8181,7 +7736,7 @@ pub const FuncGen = struct {...@@ -8181,7 +7736,7 @@ pub const FuncGen = struct {
8181 .gt => .ogt,7736 .gt => .ogt,
8182 .gte => .oge,7737 .gte => .oge,
8183 };7738 };
8184 return self.wip.fcmp(cond, params[0], params[1], "");7739 return self.wip.fcmp(fast, cond, params[0], params[1], "");
8185 }7740 }
81867741
8187 const float_bits = scalar_ty.floatBits(target);7742 const float_bits = scalar_ty.floatBits(target);
...@@ -8196,11 +7751,7 @@ pub const FuncGen = struct {...@@ -8196,11 +7751,7 @@ pub const FuncGen = struct {
8196 };7751 };
8197 const fn_name = try o.builder.fmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev });7752 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(7754 const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32);
8200 fn_name,
8201 ([1]Builder.Type{scalar_llvm_ty} ** 2)[0..],
8202 .i32,
8203 );
82047755
8205 const zero = try o.builder.intConst(.i32, 0);7756 const zero = try o.builder.intConst(.i32, 0);
8206 const int_cond: Builder.IntegerCondition = switch (pred) {7757 const int_cond: Builder.IntegerCondition = switch (pred) {
...@@ -8272,6 +7823,7 @@ pub const FuncGen = struct {...@@ -8272,6 +7823,7 @@ pub const FuncGen = struct {
8272 fn buildFloatOp(7823 fn buildFloatOp(
8273 self: *FuncGen,7824 self: *FuncGen,
8274 comptime op: FloatOp,7825 comptime op: FloatOp,
7826 fast: Builder.FastMathKind,
8275 ty: Type,7827 ty: Type,
8276 comptime params_len: usize,7828 comptime params_len: usize,
8277 params: [params_len]Builder.Value,7829 params: [params_len]Builder.Value,
...@@ -8285,27 +7837,59 @@ pub const FuncGen = struct {...@@ -8285,27 +7837,59 @@ pub const FuncGen = struct {
8285 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {7837 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
8286 // Some operations are dedicated LLVM instructions, not available as intrinsics7838 // Some operations are dedicated LLVM instructions, not available as intrinsics
8287 .neg => return self.wip.un(.fneg, params[0], ""),7839 .neg => return self.wip.un(.fneg, params[0], ""),
8288 .add => return self.wip.bin(.fadd, params[0], params[1], ""),7840 .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) {
8289 .sub => return self.wip.bin(.fsub, params[0], params[1], ""),7841 .normal => switch (op) {
8290 .mul => return self.wip.bin(.fmul, params[0], params[1], ""),7842 .add => .fadd,
8291 .div => return self.wip.bin(.fdiv, params[0], params[1], ""),7843 .sub => .fsub,
8292 .fmod => return self.wip.bin(.frem, params[0], params[1], ""),7844 .mul => .fmul,
8293 .fmax => return self.wip.bin(.@"llvm.maxnum.", params[0], params[1], ""),7845 .div => .fdiv,
8294 .fmin => return self.wip.bin(.@"llvm.minnum.", params[0], params[1], ""),7846 .fmod => .frem,
8295 .ceil => return self.wip.un(.@"llvm.ceil.", params[0], ""),7847 else => unreachable,
8296 .cos => return self.wip.un(.@"llvm.cos.", params[0], ""),7848 },
8297 .exp => return self.wip.un(.@"llvm.exp.", params[0], ""),7849 .fast => switch (op) {
8298 .exp2 => return self.wip.un(.@"llvm.exp2.", params[0], ""),7850 .add => .@"fadd fast",
8299 .fabs => return self.wip.un(.@"llvm.fabs.", params[0], ""),7851 .sub => .@"fsub fast",
8300 .floor => return self.wip.un(.@"llvm.floor.", params[0], ""),7852 .mul => .@"fmul fast",
8301 .log => return self.wip.un(.@"llvm.log.", params[0], ""),7853 .div => .@"fdiv fast",
8302 .log10 => return self.wip.un(.@"llvm.log10.", params[0], ""),7854 .fmod => .@"frem fast",
8303 .log2 => return self.wip.un(.@"llvm.log2.", params[0], ""),7855 else => unreachable,
8304 .round => return self.wip.un(.@"llvm.round.", params[0], ""),7856 },
8305 .sin => return self.wip.un(.@"llvm.sin.", params[0], ""),7857 }, params[0], params[1], ""),
8306 .sqrt => return self.wip.un(.@"llvm.sqrt.", params[0], ""),7858 .fmax,
8307 .trunc => return self.wip.un(.@"llvm.trunc.", params[0], ""),7859 .fmin,
8308 .fma => return self.wip.fusedMultiplyAdd(params[0], params[1], params[2]),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, ""),
8309 .tan => unreachable,7893 .tan => unreachable,
8310 };7894 };
83117895
...@@ -8362,7 +7946,7 @@ pub const FuncGen = struct {...@@ -8362,7 +7946,7 @@ pub const FuncGen = struct {
8362 }7946 }
83637947
8364 return self.wip.call(7948 return self.wip.call(
8365 .normal,7949 fast.toCallKind(),
8366 .ccc,7950 .ccc,
8367 .none,7951 .none,
8368 libc_fn.typeOf(&o.builder),7952 libc_fn.typeOf(&o.builder),
...@@ -8381,7 +7965,7 @@ pub const FuncGen = struct {...@@ -8381,7 +7965,7 @@ pub const FuncGen = struct {
8381 const addend = try self.resolveInst(pl_op.operand);7965 const addend = try self.resolveInst(pl_op.operand);
83827966
8383 const ty = self.typeOfIndex(inst);7967 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 });
8385 }7969 }
83867970
8387 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {7971 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -8499,28 +8083,32 @@ pub const FuncGen = struct {...@@ -8499,28 +8083,32 @@ pub const FuncGen = struct {
84998083
8500 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");8084 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))8086 const llvm_lhs_ty = try o.lowerType(lhs_ty);
8503 .@"llvm.sshl.sat."8087 const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder);
8504 else8088 const result = try self.wip.callIntrinsic(
8505 .@"llvm.ushl.sat.", lhs, casted_rhs, "");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
8507 // LLVM langref says "If b is (statically or dynamically) equal to or8097 // LLVM langref says "If b is (statically or dynamically) equal to or
8508 // larger than the integer bit width of the arguments, the result is a8098 // larger than the integer bit width of the arguments, the result is a
8509 // poison value."8099 // poison value."
8510 // However Zig semantics says that saturating shift left can never produce8100 // However Zig semantics says that saturating shift left can never produce
8511 // undefined; instead it saturates.8101 // 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);
8514 const bits = try o.builder.splatValue(8102 const bits = try o.builder.splatValue(
8515 lhs_llvm_ty,8103 llvm_lhs_ty,
8516 try o.builder.intConst(lhs_scalar_llvm_ty, lhs_bits),8104 try o.builder.intConst(llvm_lhs_scalar_ty, lhs_bits),
8517 );8105 );
8518 const lhs_max = try o.builder.splatValue(8106 const lhs_max = try o.builder.splatValue(
8519 lhs_llvm_ty,8107 llvm_lhs_ty,
8520 try o.builder.intConst(lhs_scalar_llvm_ty, -1),8108 try o.builder.intConst(llvm_lhs_scalar_ty, -1),
8521 );8109 );
8522 const in_range = try self.wip.icmp(.ult, rhs, bits, "");8110 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, "");
8524 }8112 }
85258113
8526 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value {8114 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value {
...@@ -8873,21 +8461,14 @@ pub const FuncGen = struct {...@@ -8873,21 +8461,14 @@ pub const FuncGen = struct {
8873 // Even if safety is disabled, we still emit a memset to undefined since it conveys8461 // Even if safety is disabled, we still emit a memset to undefined since it conveys
8874 // extra information to LLVM. However, safety makes the difference between using8462 // extra information to LLVM. However, safety makes the difference between using
8875 // 0xaa or actual undefined for the fill byte.8463 // 0xaa or actual undefined for the fill byte.
8876 const fill_byte = if (safety)8464 const len = try o.builder.intValue(try o.lowerType(Type.usize), operand_ty.abiSize(mod));
8877 try o.builder.intConst(.i8, 0xaa)8465 _ = try self.wip.callMemSet(
8878 else8466 dest_ptr,
8879 try o.builder.undefConst(.i8);8467 Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)),
8880 const operand_size = operand_ty.abiSize(mod);8468 if (safety) try o.builder.intValue(.i8, 0xaa) else try o.builder.undefValue(.i8),
8881 const usize_ty = try o.lowerType(Type.usize);8469 len,
8882 const len = try o.builder.intValue(usize_ty, operand_size);8470 if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal,
8883 const dest_ptr_align = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));8471 );
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);
8891 if (safety and mod.comp.bin_file.options.valgrind) {8472 if (safety and mod.comp.bin_file.options.valgrind) {
8892 try self.valgrindMarkUndef(dest_ptr, len);8473 try self.valgrindMarkUndef(dest_ptr, len);
8893 }8474 }
...@@ -8940,90 +8521,38 @@ pub const FuncGen = struct {...@@ -8940,90 +8521,38 @@ pub const FuncGen = struct {
89408521
8941 fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8522 fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
8942 _ = inst;8523 _ = inst;
8943 const o = self.dg.object;8524 _ = try self.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, "");
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);
8954 _ = try self.wip.@"unreachable"();8525 _ = try self.wip.@"unreachable"();
8955 return .none;8526 return .none;
8956 }8527 }
89578528
8958 fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8529 fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
8959 _ = inst;8530 _ = inst;
8960 const o = self.dg.object;8531 _ = try self.wip.callIntrinsic(.normal, .none, .debugtrap, &.{}, &.{}, "");
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);
8971 return .none;8532 return .none;
8972 }8533 }
89738534
8974 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8535 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
8975 _ = inst;8536 _ = inst;
8976 const o = self.dg.object;8537 const o = self.dg.object;
8977 const mod = o.module;
8978 const llvm_usize = try o.lowerType(Type.usize);8538 const llvm_usize = try o.lowerType(Type.usize);
8979 const target = mod.getTarget();8539 if (!target_util.supportsReturnAddress(o.module.getTarget())) {
8980 if (!target_util.supportsReturnAddress(target)) {
8981 // https://github.com/ziglang/zig/issues/119468540 // https://github.com/ziglang/zig/issues/11946
8982 return o.builder.intValue(llvm_usize, 0);8541 return o.builder.intValue(llvm_usize, 0);
8983 }8542 }
89848543 const result = try self.wip.callIntrinsic(.normal, .none, .returnaddress, &.{}, &.{
8985 const llvm_fn = try self.getIntrinsic("llvm.returnaddress", &.{});8544 try o.builder.intValue(.i32, 0),
8986 const params = [_]*llvm.Value{8545 }, "");
8987 (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder),8546 return self.wip.cast(.ptrtoint, result, llvm_usize, "");
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, "");
8999 }8547 }
90008548
9001 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8549 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
9002 _ = inst;8550 _ = inst;
9003 const o = self.dg.object;8551 const o = self.dg.object;
9004 const llvm_fn_name = "llvm.frameaddress.p0";8552 const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{
9005 const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {8553 try o.builder.intValue(.i32, 0),
9006 const fn_type = try o.builder.fnType(.ptr, &.{.i32}, .normal);8554 }, "");
9007 break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder));8555 return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), "");
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), "");
9027 }8556 }
90288557
9029 fn airFence(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8558 fn airFence(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -9033,15 +8562,20 @@ pub const FuncGen = struct {...@@ -9033,15 +8562,20 @@ pub const FuncGen = struct {
9033 return .none;8562 return .none;
9034 }8563 }
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 {
9037 const o = self.dg.object;8570 const o = self.dg.object;
9038 const mod = o.module;8571 const mod = o.module;
9039 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;8572 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9040 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;8573 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
9041 const ptr = try self.resolveInst(extra.ptr);8574 const ptr = try self.resolveInst(extra.ptr);
8575 const ptr_ty = self.typeOf(extra.ptr);
9042 var expected_value = try self.resolveInst(extra.expected_value);8576 var expected_value = try self.resolveInst(extra.expected_value);
9043 var new_value = try self.resolveInst(extra.new_value);8577 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);
9045 const llvm_operand_ty = try o.lowerType(operand_ty);8579 const llvm_operand_ty = try o.lowerType(operand_ty);
9046 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, false);8580 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, false);
9047 if (llvm_abi_ty != .none) {8581 if (llvm_abi_ty != .none) {
...@@ -9052,22 +8586,18 @@ pub const FuncGen = struct {...@@ -9052,22 +8586,18 @@ pub const FuncGen = struct {
9052 new_value = try self.wip.conv(signedness, new_value, llvm_abi_ty, "");8586 new_value = try self.wip.conv(signedness, new_value, llvm_abi_ty, "");
9053 }8587 }
90548588
9055 const llvm_result_ty = try o.builder.structType(.normal, &.{8589 const result = try self.wip.cmpxchg(
9056 if (llvm_abi_ty != .none) llvm_abi_ty else llvm_operand_ty,8590 kind,
9057 .i1,8591 if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal,
9058 });8592 ptr,
9059 const result = (try self.wip.unimplemented(llvm_result_ty, "")).finish(8593 expected_value,
9060 self.builder.buildAtomicCmpXchg(8594 new_value,
9061 ptr.toLlvm(&self.wip),8595 self.sync_scope,
9062 expected_value.toLlvm(&self.wip),8596 toLlvmAtomicOrdering(extra.successOrder()),
9063 new_value.toLlvm(&self.wip),8597 toLlvmAtomicOrdering(extra.failureOrder()),
9064 @enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.successOrder()))),8598 Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)),
9065 @enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.failureOrder()))),8599 "",
9066 llvm.Bool.fromBool(self.sync_scope == .singlethread),
9067 ),
9068 &self.wip,
9069 );8600 );
9070 result.toLlvm(&self.wip).setWeak(llvm.Bool.fromBool(is_weak));
90718601
9072 const optional_ty = self.typeOfIndex(inst);8602 const optional_ty = self.typeOfIndex(inst);
90738603
...@@ -9077,7 +8607,7 @@ pub const FuncGen = struct {...@@ -9077,7 +8607,7 @@ pub const FuncGen = struct {
90778607
9078 if (optional_ty.optionalReprIsPayload(mod)) {8608 if (optional_ty.optionalReprIsPayload(mod)) {
9079 const zero = try o.builder.zeroInitValue(payload.typeOfWip(&self.wip));8609 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, "");
9081 }8611 }
90828612
9083 comptime assert(optional_layout_version == 3);8613 comptime assert(optional_layout_version == 3);
...@@ -9099,63 +8629,54 @@ pub const FuncGen = struct {...@@ -9099,63 +8629,54 @@ pub const FuncGen = struct {
9099 const is_float = operand_ty.isRuntimeFloat();8629 const is_float = operand_ty.isRuntimeFloat();
9100 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);8630 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
9101 const ordering = toLlvmAtomicOrdering(extra.ordering());8631 const ordering = toLlvmAtomicOrdering(extra.ordering());
9102 const single_threaded = llvm.Bool.fromBool(self.sync_scope == .singlethread);8632 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .xchg);
9103 const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .Xchg);
9104 const llvm_operand_ty = try o.lowerType(operand_ty);8633 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
9105 if (llvm_abi_ty != .none) {8639 if (llvm_abi_ty != .none) {
9106 // operand needs widening and truncating or bitcasting.8640 // operand needs widening and truncating or bitcasting.
9107 const casted_operand = try self.wip.cast(8641 return self.wip.cast(if (is_float) .bitcast else .trunc, try self.wip.atomicrmw(
9108 if (is_float) .bitcast else if (is_signed_int) .sext else .zext,8642 access_kind,
9109 @enumFromInt(@intFromEnum(operand)),8643 op,
9110 llvm_abi_ty,8644 ptr,
9111 "",8645 try self.wip.cast(
9112 );8646 if (is_float) .bitcast else if (is_signed_int) .sext else .zext,
91138647 operand,
9114 const uncasted_result = (try self.wip.unimplemented(llvm_abi_ty, "")).finish(8648 llvm_abi_ty,
9115 self.builder.buildAtomicRmw(8649 "",
9116 op,
9117 ptr.toLlvm(&self.wip),
9118 casted_operand.toLlvm(&self.wip),
9119 @enumFromInt(@intFromEnum(ordering)),
9120 single_threaded,
9121 ),8650 ),
9122 &self.wip,8651 self.sync_scope,
9123 );8652 ordering,
91248653 ptr_alignment,
9125 if (is_float) {8654 "",
9126 return self.wip.cast(.bitcast, uncasted_result, llvm_operand_ty, "");8655 ), llvm_operand_ty, "");
9127 } else {
9128 return self.wip.cast(.trunc, uncasted_result, llvm_operand_ty, "");
9129 }
9130 }8656 }
91318657
9132 if (!llvm_operand_ty.isPointer(&o.builder)) {8658 if (!llvm_operand_ty.isPointer(&o.builder)) return self.wip.atomicrmw(
9133 return (try self.wip.unimplemented(llvm_operand_ty, "")).finish(8659 access_kind,
9134 self.builder.buildAtomicRmw(8660 op,
9135 op,8661 ptr,
9136 ptr.toLlvm(&self.wip),8662 operand,
9137 operand.toLlvm(&self.wip),8663 self.sync_scope,
9138 @enumFromInt(@intFromEnum(ordering)),8664 ordering,
9139 single_threaded,8665 ptr_alignment,
9140 ),8666 "",
9141 &self.wip,8667 );
9142 );
9143 }
91448668
9145 // It's a pointer but we need to treat it as an int.8669 // It's a pointer but we need to treat it as an int.
9146 const llvm_usize = try o.lowerType(Type.usize);8670 return self.wip.cast(.inttoptr, try self.wip.atomicrmw(
9147 const casted_operand = try self.wip.cast(.ptrtoint, operand, llvm_usize, "");8671 access_kind,
9148 const uncasted_result = (try self.wip.unimplemented(llvm_usize, "")).finish(8672 op,
9149 self.builder.buildAtomicRmw(8673 ptr,
9150 op,8674 try self.wip.cast(.ptrtoint, operand, try o.lowerType(Type.usize), ""),
9151 ptr.toLlvm(&self.wip),8675 self.sync_scope,
9152 casted_operand.toLlvm(&self.wip),8676 ordering,
9153 @enumFromInt(@intFromEnum(ordering)),8677 ptr_alignment,
9154 single_threaded,8678 "",
9155 ),8679 ), llvm_operand_ty, "");
9156 &self.wip,
9157 );
9158 return self.wip.cast(.inttoptr, uncasted_result, llvm_operand_ty, "");
9159 }8680 }
91608681
9161 fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8682 fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -9172,16 +8693,14 @@ pub const FuncGen = struct {...@@ -9172,16 +8693,14 @@ pub const FuncGen = struct {
9172 const ptr_alignment = Builder.Alignment.fromByteUnits(8693 const ptr_alignment = Builder.Alignment.fromByteUnits(
9173 info.flags.alignment.toByteUnitsOptional() orelse info.child.toType().abiAlignment(mod),8694 info.flags.alignment.toByteUnitsOptional() orelse info.child.toType().abiAlignment(mod),
9174 );8695 );
9175 const ptr_kind: Builder.MemoryAccessKind = switch (info.flags.is_volatile) {8696 const access_kind: Builder.MemoryAccessKind =
9176 false => .normal,8697 if (info.flags.is_volatile) .@"volatile" else .normal;
9177 true => .@"volatile",
9178 };
9179 const elem_llvm_ty = try o.lowerType(elem_ty);8698 const elem_llvm_ty = try o.lowerType(elem_ty);
91808699
9181 if (llvm_abi_ty != .none) {8700 if (llvm_abi_ty != .none) {
9182 // operand needs widening and truncating8701 // operand needs widening and truncating
9183 const loaded = try self.wip.loadAtomic(8702 const loaded = try self.wip.loadAtomic(
9184 ptr_kind,8703 access_kind,
9185 llvm_abi_ty,8704 llvm_abi_ty,
9186 ptr,8705 ptr,
9187 self.sync_scope,8706 self.sync_scope,
...@@ -9192,7 +8711,7 @@ pub const FuncGen = struct {...@@ -9192,7 +8711,7 @@ pub const FuncGen = struct {
9192 return self.wip.cast(.trunc, loaded, elem_llvm_ty, "");8711 return self.wip.cast(.trunc, loaded, elem_llvm_ty, "");
9193 }8712 }
9194 return self.wip.loadAtomic(8713 return self.wip.loadAtomic(
9195 ptr_kind,8714 access_kind,
9196 elem_llvm_ty,8715 elem_llvm_ty,
9197 ptr,8716 ptr,
9198 self.sync_scope,8717 self.sync_scope,
...@@ -9239,7 +8758,8 @@ pub const FuncGen = struct {...@@ -9239,7 +8758,8 @@ pub const FuncGen = struct {
9239 const elem_ty = self.typeOf(bin_op.rhs);8758 const elem_ty = self.typeOf(bin_op.rhs);
9240 const dest_ptr_align = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));8759 const dest_ptr_align = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));
9241 const dest_ptr = try self.sliceOrArrayPtr(dest_slice, ptr_ty);8760 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
9244 // Any WebAssembly runtime will trap when the destination pointer is out-of-bounds, regardless8764 // Any WebAssembly runtime will trap when the destination pointer is out-of-bounds, regardless
9245 // of the length. This means we need to emit a check where we skip the memset when the length8765 // 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 {...@@ -9260,17 +8780,10 @@ pub const FuncGen = struct {
9260 try o.builder.undefValue(.i8);8780 try o.builder.undefValue(.i8);
9261 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);8781 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
9262 if (intrinsic_len0_traps) {8782 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);
9264 } else {8784 } else {
9265 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet(8785 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
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);
9272 }8786 }
9273
9274 if (safety and mod.comp.bin_file.options.valgrind) {8787 if (safety and mod.comp.bin_file.options.valgrind) {
9275 try self.valgrindMarkUndef(dest_ptr, len);8788 try self.valgrindMarkUndef(dest_ptr, len);
9276 }8789 }
...@@ -9282,19 +8795,12 @@ pub const FuncGen = struct {...@@ -9282,19 +8795,12 @@ pub const FuncGen = struct {
9282 // repeating byte pattern of 0 bytes. In such case, the memset8795 // repeating byte pattern of 0 bytes. In such case, the memset
9283 // intrinsic can be used.8796 // intrinsic can be used.
9284 if (try elem_val.hasRepeatedByteRepr(elem_ty, mod)) |byte_val| {8797 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);
9286 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);8799 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
9287
9288 if (intrinsic_len0_traps) {8800 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);
9290 } else {8802 } else {
9291 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet(8803 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
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);
9298 }8804 }
9299 return .none;8805 return .none;
9300 }8806 }
...@@ -9309,15 +8815,9 @@ pub const FuncGen = struct {...@@ -9309,15 +8815,9 @@ pub const FuncGen = struct {
9309 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);8815 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
93108816
9311 if (intrinsic_len0_traps) {8817 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);
9313 } else {8819 } else {
9314 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet(8820 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
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);
9321 }8821 }
9322 return .none;8822 return .none;
9323 }8823 }
...@@ -9343,10 +8843,10 @@ pub const FuncGen = struct {...@@ -9343,10 +8843,10 @@ pub const FuncGen = struct {
9343 const body_block = try self.wip.block(1, "InlineMemsetBody");8843 const body_block = try self.wip.block(1, "InlineMemsetBody");
9344 const end_block = try self.wip.block(1, "InlineMemsetEnd");8844 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);
9347 const len = switch (ptr_ty.ptrSize(mod)) {8847 const len = switch (ptr_ty.ptrSize(mod)) {
9348 .Slice => try self.wip.extractValue(dest_slice, &.{1}, ""),8848 .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)),
9350 .Many, .C => unreachable,8850 .Many, .C => unreachable,
9351 };8851 };
9352 const elem_llvm_ty = try o.lowerType(elem_ty);8852 const elem_llvm_ty = try o.lowerType(elem_ty);
...@@ -9359,25 +8859,22 @@ pub const FuncGen = struct {...@@ -9359,25 +8859,22 @@ pub const FuncGen = struct {
9359 _ = try self.wip.brCond(end, body_block, end_block);8859 _ = try self.wip.brCond(end, body_block, end_block);
93608860
9361 self.wip.cursor = .{ .block = body_block };8861 self.wip.cursor = .{ .block = body_block };
9362 const elem_abi_alignment = elem_ty.abiAlignment(mod);8862 const elem_abi_align = elem_ty.abiAlignment(mod);
9363 const it_ptr_alignment = Builder.Alignment.fromByteUnits(8863 const it_ptr_align = Builder.Alignment.fromByteUnits(
9364 @min(elem_abi_alignment, dest_ptr_align.toByteUnits() orelse std.math.maxInt(u64)),8864 @min(elem_abi_align, dest_ptr_align.toByteUnits() orelse std.math.maxInt(u64)),
9365 );8865 );
9366 if (isByRef(elem_ty, mod)) {8866 if (isByRef(elem_ty, mod)) {
9367 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy(8867 _ = try self.wip.callMemCpy(
9368 it_ptr.toValue().toLlvm(&self.wip),8868 it_ptr.toValue(),
9369 @intCast(it_ptr_alignment.toByteUnits() orelse 0),8869 it_ptr_align,
9370 value.toLlvm(&self.wip),8870 value,
9371 elem_abi_alignment,8871 Builder.Alignment.fromByteUnits(elem_abi_align),
9372 (try o.builder.intConst(usize_ty, elem_abi_size)).toLlvm(&o.builder),8872 try o.builder.intValue(llvm_usize_ty, elem_abi_size),
9373 is_volatile,8873 access_kind,
9374 ), &self.wip);8874 );
9375 } else _ = try self.wip.store(switch (is_volatile) {8875 } else _ = try self.wip.store(access_kind, value, it_ptr.toValue(), it_ptr_align);
9376 false => .normal,
9377 true => .@"volatile",
9378 }, value, it_ptr.toValue(), it_ptr_alignment);
9379 const next_ptr = try self.wip.gep(.inbounds, elem_llvm_ty, it_ptr.toValue(), &.{8876 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),
9381 }, "");8878 }, "");
9382 _ = try self.wip.br(loop_block);8879 _ = try self.wip.br(loop_block);
93838880
...@@ -9392,22 +8889,16 @@ pub const FuncGen = struct {...@@ -9392,22 +8889,16 @@ pub const FuncGen = struct {
9392 fill_byte: Builder.Value,8889 fill_byte: Builder.Value,
9393 len: Builder.Value,8890 len: Builder.Value,
9394 dest_ptr_align: Builder.Alignment,8891 dest_ptr_align: Builder.Alignment,
9395 is_volatile: bool,8892 access_kind: Builder.MemoryAccessKind,
9396 ) !void {8893 ) !void {
9397 const o = self.dg.object;8894 const o = self.dg.object;
9398 const llvm_usize_ty = try o.lowerType(Type.usize);8895 const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0);
9399 const cond = try self.cmp(len, try o.builder.intValue(llvm_usize_ty, 0), Type.usize, .neq);8896 const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero);
9400 const memset_block = try self.wip.block(1, "MemsetTrapSkip");8897 const memset_block = try self.wip.block(1, "MemsetTrapSkip");
9401 const end_block = try self.wip.block(2, "MemsetTrapEnd");8898 const end_block = try self.wip.block(2, "MemsetTrapEnd");
9402 _ = try self.wip.brCond(cond, memset_block, end_block);8899 _ = try self.wip.brCond(cond, memset_block, end_block);
9403 self.wip.cursor = .{ .block = memset_block };8900 self.wip.cursor = .{ .block = memset_block };
9404 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet(8901 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
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);
9411 _ = try self.wip.br(end_block);8902 _ = try self.wip.br(end_block);
9412 self.wip.cursor = .{ .block = end_block };8903 self.wip.cursor = .{ .block = end_block };
9413 }8904 }
...@@ -9423,7 +8914,8 @@ pub const FuncGen = struct {...@@ -9423,7 +8914,8 @@ pub const FuncGen = struct {
9423 const src_ptr = try self.sliceOrArrayPtr(src_slice, src_ptr_ty);8914 const src_ptr = try self.sliceOrArrayPtr(src_slice, src_ptr_ty);
9424 const len = try self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty);8915 const len = try self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty);
9425 const dest_ptr = try self.sliceOrArrayPtr(dest_slice, dest_ptr_ty);8916 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
9428 // When bulk-memory is enabled, this will be lowered to WebAssembly's memory.copy instruction.8920 // When bulk-memory is enabled, this will be lowered to WebAssembly's memory.copy instruction.
9429 // This instruction will trap on an invalid address, regardless of the length.8921 // This instruction will trap on an invalid address, regardless of the length.
...@@ -9434,33 +8926,33 @@ pub const FuncGen = struct {...@@ -9434,33 +8926,33 @@ pub const FuncGen = struct {
9434 std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and8926 std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and
9435 dest_ptr_ty.isSlice(mod))8927 dest_ptr_ty.isSlice(mod))
9436 {8928 {
9437 const zero_usize = try o.builder.intValue(try o.lowerType(Type.usize), 0);8929 const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0);
9438 const cond = try self.cmp(len, zero_usize, Type.usize, .neq);8930 const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero);
9439 const memcpy_block = try self.wip.block(1, "MemcpyTrapSkip");8931 const memcpy_block = try self.wip.block(1, "MemcpyTrapSkip");
9440 const end_block = try self.wip.block(2, "MemcpyTrapEnd");8932 const end_block = try self.wip.block(2, "MemcpyTrapEnd");
9441 _ = try self.wip.brCond(cond, memcpy_block, end_block);8933 _ = try self.wip.brCond(cond, memcpy_block, end_block);
9442 self.wip.cursor = .{ .block = memcpy_block };8934 self.wip.cursor = .{ .block = memcpy_block };
9443 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy(8935 _ = try self.wip.callMemCpy(
9444 dest_ptr.toLlvm(&self.wip),8936 dest_ptr,
9445 dest_ptr_ty.ptrAlignment(mod),8937 Builder.Alignment.fromByteUnits(dest_ptr_ty.ptrAlignment(mod)),
9446 src_ptr.toLlvm(&self.wip),8938 src_ptr,
9447 src_ptr_ty.ptrAlignment(mod),8939 Builder.Alignment.fromByteUnits(src_ptr_ty.ptrAlignment(mod)),
9448 len.toLlvm(&self.wip),8940 len,
9449 is_volatile,8941 access_kind,
9450 ), &self.wip);8942 );
9451 _ = try self.wip.br(end_block);8943 _ = try self.wip.br(end_block);
9452 self.wip.cursor = .{ .block = end_block };8944 self.wip.cursor = .{ .block = end_block };
9453 return .none;8945 return .none;
9454 }8946 }
94558947
9456 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy(8948 _ = try self.wip.callMemCpy(
9457 dest_ptr.toLlvm(&self.wip),8949 dest_ptr,
9458 dest_ptr_ty.ptrAlignment(mod),8950 Builder.Alignment.fromByteUnits(dest_ptr_ty.ptrAlignment(mod)),
9459 src_ptr.toLlvm(&self.wip),8951 src_ptr,
9460 src_ptr_ty.ptrAlignment(mod),8952 Builder.Alignment.fromByteUnits(src_ptr_ty.ptrAlignment(mod)),
9461 len.toLlvm(&self.wip),8953 len,
9462 is_volatile,8954 access_kind,
9463 ), &self.wip);8955 );
9464 return .none;8956 return .none;
9465 }8957 }
94668958
...@@ -9513,39 +9005,51 @@ pub const FuncGen = struct {...@@ -9513,39 +9005,51 @@ pub const FuncGen = struct {
9513 const operand = try self.resolveInst(un_op);9005 const operand = try self.resolveInst(un_op);
9514 const operand_ty = self.typeOf(un_op);9006 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});
9517 }9009 }
95189010
9519 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {9011 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
9520 self.builder.setFastMath(want_fast_math);
9521
9522 const un_op = self.air.instructions.items(.data)[inst].un_op;9012 const un_op = self.air.instructions.items(.data)[inst].un_op;
9523 const operand = try self.resolveInst(un_op);9013 const operand = try self.resolveInst(un_op);
9524 const operand_ty = self.typeOf(un_op);9014 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});
9527 }9017 }
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 {
9530 const o = self.dg.object;9020 const o = self.dg.object;
9531 const ty_op = self.air.instructions.items(.data)[inst].ty_op;9021 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);
9532 const operand = try self.resolveInst(ty_op.operand);9024 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(), "");9026 const result = try self.wip.callIntrinsic(
95359027 .normal,
9536 const result_ty = self.typeOfIndex(inst);9028 .none,
9537 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");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), "");
9538 }9035 }
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 {
9541 const o = self.dg.object;9038 const o = self.dg.object;
9542 const ty_op = self.air.instructions.items(.data)[inst].ty_op;9039 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);
9543 const operand = try self.resolveInst(ty_op.operand);9042 const operand = try self.resolveInst(ty_op.operand);
95449043
9545 const wrong_size_result = try self.wip.un(intrinsic, operand, "");9044 const result = try self.wip.callIntrinsic(
95469045 .normal,
9547 const result_ty = self.typeOfIndex(inst);9046 .none,
9548 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");9047 intrinsic,
9048 &.{try o.lowerType(operand_ty)},
9049 &.{operand},
9050 "",
9051 );
9052 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
9549 }9053 }
95509054
9551 fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9055 fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -9556,6 +9060,7 @@ pub const FuncGen = struct {...@@ -9556,6 +9060,7 @@ pub const FuncGen = struct {
9556 var bits = operand_ty.intInfo(mod).bits;9060 var bits = operand_ty.intInfo(mod).bits;
9557 assert(bits % 8 == 0);9061 assert(bits % 8 == 0);
95589062
9063 const inst_ty = self.typeOfIndex(inst);
9559 var operand = try self.resolveInst(ty_op.operand);9064 var operand = try self.resolveInst(ty_op.operand);
9560 var llvm_operand_ty = try o.lowerType(operand_ty);9065 var llvm_operand_ty = try o.lowerType(operand_ty);
95619066
...@@ -9576,10 +9081,9 @@ pub const FuncGen = struct {...@@ -9576,10 +9081,9 @@ pub const FuncGen = struct {
9576 bits = bits + 8;9081 bits = bits + 8;
9577 }9082 }
95789083
9579 const wrong_size_result = try self.wip.un(.@"llvm.bswap.", operand, "");9084 const result =
95809085 try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, "");
9581 const result_ty = self.typeOfIndex(inst);9086 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
9582 return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), "");
9583 }9087 }
95849088
9585 fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9089 fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -9609,11 +9113,7 @@ pub const FuncGen = struct {...@@ -9609,11 +9113,7 @@ pub const FuncGen = struct {
96099113
9610 self.wip.cursor = .{ .block = end_block };9114 self.wip.cursor = .{ .block = end_block };
9611 const phi = try self.wip.phi(.i1, "");9115 const phi = try self.wip.phi(.i1, "");
9612 try phi.finish(9116 try phi.finish(&.{ .true, .false }, &.{ valid_block, invalid_block }, &self.wip);
9613 &.{ Builder.Constant.true.toValue(), Builder.Constant.false.toValue() },
9614 &.{ valid_block, invalid_block },
9615 &self.wip,
9616 );
9617 return phi.toValue();9117 return phi.toValue();
9618 }9118 }
96199119
...@@ -9646,37 +9146,22 @@ pub const FuncGen = struct {...@@ -9646,37 +9146,22 @@ pub const FuncGen = struct {
9646 errdefer assert(o.named_enum_map.remove(enum_type.decl));9146 errdefer assert(o.named_enum_map.remove(enum_type.decl));
96479147
9648 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);9148 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
9649 const llvm_fn_name = try o.builder.fmt("__zig_is_named_enum_value_{}", .{9149 const function_index = try o.builder.addFunction(
9650 fqn.fmt(&mod.intern_pool),9150 try o.builder.fnType(.i1, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
9651 });9151 try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}),
9152 toLlvmAddressSpace(.generic, mod.getTarget()),
9153 );
96529154
9653 var attributes: Builder.FunctionAttributes.Wip = .{};9155 var attributes: Builder.FunctionAttributes.Wip = .{};
9654 defer attributes.deinit(&o.builder);9156 defer attributes.deinit(&o.builder);
9157 try o.addCommonFnAttributes(&attributes);
96559158
9656 const fn_type = try o.builder.fnType(.i1, &.{9159 function_index.setLinkage(.internal, &o.builder);
9657 try o.lowerType(enum_type.tag_ty.toType()),9160 function_index.setCallConv(.fastcc, &o.builder);
9658 }, .normal);9161 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9659 const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));9162 gop.value_ptr.* = function_index;
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;
96789163
9679 var wip = try Builder.WipFunction.init(&o.builder, global.kind.function);9164 var wip = try Builder.WipFunction.init(&o.builder, function_index);
9680 defer wip.deinit();9165 defer wip.deinit();
9681 wip.cursor = .{ .block = try wip.block(0, "Entry") };9166 wip.cursor = .{ .block = try wip.block(0, "Entry") };
96829167
...@@ -9693,13 +9178,13 @@ pub const FuncGen = struct {...@@ -9693,13 +9178,13 @@ pub const FuncGen = struct {
9693 try wip_switch.addCase(this_tag_int_value, named_block, &wip);9178 try wip_switch.addCase(this_tag_int_value, named_block, &wip);
9694 }9179 }
9695 wip.cursor = .{ .block = named_block };9180 wip.cursor = .{ .block = named_block };
9696 _ = try wip.ret(Builder.Constant.true.toValue());9181 _ = try wip.ret(.true);
96979182
9698 wip.cursor = .{ .block = unnamed_block };9183 wip.cursor = .{ .block = unnamed_block };
9699 _ = try wip.ret(Builder.Constant.false.toValue());9184 _ = try wip.ret(.false);
97009185
9701 try wip.finish();9186 try wip.finish();
9702 return global.kind.function;9187 return function_index;
9703 }9188 }
97049189
9705 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9190 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -9730,38 +9215,25 @@ pub const FuncGen = struct {...@@ -9730,38 +9215,25 @@ pub const FuncGen = struct {
9730 if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function;9215 if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function;
9731 errdefer assert(o.decl_map.remove(enum_type.decl));9216 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);
9733 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);9220 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
9736 var attributes: Builder.FunctionAttributes.Wip = .{};9227 var attributes: Builder.FunctionAttributes.Wip = .{};
9737 defer attributes.deinit(&o.builder);9228 defer attributes.deinit(&o.builder);
9229 try o.addCommonFnAttributes(&attributes);
97389230
9739 const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);9231 function_index.setLinkage(.internal, &o.builder);
9740 const usize_ty = try o.lowerType(Type.usize);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, &.{9236 var wip = try Builder.WipFunction.init(&o.builder, function_index);
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);
9765 defer wip.deinit();9237 defer wip.deinit();
9766 wip.cursor = .{ .block = try wip.block(0, "Entry") };9238 wip.cursor = .{ .block = try wip.block(0, "Entry") };
97679239
...@@ -9771,36 +9243,20 @@ pub const FuncGen = struct {...@@ -9771,36 +9243,20 @@ pub const FuncGen = struct {
9771 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));9243 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
9772 defer wip_switch.finish(&wip);9244 defer wip_switch.finish(&wip);
97739245
9774 for (enum_type.names, 0..) |name_ip, field_index| {9246 for (enum_type.names, 0..) |name, field_index| {
9775 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_ip));9247 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
9776 const str_init = try o.builder.stringNullConst(name);9248 const name_init = try o.builder.stringNullConst(name_string);
9777 const str_ty = str_init.typeOf(&o.builder);9249 const name_variable_index =
9778 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");9250 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
9779 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));9251 try name_variable_index.setInitializer(name_init, &o.builder);
9780 str_llvm_global.setLinkage(.Private);9252 name_variable_index.setLinkage(.private, &o.builder);
9781 str_llvm_global.setGlobalConstant(.True);9253 name_variable_index.setMutability(.constant, &o.builder);
9782 str_llvm_global.setUnnamedAddr(.True);9254 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
9783 str_llvm_global.setAlignment(1);9255 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
97849256
9785 var str_global = Builder.Global{9257 const name_val = try o.builder.structValue(ret_ty, &.{
9786 .linkage = .private,9258 name_variable_index.toConst(&o.builder),
9787 .unnamed_addr = .unnamed_addr,9259 try o.builder.intConst(usize_ty, name_string.slice(&o.builder).?.len),
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),
9804 });9260 });
98059261
9806 const return_block = try wip.block(1, "Name");9262 const return_block = try wip.block(1, "Name");
...@@ -9810,14 +9266,14 @@ pub const FuncGen = struct {...@@ -9810,14 +9266,14 @@ pub const FuncGen = struct {
9810 try wip_switch.addCase(this_tag_int_value, return_block, &wip);9266 try wip_switch.addCase(this_tag_int_value, return_block, &wip);
98119267
9812 wip.cursor = .{ .block = return_block };9268 wip.cursor = .{ .block = return_block };
9813 _ = try wip.ret(slice_val);9269 _ = try wip.ret(name_val);
9814 }9270 }
98159271
9816 wip.cursor = .{ .block = bad_value_block };9272 wip.cursor = .{ .block = bad_value_block };
9817 _ = try wip.@"unreachable"();9273 _ = try wip.@"unreachable"();
98189274
9819 try wip.finish();9275 try wip.finish();
9820 return global.kind.function;9276 return function_index;
9821 }9277 }
98229278
9823 fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index {9279 fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index {
...@@ -9826,33 +9282,20 @@ pub const FuncGen = struct {...@@ -9826,33 +9282,20 @@ pub const FuncGen = struct {
9826 const name = try o.builder.string(lt_errors_fn_name);9282 const name = try o.builder.string(lt_errors_fn_name);
9827 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;9283 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
98289284
9829 // Function signature: fn (anyerror) bool9285 const function_index = try o.builder.addFunction(
98309286 try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal),
9831 const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal);9287 name,
9832 const llvm_fn = o.llvm_module.addFunction(name.slice(&o.builder).?, fn_type.toLlvm(&o.builder));9288 toLlvmAddressSpace(.generic, o.module.getTarget()),
9289 );
98339290
9834 var attributes: Builder.FunctionAttributes.Wip = .{};9291 var attributes: Builder.FunctionAttributes.Wip = .{};
9835 defer attributes.deinit(&o.builder);9292 defer attributes.deinit(&o.builder);
9293 try o.addCommonFnAttributes(&attributes);
98369294
9837 llvm_fn.setLinkage(.Internal);9295 function_index.setLinkage(.internal, &o.builder);
9838 llvm_fn.setFunctionCallConv(.Fast);9296 function_index.setCallConv(.fastcc, &o.builder);
9839 try o.addCommonFnAttributes(&attributes, llvm_fn);9297 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
98409298 return function_index;
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;
9856 }9299 }
98579300
9858 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9301 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -9885,7 +9328,7 @@ pub const FuncGen = struct {...@@ -9885,7 +9328,7 @@ pub const FuncGen = struct {
9885 const a = try self.resolveInst(extra.lhs);9328 const a = try self.resolveInst(extra.lhs);
9886 const b = try self.resolveInst(extra.rhs);9329 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, "");
9889 }9332 }
98909333
9891 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9334 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -9997,8 +9440,7 @@ pub const FuncGen = struct {...@@ -9997,8 +9440,7 @@ pub const FuncGen = struct {
9997 return self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, "");9440 return self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, "");
9998 }9441 }
99999442
10000 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {9443 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
10001 self.builder.setFastMath(want_fast_math);
10002 const o = self.dg.object;9444 const o = self.dg.object;
10003 const mod = o.module;9445 const mod = o.module;
10004 const target = mod.getTarget();9446 const target = mod.getTarget();
...@@ -10006,72 +9448,53 @@ pub const FuncGen = struct {...@@ -10006,72 +9448,53 @@ pub const FuncGen = struct {
10006 const reduce = self.air.instructions.items(.data)[inst].reduce;9448 const reduce = self.air.instructions.items(.data)[inst].reduce;
10007 const operand = try self.resolveInst(reduce.operand);9449 const operand = try self.resolveInst(reduce.operand);
10008 const operand_ty = self.typeOf(reduce.operand);9450 const operand_ty = self.typeOf(reduce.operand);
9451 const llvm_operand_ty = try o.lowerType(operand_ty);
10009 const scalar_ty = self.typeOfIndex(inst);9452 const scalar_ty = self.typeOfIndex(inst);
10010 const llvm_scalar_ty = try o.lowerType(scalar_ty);9453 const llvm_scalar_ty = try o.lowerType(scalar_ty);
100119454
10012 switch (reduce.operation) {9455 switch (reduce.operation) {
10013 .And => return (try self.wip.unimplemented(llvm_scalar_ty, ""))9456 .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
10014 .finish(self.builder.buildAndReduce(operand.toLlvm(&self.wip)), &self.wip),9457 .And => .@"vector.reduce.and",
10015 .Or => return (try self.wip.unimplemented(llvm_scalar_ty, ""))9458 .Or => .@"vector.reduce.or",
10016 .finish(self.builder.buildOrReduce(operand.toLlvm(&self.wip)), &self.wip),9459 .Xor => .@"vector.reduce.xor",
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 },
10045 else => unreachable,9460 else => unreachable,
10046 },9461 }, &.{llvm_operand_ty}, &.{operand}, ""),
10047 .Add => switch (scalar_ty.zigTypeTag(mod)) {9462 .Min, .Max => switch (scalar_ty.zigTypeTag(mod)) {
10048 .Int => return (try self.wip.unimplemented(llvm_scalar_ty, ""))9463 .Int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
10049 .finish(self.builder.buildAddReduce(operand.toLlvm(&self.wip)), &self.wip),9464 .Min => if (scalar_ty.isSignedInt(mod))
10050 .Float => if (intrinsicsAllowed(scalar_ty, target)) {9465 .@"vector.reduce.smin"
10051 const neutral_value = try o.builder.fpConst(llvm_scalar_ty, -0.0);9466 else
10052 return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish(9467 .@"vector.reduce.umin",
10053 self.builder.buildFPAddReduce(9468 .Max => if (scalar_ty.isSignedInt(mod))
10054 neutral_value.toLlvm(&o.builder),9469 .@"vector.reduce.smax"
10055 operand.toLlvm(&self.wip),9470 else
10056 ),9471 .@"vector.reduce.umax",
10057 &self.wip,9472 else => unreachable,
10058 );9473 }, &.{llvm_operand_ty}, &.{operand}, ""),
10059 },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}, ""),
10060 else => unreachable,9480 else => unreachable,
10061 },9481 },
10062 .Mul => switch (scalar_ty.zigTypeTag(mod)) {9482 .Add, .Mul => switch (scalar_ty.zigTypeTag(mod)) {
10063 .Int => return (try self.wip.unimplemented(llvm_scalar_ty, ""))9483 .Int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
10064 .finish(self.builder.buildMulReduce(operand.toLlvm(&self.wip)), &self.wip),9484 .Add => .@"vector.reduce.add",
10065 .Float => if (intrinsicsAllowed(scalar_ty, target)) {9485 .Mul => .@"vector.reduce.mul",
10066 const neutral_value = try o.builder.fpConst(llvm_scalar_ty, 1.0);9486 else => unreachable,
10067 return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish(9487 }, &.{llvm_operand_ty}, &.{operand}, ""),
10068 self.builder.buildFPMulReduce(9488 .Float => if (intrinsicsAllowed(scalar_ty, target))
10069 neutral_value.toLlvm(&o.builder),9489 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
10070 operand.toLlvm(&self.wip),9490 .Add => .@"vector.reduce.fadd",
10071 ),9491 .Mul => .@"vector.reduce.fmul",
10072 &self.wip,9492 else => unreachable,
10073 );9493 }, &.{llvm_operand_ty}, &.{ switch (reduce.operation) {
10074 },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 }, ""),
10075 else => unreachable,9498 else => unreachable,
10076 },9499 },
10077 }9500 }
...@@ -10168,10 +9591,8 @@ pub const FuncGen = struct {...@@ -10168,10 +9591,8 @@ pub const FuncGen = struct {
10168 else9591 else
10169 try self.wip.cast(.bitcast, non_int_val, small_int_ty, "");9592 try self.wip.cast(.bitcast, non_int_val, small_int_ty, "");
10170 const shift_rhs = try o.builder.intValue(int_ty, running_bits);9593 const shift_rhs = try o.builder.intValue(int_ty, running_bits);
10171 // If the field is as large as the entire packed struct, this9594 const extended_int_val =
10172 // zext would go from, e.g. i16 to i16. This is legal with9595 try self.wip.conv(.unsigned, small_int_val, int_ty, "");
10173 // constZExtOrBitCast but not legal with constZExt.
10174 const extended_int_val = try self.wip.conv(.unsigned, small_int_val, int_ty, "");
10175 const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, "");9596 const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, "");
10176 running_int = try self.wip.bin(.@"or", running_int, shifted, "");9597 running_int = try self.wip.bin(.@"or", running_int, shifted, "");
10177 running_bits += ty_bit_size;9598 running_bits += ty_bit_size;
...@@ -10416,29 +9837,12 @@ pub const FuncGen = struct {...@@ -10416,29 +9837,12 @@ pub const FuncGen = struct {
10416 .data => {},9837 .data => {},
10417 }9838 }
104189839
10419 const llvm_fn_name = "llvm.prefetch.p0";9840 _ = try self.wip.callIntrinsic(.normal, .none, .prefetch, &.{.ptr}, &.{
10420 // declare void @llvm.prefetch(i8*, i32, i32, i32)9841 try self.resolveInst(prefetch.ptr),
10421 const llvm_fn_ty = try o.builder.fnType(.void, &.{ .ptr, .i32, .i32, .i32 }, .normal);9842 try o.builder.intValue(.i32, prefetch.rw),
10422 const fn_val = o.llvm_module.getNamedFunction(llvm_fn_name) orelse9843 try o.builder.intValue(.i32, prefetch.locality),
10423 o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder));9844 try o.builder.intValue(.i32, prefetch.cache),
104249845 }, "");
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);
10442 return .none;9846 return .none;
10443 }9847 }
104449848
...@@ -10451,26 +9855,18 @@ pub const FuncGen = struct {...@@ -10451,26 +9855,18 @@ pub const FuncGen = struct {
10451 return self.wip.cast(.addrspacecast, operand, try o.lowerType(inst_ty), "");9855 return self.wip.cast(.addrspacecast, operand, try o.lowerType(inst_ty), "");
10452 }9856 }
104539857
10454 fn amdgcnWorkIntrinsic(self: *FuncGen, dimension: u32, default: u32, comptime basename: []const u8) !Builder.Value {9858 fn amdgcnWorkIntrinsic(
10455 const o = self.dg.object;9859 self: *FuncGen,
10456 const llvm_fn_name = switch (dimension) {9860 dimension: u32,
10457 0 => basename ++ ".x",9861 default: u32,
10458 1 => basename ++ ".y",9862 comptime basename: []const u8,
10459 2 => basename ++ ".z",9863 ) !Builder.Value {
10460 else => return o.builder.intValue(.i32, default),9864 return self.wip.callIntrinsic(.normal, .none, switch (dimension) {
10461 };9865 0 => @field(Builder.Intrinsic, basename ++ ".x"),
104629866 1 => @field(Builder.Intrinsic, basename ++ ".y"),
10463 const args: [0]*llvm.Value = .{};9867 2 => @field(Builder.Intrinsic, basename ++ ".z"),
10464 const llvm_fn = try self.getIntrinsic(llvm_fn_name, &.{});9868 else => return self.dg.object.builder.intValue(.i32, default),
10465 return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld(9869 }, &.{}, &.{}, "");
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);
10474 }9870 }
104759871
10476 fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9872 fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -10480,7 +9876,7 @@ pub const FuncGen = struct {...@@ -10480,7 +9876,7 @@ pub const FuncGen = struct {
104809876
10481 const pl_op = self.air.instructions.items(.data)[inst].pl_op;9877 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
10482 const dimension = pl_op.payload;9878 const dimension = pl_op.payload;
10483 return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workitem.id");9879 return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workitem.id");
10484 }9880 }
104859881
10486 fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9882 fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -10492,27 +9888,10 @@ pub const FuncGen = struct {...@@ -10492,27 +9888,10 @@ pub const FuncGen = struct {
10492 const dimension = pl_op.payload;9888 const dimension = pl_op.payload;
10493 if (dimension >= 3) return o.builder.intValue(.i32, 1);9889 if (dimension >= 3) return o.builder.intValue(.i32, 1);
104949890
10495 var attributes: Builder.FunctionAttributes.Wip = .{};
10496 defer attributes.deinit(&o.builder);
10497
10498 // Fetch the dispatch pointer, which points to this structure:9891 // Fetch the dispatch pointer, which points to this structure:
10499 // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L29139892 // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913
10500 const llvm_fn = try self.getIntrinsic("llvm.amdgcn.dispatch.ptr", &.{});9893 const dispatch_ptr =
10501 const args: [0]*llvm.Value = .{};9894 try self.wip.callIntrinsic(.normal, .none, .@"amdgcn.dispatch.ptr", &.{}, &.{}, "");
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);
105169895
10517 // Load the work_group_* member from the struct as u16.9896 // Load the work_group_* member from the struct as u16.
10518 // Just treat the dispatch pointer as an array of u16 to keep things simple.9897 // Just treat the dispatch pointer as an array of u16 to keep things simple.
...@@ -10530,45 +9909,29 @@ pub const FuncGen = struct {...@@ -10530,45 +9909,29 @@ pub const FuncGen = struct {
105309909
10531 const pl_op = self.air.instructions.items(.data)[inst].pl_op;9910 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
10532 const dimension = pl_op.payload;9911 const dimension = pl_op.payload;
10533 return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workgroup.id");9912 return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workgroup.id");
10534 }9913 }
105359914
10536 fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index {9915 fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index {
10537 const o = self.dg.object;9916 const o = self.dg.object;
9917 const mod = o.module;
9918
10538 const table = o.error_name_table;9919 const table = o.error_name_table;
10539 if (table != .none) return table;9920 if (table != .none) return table;
105409921
10541 const mod = o.module;9922 // TODO: Address space
10542 const slice_ty = Type.slice_const_u8_sentinel_0;9923 const variable_index =
10543 const slice_alignment = slice_ty.abiAlignment(mod);9924 try o.builder.addVariable(try o.builder.string("__zig_err_name_table"), .ptr, .default);
10544 const undef_init = try o.builder.undefConst(.ptr); // TODO: Address space9925 variable_index.setLinkage(.private, &o.builder);
105459926 variable_index.setMutability(.constant, &o.builder);
10546 const name = try o.builder.string("__zig_err_name_table");9927 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
10547 const error_name_table_global = o.llvm_module.addGlobal(Builder.Type.ptr.toLlvm(&o.builder), name.slice(&o.builder).?);9928 variable_index.setAlignment(
10548 error_name_table_global.setInitializer(undef_init.toLlvm(&o.builder));9929 Builder.Alignment.fromByteUnits(Type.slice_const_u8_sentinel_0.abiAlignment(mod)),
10549 error_name_table_global.setLinkage(.Private);9930 &o.builder,
10550 error_name_table_global.setGlobalConstant(.True);9931 );
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);
105699932
10570 o.error_name_table = global.kind.variable;9933 o.error_name_table = variable_index;
10571 return global.kind.variable;9934 return variable_index;
10572 }9935 }
105739936
10574 /// Assumes the optional is not pointer-like and payload has bits.9937 /// Assumes the optional is not pointer-like and payload has bits.
...@@ -10613,7 +9976,7 @@ pub const FuncGen = struct {...@@ -10613,7 +9976,7 @@ pub const FuncGen = struct {
10613 if (can_elide_load)9976 if (can_elide_load)
10614 return payload_ptr;9977 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);
10617 }9980 }
10618 const payload_llvm_ty = try o.lowerType(payload_ty);9981 const payload_llvm_ty = try o.lowerType(payload_ty);
10619 return fg.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, "");9982 return fg.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, "");
...@@ -10716,27 +10079,13 @@ pub const FuncGen = struct {...@@ -10716,27 +10079,13 @@ pub const FuncGen = struct {
10716 }10079 }
10717 }10080 }
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
10733 /// Load a by-ref type by constructing a new alloca and performing a memcpy.10082 /// Load a by-ref type by constructing a new alloca and performing a memcpy.
10734 fn loadByRef(10083 fn loadByRef(
10735 fg: *FuncGen,10084 fg: *FuncGen,
10736 ptr: Builder.Value,10085 ptr: Builder.Value,
10737 pointee_type: Type,10086 pointee_type: Type,
10738 ptr_alignment: Builder.Alignment,10087 ptr_alignment: Builder.Alignment,
10739 is_volatile: bool,10088 access_kind: Builder.MemoryAccessKind,
10740 ) !Builder.Value {10089 ) !Builder.Value {
10741 const o = fg.dg.object;10090 const o = fg.dg.object;
10742 const mod = o.module;10091 const mod = o.module;
...@@ -10745,16 +10094,15 @@ pub const FuncGen = struct {...@@ -10745,16 +10094,15 @@ pub const FuncGen = struct {
10745 @max(ptr_alignment.toByteUnits() orelse 0, pointee_type.abiAlignment(mod)),10094 @max(ptr_alignment.toByteUnits() orelse 0, pointee_type.abiAlignment(mod)),
10746 );10095 );
10747 const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align);10096 const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align);
10748 const usize_ty = try o.lowerType(Type.usize);
10749 const size_bytes = pointee_type.abiSize(mod);10097 const size_bytes = pointee_type.abiSize(mod);
10750 _ = (try fg.wip.unimplemented(.void, "")).finish(fg.builder.buildMemCpy(10098 _ = try fg.wip.callMemCpy(
10751 result_ptr.toLlvm(&fg.wip),10099 result_ptr,
10752 @intCast(result_align.toByteUnits() orelse 0),10100 result_align,
10753 ptr.toLlvm(&fg.wip),10101 ptr,
10754 @intCast(ptr_alignment.toByteUnits() orelse 0),10102 ptr_alignment,
10755 (try o.builder.intConst(usize_ty, size_bytes)).toLlvm(&o.builder),10103 try o.builder.intValue(try o.lowerType(Type.usize), size_bytes),
10756 is_volatile,10104 access_kind,
10757 ), &fg.wip);10105 );
10758 return result_ptr;10106 return result_ptr;
10759 }10107 }
1076010108
...@@ -10771,30 +10119,29 @@ pub const FuncGen = struct {...@@ -10771,30 +10119,29 @@ pub const FuncGen = struct {
10771 const ptr_alignment = Builder.Alignment.fromByteUnits(10119 const ptr_alignment = Builder.Alignment.fromByteUnits(
10772 info.flags.alignment.toByteUnitsOptional() orelse elem_ty.abiAlignment(mod),10120 info.flags.alignment.toByteUnitsOptional() orelse elem_ty.abiAlignment(mod),
10773 );10121 );
10774 const ptr_kind: Builder.MemoryAccessKind = switch (info.flags.is_volatile) {10122 const access_kind: Builder.MemoryAccessKind =
10775 false => .normal,10123 if (info.flags.is_volatile) .@"volatile" else .normal;
10776 true => .@"volatile",
10777 };
1077810124
10779 assert(info.flags.vector_index != .runtime);10125 assert(info.flags.vector_index != .runtime);
10780 if (info.flags.vector_index != .none) {10126 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);
10782 const vec_elem_ty = try o.lowerType(elem_ty);10128 const vec_elem_ty = try o.lowerType(elem_ty);
10783 const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty);10129 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, "");
10786 return self.wip.extractElement(loaded_vector, index_u32, "");10132 return self.wip.extractElement(loaded_vector, index_u32, "");
10787 }10133 }
1078810134
10789 if (info.packed_offset.host_size == 0) {10135 if (info.packed_offset.host_size == 0) {
10790 if (isByRef(elem_ty, mod)) {10136 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);
10792 }10138 }
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, "");
10794 }10140 }
1079510141
10796 const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8));10142 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
10799 const elem_bits = ptr_ty.childType(mod).bitSize(mod);10146 const elem_bits = ptr_ty.childType(mod).bitSize(mod);
10800 const shift_amt = try o.builder.intValue(containing_int_ty, info.packed_offset.bit_offset);10147 const shift_amt = try o.builder.intValue(containing_int_ty, info.packed_offset.bit_offset);
...@@ -10841,23 +10188,21 @@ pub const FuncGen = struct {...@@ -10841,23 +10188,21 @@ pub const FuncGen = struct {
10841 return;10188 return;
10842 }10189 }
10843 const ptr_alignment = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));10190 const ptr_alignment = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod));
10844 const ptr_kind: Builder.MemoryAccessKind = switch (info.flags.is_volatile) {10191 const access_kind: Builder.MemoryAccessKind =
10845 false => .normal,10192 if (info.flags.is_volatile) .@"volatile" else .normal;
10846 true => .@"volatile",
10847 };
1084810193
10849 assert(info.flags.vector_index != .runtime);10194 assert(info.flags.vector_index != .runtime);
10850 if (info.flags.vector_index != .none) {10195 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);
10852 const vec_elem_ty = try o.lowerType(elem_ty);10197 const vec_elem_ty = try o.lowerType(elem_ty);
10853 const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty);10198 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
10857 const modified_vector = try self.wip.insertElement(loaded_vector, elem, index_u32, "");10202 const modified_vector = try self.wip.insertElement(loaded_vector, elem, index_u32, "");
1085810203
10859 assert(ordering == .none);10204 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);
10861 return;10206 return;
10862 }10207 }
1086310208
...@@ -10865,7 +10210,7 @@ pub const FuncGen = struct {...@@ -10865,7 +10210,7 @@ pub const FuncGen = struct {
10865 const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8));10210 const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8));
10866 assert(ordering == .none);10211 assert(ordering == .none);
10867 const containing_int =10212 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, "");
10869 const elem_bits = ptr_ty.childType(mod).bitSize(mod);10214 const elem_bits = ptr_ty.childType(mod).bitSize(mod);
10870 const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset);10215 const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset);
10871 // Convert to equally-sized integer type in order to perform the bit10216 // Convert to equally-sized integer type in order to perform the bit
...@@ -10889,23 +10234,29 @@ pub const FuncGen = struct {...@@ -10889,23 +10234,29 @@ pub const FuncGen = struct {
10889 const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, "");10234 const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, "");
1089010235
10891 assert(ordering == .none);10236 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);
10893 return;10238 return;
10894 }10239 }
10895 if (!isByRef(elem_ty, mod)) {10240 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 );
10897 return;10249 return;
10898 }10250 }
10899 assert(ordering == .none);10251 assert(ordering == .none);
10900 const size_bytes = elem_ty.abiSize(mod);10252 _ = try self.wip.callMemCpy(
10901 _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy(10253 ptr,
10902 ptr.toLlvm(&self.wip),10254 ptr_alignment,
10903 @intCast(ptr_alignment.toByteUnits() orelse 0),10255 elem,
10904 elem.toLlvm(&self.wip),10256 Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod)),
10905 elem_ty.abiAlignment(mod),10257 try o.builder.intValue(try o.lowerType(Type.usize), elem_ty.abiSize(mod)),
10906 (try o.builder.intConst(try o.lowerType(Type.usize), size_bytes)).toLlvm(&o.builder),10258 access_kind,
10907 info.flags.is_volatile,10259 );
10908 ), &self.wip);
10909 }10260 }
1091010261
10911 fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void {10262 fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void {
...@@ -10982,26 +10333,15 @@ pub const FuncGen = struct {...@@ -10982,26 +10333,15 @@ pub const FuncGen = struct {
10982 else => unreachable,10333 else => unreachable,
10983 };10334 };
1098410335
10985 const fn_llvm_ty = (try o.builder.fnType(llvm_usize, &(.{llvm_usize} ** 2), .normal)).toLlvm(&o.builder);10336 return fg.wip.callAsm(
10986 const array_ptr_as_usize = try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, "");10337 .none,
10987 const args = [_]*llvm.Value{ array_ptr_as_usize.toLlvm(&fg.wip), default_value.toLlvm(&fg.wip) };10338 try o.builder.fnType(llvm_usize, &.{ llvm_usize, llvm_usize }, .normal),
10988 const asm_fn = llvm.getInlineAsm(10339 .{ .sideeffect = true },
10989 fn_llvm_ty,10340 try o.builder.string(arch_specific.template),
10990 arch_specific.template.ptr,10341 try o.builder.string(arch_specific.constraints),
10991 arch_specific.template.len,10342 &.{ try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, ""), default_value },
10992 arch_specific.constraints.ptr,10343 "",
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,
11003 );10344 );
11004 return call;
11005 }10345 }
1100610346
11007 fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type {10347 fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type {
...@@ -11032,17 +10372,17 @@ fn toLlvmAtomicRmwBinOp(...@@ -11032,17 +10372,17 @@ fn toLlvmAtomicRmwBinOp(
11032 op: std.builtin.AtomicRmwOp,10372 op: std.builtin.AtomicRmwOp,
11033 is_signed: bool,10373 is_signed: bool,
11034 is_float: bool,10374 is_float: bool,
11035) llvm.AtomicRMWBinOp {10375) Builder.Function.Instruction.AtomicRmw.Operation {
11036 return switch (op) {10376 return switch (op) {
11037 .Xchg => .Xchg,10377 .Xchg => .xchg,
11038 .Add => if (is_float) .FAdd else return .Add,10378 .Add => if (is_float) .fadd else return .add,
11039 .Sub => if (is_float) .FSub else return .Sub,10379 .Sub => if (is_float) .fsub else return .sub,
11040 .And => .And,10380 .And => .@"and",
11041 .Nand => .Nand,10381 .Nand => .nand,
11042 .Or => .Or,10382 .Or => .@"or",
11043 .Xor => .Xor,10383 .Xor => .xor,
11044 .Max => if (is_float) .FMax else if (is_signed) .Max else return .UMax,10384 .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,10385 .Min => if (is_float) .fmin else if (is_signed) .min else return .umin,
11046 };10386 };
11047}10387}
1104810388
...@@ -12008,15 +11348,19 @@ fn buildAllocaInner(...@@ -12008,15 +11348,19 @@ fn buildAllocaInner(
1200811348
12009 const alloca = blk: {11349 const alloca = blk: {
12010 const prev_cursor = wip.cursor;11350 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;
12012 defer {11355 defer {
12013 wip.cursor = prev_cursor;11356 wip.cursor = prev_cursor;
12014 if (wip.cursor.block == .entry) wip.cursor.instruction += 1;11357 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);
12016 }11360 }
1201711361
12018 wip.cursor = .{ .block = .entry };11362 wip.cursor = .{ .block = .entry };
12019 wip.llvm.builder.clearCurrentDebugLocation();11363 if (wip.builder.useLibLlvm()) wip.llvm.builder.clearCurrentDebugLocation();
12020 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");11364 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");
12021 };11365 };
1202211366
src/codegen/llvm/Builder.zig+3028-1057
...@@ -13,6 +13,7 @@ llvm: if (build_options.have_llvm) struct {...@@ -13,6 +13,7 @@ llvm: if (build_options.have_llvm) struct {
13 types: std.ArrayListUnmanaged(*llvm.Type),13 types: std.ArrayListUnmanaged(*llvm.Type),
14 globals: std.ArrayListUnmanaged(*llvm.Value),14 globals: std.ArrayListUnmanaged(*llvm.Value),
15 constants: std.ArrayListUnmanaged(*llvm.Value),15 constants: std.ArrayListUnmanaged(*llvm.Value),
16 replacements: std.AutoHashMapUnmanaged(*llvm.Value, Global.Index),
16} else void,17} else void,
1718
18source_filename: String,19source_filename: String,
...@@ -50,10 +51,12 @@ constant_extra: std.ArrayListUnmanaged(u32),...@@ -50,10 +51,12 @@ constant_extra: std.ArrayListUnmanaged(u32),
50constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb),51constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb),
5152
52pub const expected_args_len = 16;53pub const expected_args_len = 16;
54pub const expected_attrs_len = 16;
53pub const expected_fields_len = 32;55pub const expected_fields_len = 32;
54pub const expected_gep_indices_len = 8;56pub const expected_gep_indices_len = 8;
55pub const expected_cases_len = 8;57pub const expected_cases_len = 8;
56pub const expected_incoming_len = 8;58pub const expected_incoming_len = 8;
59pub const expected_intrinsic_name_len = 64;
5760
58pub const Options = struct {61pub const Options = struct {
59 allocator: Allocator,62 allocator: Allocator,
...@@ -151,11 +154,14 @@ pub const Type = enum(u32) {...@@ -151,11 +154,14 @@ pub const Type = enum(u32) {
151 i80,154 i80,
152 i128,155 i128,
153 ptr,156 ptr,
157 @"ptr addrspace(4)",
154158
155 none = std.math.maxInt(u32),159 none = std.math.maxInt(u32),
156 _,160 _,
157161
158 pub const err_int = Type.i16;162 pub const err_int = Type.i16;
163 pub const ptr_amdgpu_constant =
164 @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));
159165
160 pub const Tag = enum(u4) {166 pub const Tag = enum(u4) {
161 simple,167 simple,
...@@ -391,7 +397,7 @@ pub const Type = enum(u32) {...@@ -391,7 +397,7 @@ pub const Type = enum(u32) {
391 .double, .i64, .x86_mmx => 64,397 .double, .i64, .x86_mmx => 64,
392 .x86_fp80, .i80 => 80,398 .x86_fp80, .i80 => 80,
393 .fp128, .ppc_fp128, .i128 => 128,399 .fp128, .ppc_fp128, .i128 => 128,
394 .ptr => @panic("TODO: query data layout"),400 .ptr, .@"ptr addrspace(4)" => @panic("TODO: query data layout"),
395 _ => {401 _ => {
396 const item = builder.type_items.items[@intFromEnum(self)];402 const item = builder.type_items.items[@intFromEnum(self)];
397 return switch (item.tag) {403 return switch (item.tag) {
...@@ -690,7 +696,7 @@ pub const Type = enum(u32) {...@@ -690,7 +696,7 @@ pub const Type = enum(u32) {
690 }696 }
691 },697 },
692 .integer => try writer.print("i{d}", .{item.data}),698 .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))}),
694 .target => {700 .target => {
695 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);701 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
696 const types = extra.trail.next(extra.data.types_len, Type, data.builder);702 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
...@@ -795,6 +801,7 @@ pub const Type = enum(u32) {...@@ -795,6 +801,7 @@ pub const Type = enum(u32) {
795 .i80,801 .i80,
796 .i128,802 .i128,
797 .ptr,803 .ptr,
804 .@"ptr addrspace(4)",
798 => true,805 => true,
799 .none => unreachable,806 .none => unreachable,
800 _ => {807 _ => {
...@@ -1151,13 +1158,13 @@ pub const Attribute = union(Kind) {...@@ -1151,13 +1158,13 @@ pub const Attribute = union(Kind) {
1151 .sret,1158 .sret,
1152 .elementtype,1159 .elementtype,
1153 => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }),1160 => |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}),
1155 .dereferenceable,1162 .dereferenceable,
1156 .dereferenceable_or_null,1163 .dereferenceable_or_null,
1157 => |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }),1164 => |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }),
1158 .nofpclass => |fpclass| {1165 .nofpclass => |fpclass| {
1159 const Int = @typeInfo(FpClass).Struct.backing_integer.?;1166 const Int = @typeInfo(FpClass).Struct.backing_integer.?;
1160 try writer.print("{s}(", .{@tagName(attribute)});1167 try writer.print(" {s}(", .{@tagName(attribute)});
1161 var any = false;1168 var any = false;
1162 var remaining: Int = @bitCast(fpclass);1169 var remaining: Int = @bitCast(fpclass);
1163 inline for (@typeInfo(FpClass).Struct.decls) |decl| {1170 inline for (@typeInfo(FpClass).Struct.decls) |decl| {
...@@ -1175,13 +1182,13 @@ pub const Attribute = union(Kind) {...@@ -1175,13 +1182,13 @@ pub const Attribute = union(Kind) {
1175 },1182 },
1176 .alignstack => |alignment| try writer.print(1183 .alignstack => |alignment| try writer.print(
1177 if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null)1184 if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null)
1178 "{s}={d}"1185 " {s}={d}"
1179 else1186 else
1180 "{s}({d})",1187 " {s}({d})",
1181 .{ @tagName(attribute), alignment.toByteUnits() orelse return },1188 .{ @tagName(attribute), alignment.toByteUnits() orelse return },
1182 ),1189 ),
1183 .allockind => |allockind| {1190 .allockind => |allockind| {
1184 try writer.print("{s}(\"", .{@tagName(attribute)});1191 try writer.print(" {s}(\"", .{@tagName(attribute)});
1185 var any = false;1192 var any = false;
1186 inline for (@typeInfo(AllocKind).Struct.fields) |field| {1193 inline for (@typeInfo(AllocKind).Struct.fields) |field| {
1187 if (comptime std.mem.eql(u8, field.name, "_")) continue;1194 if (comptime std.mem.eql(u8, field.name, "_")) continue;
...@@ -1196,22 +1203,30 @@ pub const Attribute = union(Kind) {...@@ -1196,22 +1203,30 @@ pub const Attribute = union(Kind) {
1196 try writer.writeAll("\")");1203 try writer.writeAll("\")");
1197 },1204 },
1198 .allocsize => |allocsize| {1205 .allocsize => |allocsize| {
1199 try writer.print("{s}({d}", .{ @tagName(attribute), allocsize.elem_size });1206 try writer.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });
1200 if (allocsize.num_elems != AllocSize.none)1207 if (allocsize.num_elems != AllocSize.none)
1201 try writer.print(",{d}", .{allocsize.num_elems});1208 try writer.print(",{d}", .{allocsize.num_elems});
1202 try writer.writeByte(')');1209 try writer.writeByte(')');
1203 },1210 },
1204 .memory => |memory| try writer.print("{s}({s}, argmem: {s}, inaccessiblemem: {s})", .{1211 .memory => |memory| {
1205 @tagName(attribute),1212 try writer.print(" {s}(", .{@tagName(attribute)});
1206 @tagName(memory.other),1213 var any = memory.other != .none or
1207 @tagName(memory.argmem),1214 (memory.argmem == .none and memory.inaccessiblemem == .none);
1208 @tagName(memory.inaccessiblemem),1215 if (any) try writer.writeAll(@tagName(memory.other));
1209 }),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 },
1210 .uwtable => |uwtable| if (uwtable != .none) {1225 .uwtable => |uwtable| if (uwtable != .none) {
1211 try writer.writeAll(@tagName(attribute));1226 try writer.print(" {s}", .{@tagName(attribute)});
1212 if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)});1227 if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)});
1213 },1228 },
1214 .vscale_range => |vscale_range| try writer.print("{s}({d},{d})", .{1229 .vscale_range => |vscale_range| try writer.print(" {s}({d},{d})", .{
1215 @tagName(attribute),1230 @tagName(attribute),
1216 vscale_range.min.toByteUnits().?,1231 vscale_range.min.toByteUnits().?,
1217 vscale_range.max.toByteUnits() orelse 0,1232 vscale_range.max.toByteUnits() orelse 0,
...@@ -1335,21 +1350,29 @@ pub const Attribute = union(Kind) {...@@ -1335,21 +1350,29 @@ pub const Attribute = union(Kind) {
1335 //sanitize_memtag,1350 //sanitize_memtag,
1336 sanitize_address_dyninit,1351 sanitize_address_dyninit,
13371352
1338 string = std.math.maxInt(u31) - 1,1353 string = std.math.maxInt(u31),
1339 none = std.math.maxInt(u31),1354 none = std.math.maxInt(u32),
1340 _,1355 _,
13411356
1342 pub const len = @typeInfo(Kind).Enum.fields.len - 2;1357 pub const len = @typeInfo(Kind).Enum.fields.len - 2;
13431358
1344 pub fn fromString(str: String) Kind {1359 pub fn fromString(str: String) Kind {
1345 assert(!str.isAnon());1360 assert(!str.isAnon());
1346 return @enumFromInt(@intFromEnum(str));1361 const kind: Kind = @enumFromInt(@intFromEnum(str));
1362 assert(kind != .none);
1363 return kind;
1347 }1364 }
13481365
1349 fn toString(self: Kind) ?String {1366 fn toString(self: Kind) ?String {
1367 assert(self != .none);
1350 const str: String = @enumFromInt(@intFromEnum(self));1368 const str: String = @enumFromInt(@intFromEnum(self));
1351 return if (str.isAnon()) null else str;1369 return if (str.isAnon()) null else str;
1352 }1370 }
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 }
1353 };1376 };
13541377
1355 pub const FpClass = packed struct(u32) {1378 pub const FpClass = packed struct(u32) {
...@@ -1424,12 +1447,16 @@ pub const Attribute = union(Kind) {...@@ -1424,12 +1447,16 @@ pub const Attribute = union(Kind) {
1424 };1447 };
14251448
1426 pub const Memory = packed struct(u32) {1449 pub const Memory = packed struct(u32) {
1427 argmem: Effect,1450 argmem: Effect = .none,
1428 inaccessiblemem: Effect,1451 inaccessiblemem: Effect = .none,
1429 other: Effect,1452 other: Effect = .none,
1430 _: u26 = 0,1453 _: u26 = 0,
14311454
1432 pub const Effect = enum(u2) { none, read, write, readwrite };1455 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 }
1433 };1460 };
14341461
1435 pub const UwTable = enum(u32) {1462 pub const UwTable = enum(u32) {
...@@ -1683,17 +1710,17 @@ pub const FunctionAttributes = enum(u32) {...@@ -1683,17 +1710,17 @@ pub const FunctionAttributes = enum(u32) {
1683};1710};
16841711
1685pub const Linkage = enum {1712pub const Linkage = enum {
1686 external,
1687 private,1713 private,
1688 internal,1714 internal,
1689 available_externally,
1690 linkonce,
1691 weak,1715 weak,
1692 common,1716 weak_odr,
1717 linkonce,
1718 linkonce_odr,
1719 available_externally,
1693 appending,1720 appending,
1721 common,
1694 extern_weak,1722 extern_weak,
1695 linkonce_odr,1723 external,
1696 weak_odr,
16971724
1698 pub fn format(1725 pub fn format(
1699 self: Linkage,1726 self: Linkage,
...@@ -1703,6 +1730,22 @@ pub const Linkage = enum {...@@ -1703,6 +1730,22 @@ pub const Linkage = enum {
1703 ) @TypeOf(writer).Error!void {1730 ) @TypeOf(writer).Error!void {
1704 if (self != .external) try writer.print(" {s}", .{@tagName(self)});1731 if (self != .external) try writer.print(" {s}", .{@tagName(self)});
1705 }1732 }
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 }
1706};1749};
17071750
1708pub const Preemption = enum {1751pub const Preemption = enum {
...@@ -1733,6 +1776,14 @@ pub const Visibility = enum {...@@ -1733,6 +1776,14 @@ pub const Visibility = enum {
1733 ) @TypeOf(writer).Error!void {1776 ) @TypeOf(writer).Error!void {
1734 if (self != .default) try writer.print(" {s}", .{@tagName(self)});1777 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1735 }1778 }
1779
1780 fn toLlvm(self: Visibility) llvm.Visibility {
1781 return switch (self) {
1782 .default => .Default,
1783 .hidden => .Hidden,
1784 .protected => .Protected,
1785 };
1786 }
1736};1787};
17371788
1738pub const DllStorageClass = enum {1789pub const DllStorageClass = enum {
...@@ -1748,6 +1799,14 @@ pub const DllStorageClass = enum {...@@ -1748,6 +1799,14 @@ pub const DllStorageClass = enum {
1748 ) @TypeOf(writer).Error!void {1799 ) @TypeOf(writer).Error!void {
1749 if (self != .default) try writer.print(" {s}", .{@tagName(self)});1800 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1750 }1801 }
1802
1803 fn toLlvm(self: DllStorageClass) llvm.DLLStorageClass {
1804 return switch (self) {
1805 .default => .Default,
1806 .dllimport => .DLLImport,
1807 .dllexport => .DLLExport,
1808 };
1809 }
1751};1810};
17521811
1753pub const ThreadLocal = enum {1812pub const ThreadLocal = enum {
...@@ -1759,20 +1818,28 @@ pub const ThreadLocal = enum {...@@ -1759,20 +1818,28 @@ pub const ThreadLocal = enum {
17591818
1760 pub fn format(1819 pub fn format(
1761 self: ThreadLocal,1820 self: ThreadLocal,
1762 comptime _: []const u8,1821 comptime prefix: []const u8,
1763 _: std.fmt.FormatOptions,1822 _: std.fmt.FormatOptions,
1764 writer: anytype,1823 writer: anytype,
1765 ) @TypeOf(writer).Error!void {1824 ) @TypeOf(writer).Error!void {
1766 if (self == .default) return;1825 if (self == .default) return;
1767 try writer.writeAll(" thread_local");1826 try writer.print("{s}thread_local", .{prefix});
1768 if (self != .generaldynamic) {1827 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});
1769 try writer.writeByte('(');1828 }
1770 try writer.writeAll(@tagName(self));1829
1771 try writer.writeByte(')');1830 fn toLlvm(self: ThreadLocal) llvm.ThreadLocalMode {
1772 }1831 return switch (self) {
1832 .default => .NotThreadLocal,
1833 .generaldynamic => .GeneralDynamicTLSModel,
1834 .localdynamic => .LocalDynamicTLSModel,
1835 .initialexec => .InitialExecTLSModel,
1836 .localexec => .LocalExecTLSModel,
1837 };
1773 }1838 }
1774};1839};
17751840
1841pub const Mutability = enum { global, constant };
1842
1776pub const UnnamedAddr = enum {1843pub const UnnamedAddr = enum {
1777 default,1844 default,
1778 unnamed_addr,1845 unnamed_addr,
...@@ -1867,7 +1934,7 @@ pub const AddrSpace = enum(u24) {...@@ -1867,7 +1934,7 @@ pub const AddrSpace = enum(u24) {
1867 _: std.fmt.FormatOptions,1934 _: std.fmt.FormatOptions,
1868 writer: anytype,1935 writer: anytype,
1869 ) @TypeOf(writer).Error!void {1936 ) @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) });
1871 }1938 }
1872};1939};
18731940
...@@ -1908,7 +1975,7 @@ pub const Alignment = enum(u6) {...@@ -1908,7 +1975,7 @@ pub const Alignment = enum(u6) {
1908 _: std.fmt.FormatOptions,1975 _: std.fmt.FormatOptions,
1909 writer: anytype,1976 writer: anytype,
1910 ) @TypeOf(writer).Error!void {1977 ) @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 });
1912 }1979 }
1913};1980};
19141981
...@@ -2031,6 +2098,11 @@ pub const CallConv = enum(u10) {...@@ -2031,6 +2098,11 @@ pub const CallConv = enum(u10) {
2031 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),2098 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),
2032 }2099 }
2033 }2100 }
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 }
2034};2106};
20352107
2036pub const Global = struct {2108pub const Global = struct {
...@@ -2067,10 +2139,6 @@ pub const Global = struct {...@@ -2067,10 +2139,6 @@ pub const Global = struct {
2067 return self.unwrap(builder) == other.unwrap(builder);2139 return self.unwrap(builder) == other.unwrap(builder);
2068 }2140 }
20692141
2070 pub fn name(self: Index, builder: *const Builder) String {
2071 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
2072 }
2073
2074 pub fn ptr(self: Index, builder: *Builder) *Global {2142 pub fn ptr(self: Index, builder: *Builder) *Global {
2075 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];2143 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
2076 }2144 }
...@@ -2079,6 +2147,10 @@ pub const Global = struct {...@@ -2079,6 +2147,10 @@ pub const Global = struct {
2079 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];2147 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
2080 }2148 }
20812149
2150 pub fn name(self: Index, builder: *const Builder) String {
2151 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
2152 }
2153
2082 pub fn typeOf(self: Index, builder: *const Builder) Type {2154 pub fn typeOf(self: Index, builder: *const Builder) Type {
2083 return self.ptrConst(builder).type;2155 return self.ptrConst(builder).type;
2084 }2156 }
...@@ -2087,6 +2159,30 @@ pub const Global = struct {...@@ -2087,6 +2159,30 @@ pub const Global = struct {
2087 return @enumFromInt(@intFromEnum(Constant.first_global) + @intFromEnum(self));2159 return @enumFromInt(@intFromEnum(Constant.first_global) + @intFromEnum(self));
2088 }2160 }
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
2090 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {2186 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
2091 assert(builder.useLibLlvm());2187 assert(builder.useLibLlvm());
2092 return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))];2188 return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))];
...@@ -2122,9 +2218,36 @@ pub const Global = struct {...@@ -2122,9 +2218,36 @@ pub const Global = struct {
21222218
2123 pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void {2219 pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
2124 try builder.ensureUnusedGlobalCapacity(.empty);2220 try builder.ensureUnusedGlobalCapacity(.empty);
2221 if (builder.useLibLlvm())
2222 try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1);
2125 self.replaceAssumeCapacity(other, builder);2223 self.replaceAssumeCapacity(other, builder);
2126 }2224 }
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
2128 fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void {2251 fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void {
2129 const old_name = self.name(builder);2252 const old_name = self.name(builder);
2130 if (new_name == old_name) return;2253 if (new_name == old_name) return;
...@@ -2151,7 +2274,7 @@ pub const Global = struct {...@@ -2151,7 +2274,7 @@ pub const Global = struct {
2151 if (!builder.useLibLlvm()) return;2274 if (!builder.useLibLlvm()) return;
2152 const index = @intFromEnum(self.unwrap(builder));2275 const index = @intFromEnum(self.unwrap(builder));
2153 const name_slice = self.name(builder).slice(builder) orelse "";2276 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);
2155 }2278 }
21562279
2157 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {2280 fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
...@@ -2161,13 +2284,8 @@ pub const Global = struct {...@@ -2161,13 +2284,8 @@ pub const Global = struct {
2161 if (builder.useLibLlvm()) {2284 if (builder.useLibLlvm()) {
2162 const self_llvm = self.toLlvm(builder);2285 const self_llvm = self.toLlvm(builder);
2163 self_llvm.replaceAllUsesWith(other.toLlvm(builder));2286 self_llvm.replaceAllUsesWith(other.toLlvm(builder));
2164 switch (self.ptr(builder).kind) {2287 self_llvm.removeGlobalValue();
2165 .alias,2288 builder.llvm.replacements.putAssumeCapacityNoClobber(self_llvm, other);
2166 .variable,
2167 => self_llvm.deleteGlobal(),
2168 .function => self_llvm.deleteFunction(),
2169 .replaced => unreachable,
2170 }
2171 }2289 }
2172 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };2290 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
2173 }2291 }
...@@ -2179,42 +2297,17 @@ pub const Global = struct {...@@ -2179,42 +2297,17 @@ pub const Global = struct {
2179 };2297 };
2180 }2298 }
2181 };2299 };
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 }
2201};2300};
22022301
2203pub const Alias = struct {2302pub const Alias = struct {
2204 global: Global.Index,2303 global: Global.Index,
2205 thread_local: ThreadLocal = .default,2304 thread_local: ThreadLocal = .default,
2206 init: Constant = .no_init,2305 aliasee: Constant = .no_init,
22072306
2208 pub const Index = enum(u32) {2307 pub const Index = enum(u32) {
2209 none = std.math.maxInt(u32),2308 none = std.math.maxInt(u32),
2210 _,2309 _,
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
2218 pub fn ptr(self: Index, builder: *Builder) *Alias {2311 pub fn ptr(self: Index, builder: *Builder) *Alias {
2219 return &builder.aliases.items[@intFromEnum(self)];2312 return &builder.aliases.items[@intFromEnum(self)];
2220 }2313 }
...@@ -2223,6 +2316,14 @@ pub const Alias = struct {...@@ -2223,6 +2316,14 @@ pub const Alias = struct {
2223 return &builder.aliases.items[@intFromEnum(self)];2316 return &builder.aliases.items[@intFromEnum(self)];
2224 }2317 }
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
2226 pub fn typeOf(self: Index, builder: *const Builder) Type {2327 pub fn typeOf(self: Index, builder: *const Builder) Type {
2227 return self.ptrConst(builder).global.typeOf(builder);2328 return self.ptrConst(builder).global.typeOf(builder);
2228 }2329 }
...@@ -2235,7 +2336,18 @@ pub const Alias = struct {...@@ -2235,7 +2336,18 @@ pub const Alias = struct {
2235 return self.toConst(builder).toValue();2336 return self.toConst(builder).toValue();
2236 }2337 }
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 {
2239 return self.ptrConst(builder).global.toLlvm(builder);2351 return self.ptrConst(builder).global.toLlvm(builder);
2240 }2352 }
2241 };2353 };
...@@ -2244,7 +2356,7 @@ pub const Alias = struct {...@@ -2244,7 +2356,7 @@ pub const Alias = struct {
2244pub const Variable = struct {2356pub const Variable = struct {
2245 global: Global.Index,2357 global: Global.Index,
2246 thread_local: ThreadLocal = .default,2358 thread_local: ThreadLocal = .default,
2247 mutability: enum { global, constant } = .global,2359 mutability: Mutability = .global,
2248 init: Constant = .no_init,2360 init: Constant = .no_init,
2249 section: String = .none,2361 section: String = .none,
2250 alignment: Alignment = .default,2362 alignment: Alignment = .default,
...@@ -2261,6 +2373,14 @@ pub const Variable = struct {...@@ -2261,6 +2373,14 @@ pub const Variable = struct {
2261 return &builder.variables.items[@intFromEnum(self)];2373 return &builder.variables.items[@intFromEnum(self)];
2262 }2374 }
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
2264 pub fn typeOf(self: Index, builder: *const Builder) Type {2384 pub fn typeOf(self: Index, builder: *const Builder) Type {
2265 return self.ptrConst(builder).global.typeOf(builder);2385 return self.ptrConst(builder).global.typeOf(builder);
2266 }2386 }
...@@ -2269,14 +2389,1407 @@ pub const Variable = struct {...@@ -2269,14 +2389,1407 @@ pub const Variable = struct {
2269 return self.ptrConst(builder).global.toConst();2389 return self.ptrConst(builder).global.toConst();
2270 }2390 }
22712391
2272 pub fn toValue(self: Index, builder: *const Builder) Value {2392 pub fn toValue(self: Index, builder: *const Builder) Value {
2273 return self.toConst(builder).toValue();2393 return self.toConst(builder).toValue();
2274 }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 {3775 .@"wasm.memory.size" = .{
2277 return self.ptrConst(builder).global.toLlvm(builder);3776 .ret_len = 1,
2278 }3777 .params = &.{
2279 };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 });
2280};3793};
22813794
2282pub const Function = struct {3795pub const Function = struct {
...@@ -2303,6 +3816,14 @@ pub const Function = struct {...@@ -2303,6 +3816,14 @@ pub const Function = struct {
2303 return &builder.functions.items[@intFromEnum(self)];3816 return &builder.functions.items[@intFromEnum(self)];
2304 }3817 }
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
2306 pub fn typeOf(self: Index, builder: *const Builder) Type {3827 pub fn typeOf(self: Index, builder: *const Builder) Type {
2307 return self.ptrConst(builder).global.typeOf(builder);3828 return self.ptrConst(builder).global.typeOf(builder);
2308 }3829 }
...@@ -2315,6 +3836,110 @@ pub const Function = struct {...@@ -2315,6 +3836,110 @@ pub const Function = struct {
2315 return self.toConst(builder).toValue();3836 return self.toConst(builder).toValue();
2316 }3837 }
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
2318 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {3943 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
2319 return self.ptrConst(builder).global.toLlvm(builder);3944 return self.ptrConst(builder).global.toLlvm(builder);
2320 }3945 }
...@@ -2342,12 +3967,15 @@ pub const Function = struct {...@@ -2342,12 +3967,15 @@ pub const Function = struct {
2342 arg,3967 arg,
2343 ashr,3968 ashr,
2344 @"ashr exact",3969 @"ashr exact",
3970 atomicrmw,
2345 bitcast,3971 bitcast,
2346 block,3972 block,
2347 br,3973 br,
2348 br_cond,3974 br_cond,
2349 call,3975 call,
2350 @"call fast",3976 @"call fast",
3977 cmpxchg,
3978 @"cmpxchg weak",
2351 extractelement,3979 extractelement,
2352 extractvalue,3980 extractvalue,
2353 fadd,3981 fadd,
...@@ -2414,43 +4042,8 @@ pub const Function = struct {...@@ -2414,43 +4042,8 @@ pub const Function = struct {
2414 insertelement,4042 insertelement,
2415 insertvalue,4043 insertvalue,
2416 inttoptr,4044 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.",
2450 load,4045 load,
2451 @"load atomic",4046 @"load atomic",
2452 @"load atomic volatile",
2453 @"load volatile",
2454 lshr,4047 lshr,
2455 @"lshr exact",4048 @"lshr exact",
2456 mul,4049 mul,
...@@ -2481,8 +4074,6 @@ pub const Function = struct {...@@ -2481,8 +4074,6 @@ pub const Function = struct {
2481 srem,4074 srem,
2482 store,4075 store,
2483 @"store atomic",4076 @"store atomic",
2484 @"store atomic volatile",
2485 @"store volatile",
2486 sub,4077 sub,
2487 @"sub nsw",4078 @"sub nsw",
2488 @"sub nuw",4079 @"sub nuw",
...@@ -2495,7 +4086,6 @@ pub const Function = struct {...@@ -2495,7 +4086,6 @@ pub const Function = struct {
2495 @"udiv exact",4086 @"udiv exact",
2496 urem,4087 urem,
2497 uitofp,4088 uitofp,
2498 unimplemented,
2499 @"unreachable",4089 @"unreachable",
2500 va_arg,4090 va_arg,
2501 xor,4091 xor,
...@@ -2536,8 +4126,6 @@ pub const Function = struct {...@@ -2536,8 +4126,6 @@ pub const Function = struct {
2536 .@"ret void",4126 .@"ret void",
2537 .store,4127 .store,
2538 .@"store atomic",4128 .@"store atomic",
2539 .@"store atomic volatile",
2540 .@"store volatile",
2541 .@"switch",4129 .@"switch",
2542 .@"unreachable",4130 .@"unreachable",
2543 => false,4131 => false,
...@@ -2549,7 +4137,6 @@ pub const Function = struct {...@@ -2549,7 +4137,6 @@ pub const Function = struct {
2549 .@"notail call fast",4137 .@"notail call fast",
2550 .@"tail call",4138 .@"tail call",
2551 .@"tail call fast",4139 .@"tail call fast",
2552 .unimplemented,
2553 => self.typeOfWip(wip) != .void,4140 => self.typeOfWip(wip) != .void,
2554 else => true,4141 else => true,
2555 };4142 };
...@@ -2575,22 +4162,6 @@ pub const Function = struct {...@@ -2575,22 +4162,6 @@ pub const Function = struct {
2575 .@"frem fast",4162 .@"frem fast",
2576 .fsub,4163 .fsub,
2577 .@"fsub fast",4164 .@"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.",
2594 .lshr,4165 .lshr,
2595 .@"lshr exact",4166 .@"lshr exact",
2596 .mul,4167 .mul,
...@@ -2635,6 +4206,7 @@ pub const Function = struct {...@@ -2635,6 +4206,7 @@ pub const Function = struct {
2635 ),4206 ),
2636 .arg => wip.function.typeOf(wip.builder)4207 .arg => wip.function.typeOf(wip.builder)
2637 .functionParameters(wip.builder)[instruction.data],4208 .functionParameters(wip.builder)[instruction.data],
4209 .atomicrmw => wip.extraData(AtomicRmw, instruction.data).val.typeOfWip(wip),
2638 .block => .label,4210 .block => .label,
2639 .br,4211 .br,
2640 .br_cond,4212 .br_cond,
...@@ -2643,8 +4215,6 @@ pub const Function = struct {...@@ -2643,8 +4215,6 @@ pub const Function = struct {
2643 .@"ret void",4215 .@"ret void",
2644 .store,4216 .store,
2645 .@"store atomic",4217 .@"store atomic",
2646 .@"store atomic volatile",
2647 .@"store volatile",
2648 .@"switch",4218 .@"switch",
2649 .@"unreachable",4219 .@"unreachable",
2650 => .none,4220 => .none,
...@@ -2657,6 +4227,12 @@ pub const Function = struct {...@@ -2657,6 +4227,12 @@ pub const Function = struct {
2657 .@"tail call",4227 .@"tail call",
2658 .@"tail call fast",4228 .@"tail call fast",
2659 => wip.extraData(Call, instruction.data).ty.functionReturn(wip.builder),4229 => 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,
2660 .extractelement => wip.extraData(ExtractElement, instruction.data)4236 .extractelement => wip.extraData(ExtractElement, instruction.data)
2661 .val.typeOfWip(wip).childType(wip.builder),4237 .val.typeOfWip(wip).childType(wip.builder),
2662 .extractvalue => {4238 .extractvalue => {
...@@ -2710,22 +4286,6 @@ pub const Function = struct {...@@ -2710,22 +4286,6 @@ pub const Function = struct {
2710 .changeScalarAssumeCapacity(.i1, wip.builder),4286 .changeScalarAssumeCapacity(.i1, wip.builder),
2711 .fneg,4287 .fneg,
2712 .@"fneg fast",4288 .@"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.",
2729 => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip),4289 => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip),
2730 .getelementptr,4290 .getelementptr,
2731 .@"getelementptr inbounds",4291 .@"getelementptr inbounds",
...@@ -2744,8 +4304,6 @@ pub const Function = struct {...@@ -2744,8 +4304,6 @@ pub const Function = struct {
2744 .insertvalue => wip.extraData(InsertValue, instruction.data).val.typeOfWip(wip),4304 .insertvalue => wip.extraData(InsertValue, instruction.data).val.typeOfWip(wip),
2745 .load,4305 .load,
2746 .@"load atomic",4306 .@"load atomic",
2747 .@"load atomic volatile",
2748 .@"load volatile",
2749 => wip.extraData(Load, instruction.data).type,4307 => wip.extraData(Load, instruction.data).type,
2750 .phi,4308 .phi,
2751 .@"phi fast",4309 .@"phi fast",
...@@ -2760,9 +4318,7 @@ pub const Function = struct {...@@ -2760,9 +4318,7 @@ pub const Function = struct {
2760 wip.builder,4318 wip.builder,
2761 );4319 );
2762 },4320 },
2763 .unimplemented => @enumFromInt(instruction.data),
2764 .va_arg => wip.extraData(VaArg, instruction.data).type,4321 .va_arg => wip.extraData(VaArg, instruction.data).type,
2765 .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip),
2766 };4322 };
2767 }4323 }
27684324
...@@ -2791,22 +4347,6 @@ pub const Function = struct {...@@ -2791,22 +4347,6 @@ pub const Function = struct {
2791 .@"frem fast",4347 .@"frem fast",
2792 .fsub,4348 .fsub,
2793 .@"fsub fast",4349 .@"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.",
2810 .lshr,4350 .lshr,
2811 .@"lshr exact",4351 .@"lshr exact",
2812 .mul,4352 .mul,
...@@ -2851,6 +4391,8 @@ pub const Function = struct {...@@ -2851,6 +4391,8 @@ pub const Function = struct {
2851 ),4391 ),
2852 .arg => function.global.typeOf(builder)4392 .arg => function.global.typeOf(builder)
2853 .functionParameters(builder)[instruction.data],4393 .functionParameters(builder)[instruction.data],
4394 .atomicrmw => function.extraData(AtomicRmw, instruction.data)
4395 .val.typeOf(function_index, builder),
2854 .block => .label,4396 .block => .label,
2855 .br,4397 .br,
2856 .br_cond,4398 .br_cond,
...@@ -2859,8 +4401,6 @@ pub const Function = struct {...@@ -2859,8 +4401,6 @@ pub const Function = struct {
2859 .@"ret void",4401 .@"ret void",
2860 .store,4402 .store,
2861 .@"store atomic",4403 .@"store atomic",
2862 .@"store atomic volatile",
2863 .@"store volatile",
2864 .@"switch",4404 .@"switch",
2865 .@"unreachable",4405 .@"unreachable",
2866 => .none,4406 => .none,
...@@ -2873,6 +4413,13 @@ pub const Function = struct {...@@ -2873,6 +4413,13 @@ pub const Function = struct {
2873 .@"tail call",4413 .@"tail call",
2874 .@"tail call fast",4414 .@"tail call fast",
2875 => function.extraData(Call, instruction.data).ty.functionReturn(builder),4415 => 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,
2876 .extractelement => function.extraData(ExtractElement, instruction.data)4423 .extractelement => function.extraData(ExtractElement, instruction.data)
2877 .val.typeOf(function_index, builder).childType(builder),4424 .val.typeOf(function_index, builder).childType(builder),
2878 .extractvalue => {4425 .extractvalue => {
...@@ -2927,22 +4474,6 @@ pub const Function = struct {...@@ -2927,22 +4474,6 @@ pub const Function = struct {
2927 .changeScalarAssumeCapacity(.i1, builder),4474 .changeScalarAssumeCapacity(.i1, builder),
2928 .fneg,4475 .fneg,
2929 .@"fneg fast",4476 .@"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.",
2946 => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder),4477 => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder),
2947 .getelementptr,4478 .getelementptr,
2948 .@"getelementptr inbounds",4479 .@"getelementptr inbounds",
...@@ -2963,8 +4494,6 @@ pub const Function = struct {...@@ -2963,8 +4494,6 @@ pub const Function = struct {
2963 .val.typeOf(function_index, builder),4494 .val.typeOf(function_index, builder),
2964 .load,4495 .load,
2965 .@"load atomic",4496 .@"load atomic",
2966 .@"load atomic volatile",
2967 .@"load volatile",
2968 => function.extraData(Load, instruction.data).type,4497 => function.extraData(Load, instruction.data).type,
2969 .phi,4498 .phi,
2970 .@"phi fast",4499 .@"phi fast",
...@@ -2979,9 +4508,7 @@ pub const Function = struct {...@@ -2979,9 +4508,7 @@ pub const Function = struct {
2979 builder,4508 builder,
2980 );4509 );
2981 },4510 },
2982 .unimplemented => @enumFromInt(instruction.data),
2983 .va_arg => function.extraData(VaArg, instruction.data).type,4511 .va_arg => function.extraData(VaArg, instruction.data).type,
2984 .@"llvm.fma." => function.extraData(FusedMultiplyAdd, instruction.data).a.typeOf(function_index, builder),
2985 };4512 };
2986 }4513 }
29874514
...@@ -3023,12 +4550,14 @@ pub const Function = struct {...@@ -3023,12 +4550,14 @@ pub const Function = struct {
3023 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };4550 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };
3024 }4551 }
30254552
3026 pub fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value {4553 fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value {
3027 assert(wip.builder.useLibLlvm());4554 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);
3029 }4558 }
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 {
3032 return if (wip.builder.strip)4561 return if (wip.builder.strip)
3033 ""4562 ""
3034 else4563 else
...@@ -3074,12 +4603,6 @@ pub const Function = struct {...@@ -3074,12 +4603,6 @@ pub const Function = struct {
3074 mask: Value,4603 mask: Value,
3075 };4604 };
30764605
3077 pub const FusedMultiplyAdd = struct {
3078 a: Value,
3079 b: Value,
3080 c: Value,
3081 };
3082
3083 pub const ExtractValue = struct {4606 pub const ExtractValue = struct {
3084 val: Value,4607 val: Value,
3085 indices_len: u32,4608 indices_len: u32,
...@@ -3107,15 +4630,70 @@ pub const Function = struct {...@@ -3107,15 +4630,70 @@ pub const Function = struct {
3107 };4630 };
31084631
3109 pub const Load = struct {4632 pub const Load = struct {
4633 info: MemoryAccessInfo,
3110 type: Type,4634 type: Type,
3111 ptr: Value,4635 ptr: Value,
3112 info: MemoryAccessInfo,
3113 };4636 };
31144637
3115 pub const Store = struct {4638 pub const Store = struct {
4639 info: MemoryAccessInfo,
3116 val: Value,4640 val: Value,
3117 ptr: Value,4641 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 {
3118 info: MemoryAccessInfo,4654 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 };
3119 };4697 };
31204698
3121 pub const GetElementPtr = struct {4699 pub const GetElementPtr = struct {
...@@ -3487,24 +5065,7 @@ pub const WipFunction = struct {...@@ -3487,24 +5065,7 @@ pub const WipFunction = struct {
3487 switch (tag) {5065 switch (tag) {
3488 .fneg,5066 .fneg,
3489 .@"fneg fast",5067 .@"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.",
3503 => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()),5068 => 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)),
3508 else => unreachable,5069 else => unreachable,
3509 }5070 }
3510 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);5071 try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
...@@ -3513,43 +5074,10 @@ pub const WipFunction = struct {...@@ -3513,43 +5074,10 @@ pub const WipFunction = struct {
3513 switch (tag) {5074 switch (tag) {
3514 .fneg => self.llvm.builder.setFastMath(false),5075 .fneg => self.llvm.builder.setFastMath(false),
3515 .@"fneg fast" => self.llvm.builder.setFastMath(true),5076 .@"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 => {},
3533 else => unreachable,5077 else => unreachable,
3534 }5078 }
3535 self.llvm.instructions.appendAssumeCapacity(switch (tag) {5079 self.llvm.instructions.appendAssumeCapacity(switch (tag) {
3536 .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg,5080 .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,
3553 else => unreachable,5081 else => unreachable,
3554 }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self)));5082 }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self)));
3555 }5083 }
...@@ -3593,20 +5121,6 @@ pub const WipFunction = struct {...@@ -3593,20 +5121,6 @@ pub const WipFunction = struct {
3593 .@"frem fast",5121 .@"frem fast",
3594 .fsub,5122 .fsub,
3595 .@"fsub fast",5123 .@"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.",
3610 .lshr,5124 .lshr,
3611 .@"lshr exact",5125 .@"lshr exact",
3612 .mul,5126 .mul,
...@@ -3627,9 +5141,6 @@ pub const WipFunction = struct {...@@ -3627,9 +5141,6 @@ pub const WipFunction = struct {
3627 .urem,5141 .urem,
3628 .xor,5142 .xor,
3629 => assert(lhs.typeOfWip(self) == rhs.typeOfWip(self)),5143 => 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),
3633 else => unreachable,5144 else => unreachable,
3634 }5145 }
3635 try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0);5146 try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0);
...@@ -3665,22 +5176,6 @@ pub const WipFunction = struct {...@@ -3665,22 +5176,6 @@ pub const WipFunction = struct {
3665 .fmul, .@"fmul fast" => &llvm.Builder.buildFMul,5176 .fmul, .@"fmul fast" => &llvm.Builder.buildFMul,
3666 .frem, .@"frem fast" => &llvm.Builder.buildFRem,5177 .frem, .@"frem fast" => &llvm.Builder.buildFRem,
3667 .fsub, .@"fsub fast" => &llvm.Builder.buildFSub,5178 .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,
3684 .lshr => &llvm.Builder.buildLShr,5179 .lshr => &llvm.Builder.buildLShr,
3685 .@"lshr exact" => &llvm.Builder.buildLShrExact,5180 .@"lshr exact" => &llvm.Builder.buildLShrExact,
3686 .mul => &llvm.Builder.buildMul,5181 .mul => &llvm.Builder.buildMul,
...@@ -3934,21 +5429,21 @@ pub const WipFunction = struct {...@@ -3934,21 +5429,21 @@ pub const WipFunction = struct {
39345429
3935 pub fn load(5430 pub fn load(
3936 self: *WipFunction,5431 self: *WipFunction,
3937 kind: MemoryAccessKind,5432 access_kind: MemoryAccessKind,
3938 ty: Type,5433 ty: Type,
3939 ptr: Value,5434 ptr: Value,
3940 alignment: Alignment,5435 alignment: Alignment,
3941 name: []const u8,5436 name: []const u8,
3942 ) Allocator.Error!Value {5437 ) 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);
3944 }5439 }
39455440
3946 pub fn loadAtomic(5441 pub fn loadAtomic(
3947 self: *WipFunction,5442 self: *WipFunction,
3948 kind: MemoryAccessKind,5443 access_kind: MemoryAccessKind,
3949 ty: Type,5444 ty: Type,
3950 ptr: Value,5445 ptr: Value,
3951 scope: SyncScope,5446 sync_scope: SyncScope,
3952 ordering: AtomicOrdering,5447 ordering: AtomicOrdering,
3953 alignment: Alignment,5448 alignment: Alignment,
3954 name: []const u8,5449 name: []const u8,
...@@ -3957,22 +5452,21 @@ pub const WipFunction = struct {...@@ -3957,22 +5452,21 @@ pub const WipFunction = struct {
3957 try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0);5452 try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0);
3958 const instruction = try self.addInst(name, .{5453 const instruction = try self.addInst(name, .{
3959 .tag = switch (ordering) {5454 .tag = switch (ordering) {
3960 .none => switch (kind) {5455 .none => .load,
3961 .normal => .load,5456 else => .@"load atomic",
3962 .@"volatile" => .@"load volatile",
3963 },
3964 else => switch (kind) {
3965 .normal => .@"load atomic",
3966 .@"volatile" => .@"load atomic volatile",
3967 },
3968 },5457 },
3969 .data = self.addExtraAssumeCapacity(Instruction.Load{5458 .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 },
3970 .type = ty,5468 .type = ty,
3971 .ptr = ptr,5469 .ptr = ptr,
3972 .info = .{ .scope = switch (ordering) {
3973 .none => .system,
3974 else => scope,
3975 }, .ordering = ordering, .alignment = alignment },
3976 }),5470 }),
3977 });5471 });
3978 if (self.builder.useLibLlvm()) {5472 if (self.builder.useLibLlvm()) {
...@@ -3981,7 +5475,8 @@ pub const WipFunction = struct {...@@ -3981,7 +5475,8 @@ pub const WipFunction = struct {
3981 ptr.toLlvm(self),5475 ptr.toLlvm(self),
3982 instruction.llvmName(self),5476 instruction.llvmName(self),
3983 );5477 );
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());
3985 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));5480 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
3986 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);5481 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
3987 }5482 }
...@@ -4000,10 +5495,10 @@ pub const WipFunction = struct {...@@ -4000,10 +5495,10 @@ pub const WipFunction = struct {
40005495
4001 pub fn storeAtomic(5496 pub fn storeAtomic(
4002 self: *WipFunction,5497 self: *WipFunction,
4003 kind: MemoryAccessKind,5498 access_kind: MemoryAccessKind,
4004 val: Value,5499 val: Value,
4005 ptr: Value,5500 ptr: Value,
4006 scope: SyncScope,5501 sync_scope: SyncScope,
4007 ordering: AtomicOrdering,5502 ordering: AtomicOrdering,
4008 alignment: Alignment,5503 alignment: Alignment,
4009 ) Allocator.Error!Instruction.Index {5504 ) Allocator.Error!Instruction.Index {
...@@ -4011,31 +5506,27 @@ pub const WipFunction = struct {...@@ -4011,31 +5506,27 @@ pub const WipFunction = struct {
4011 try self.ensureUnusedExtraCapacity(1, Instruction.Store, 0);5506 try self.ensureUnusedExtraCapacity(1, Instruction.Store, 0);
4012 const instruction = try self.addInst(null, .{5507 const instruction = try self.addInst(null, .{
4013 .tag = switch (ordering) {5508 .tag = switch (ordering) {
4014 .none => switch (kind) {5509 .none => .store,
4015 .normal => .store,5510 else => .@"store atomic",
4016 .@"volatile" => .@"store volatile",
4017 },
4018 else => switch (kind) {
4019 .normal => .@"store atomic",
4020 .@"volatile" => .@"store atomic volatile",
4021 },
4022 },5511 },
4023 .data = self.addExtraAssumeCapacity(Instruction.Store{5512 .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 },
4024 .val = val,5522 .val = val,
4025 .ptr = ptr,5523 .ptr = ptr,
4026 .info = .{ .scope = switch (ordering) {
4027 .none => .system,
4028 else => scope,
4029 }, .ordering = ordering, .alignment = alignment },
4030 }),5524 }),
4031 });5525 });
4032 if (self.builder.useLibLlvm()) {5526 if (self.builder.useLibLlvm()) {
4033 const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self));5527 const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self));
4034 switch (kind) {5528 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
4035 .normal => {},5529 if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm());
4036 .@"volatile" => llvm_instruction.setVolatile(.True),
4037 }
4038 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
4039 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));5530 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
4040 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);5531 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
4041 }5532 }
...@@ -4044,7 +5535,7 @@ pub const WipFunction = struct {...@@ -4044,7 +5535,7 @@ pub const WipFunction = struct {
40445535
4045 pub fn fence(5536 pub fn fence(
4046 self: *WipFunction,5537 self: *WipFunction,
4047 scope: SyncScope,5538 sync_scope: SyncScope,
4048 ordering: AtomicOrdering,5539 ordering: AtomicOrdering,
4049 ) Allocator.Error!Instruction.Index {5540 ) Allocator.Error!Instruction.Index {
4050 assert(ordering != .none);5541 assert(ordering != .none);
...@@ -4052,21 +5543,130 @@ pub const WipFunction = struct {...@@ -4052,21 +5543,130 @@ pub const WipFunction = struct {
4052 const instruction = try self.addInst(null, .{5543 const instruction = try self.addInst(null, .{
4053 .tag = .fence,5544 .tag = .fence,
4054 .data = @bitCast(MemoryAccessInfo{5545 .data = @bitCast(MemoryAccessInfo{
4055 .scope = scope,5546 .sync_scope = sync_scope,
4056 .ordering = ordering,5547 .success_ordering = ordering,
4057 .alignment = undefined,
4058 }),5548 }),
4059 });5549 });
4060 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(5550 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
4061 self.llvm.builder.buildFence(5551 self.llvm.builder.buildFence(
4062 @enumFromInt(@intFromEnum(ordering)),5552 ordering.toLlvm(),
4063 llvm.Bool.fromBool(scope == .singlethread),5553 llvm.Bool.fromBool(sync_scope == .singlethread),
4064 "",5554 "",
4065 ),5555 ),
4066 );5556 );
4067 return instruction;5557 return instruction;
4068 }5558 }
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
4070 pub fn gep(5670 pub fn gep(
4071 self: *WipFunction,5671 self: *WipFunction,
4072 kind: Instruction.GetElementPtr.Kind,5672 kind: Instruction.GetElementPtr.Kind,
...@@ -4239,25 +5839,19 @@ pub const WipFunction = struct {...@@ -4239,25 +5839,19 @@ pub const WipFunction = struct {
42395839
4240 pub fn fcmp(5840 pub fn fcmp(
4241 self: *WipFunction,5841 self: *WipFunction,
5842 fast: FastMathKind,
4242 cond: FloatCondition,5843 cond: FloatCondition,
4243 lhs: Value,5844 lhs: Value,
4244 rhs: Value,5845 rhs: Value,
4245 name: []const u8,5846 name: []const u8,
4246 ) Allocator.Error!Value {5847 ) Allocator.Error!Value {
4247 return self.cmpTag(switch (cond) {5848 return self.cmpTag(switch (fast) {
4248 inline else => |tag| @field(Instruction.Tag, "fcmp " ++ @tagName(tag)),5849 inline else => |fast_tag| switch (cond) {
4249 }, @intFromEnum(cond), lhs, rhs, name);5850 inline else => |cond_tag| @field(Instruction.Tag, "fcmp " ++ switch (fast_tag) {
4250 }5851 .normal => "",
42515852 .fast => "fast ",
4252 pub fn fcmpFast(5853 } ++ @tagName(cond_tag)),
4253 self: *WipFunction,5854 },
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)),
4261 }, @intFromEnum(cond), lhs, rhs, name);5855 }, @intFromEnum(cond), lhs, rhs, name);
4262 }5856 }
42635857
...@@ -4315,22 +5909,16 @@ pub const WipFunction = struct {...@@ -4315,22 +5909,16 @@ pub const WipFunction = struct {
43155909
4316 pub fn select(5910 pub fn select(
4317 self: *WipFunction,5911 self: *WipFunction,
5912 fast: FastMathKind,
4318 cond: Value,5913 cond: Value,
4319 lhs: Value,5914 lhs: Value,
4320 rhs: Value,5915 rhs: Value,
4321 name: []const u8,5916 name: []const u8,
4322 ) Allocator.Error!Value {5917 ) Allocator.Error!Value {
4323 return self.selectTag(.select, cond, lhs, rhs, name);5918 return self.selectTag(switch (fast) {
4324 }5919 .normal => .select,
43255920 .fast => .@"select fast",
4326 pub fn selectFast(5921 }, cond, lhs, rhs, name);
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);
4334 }5922 }
43355923
4336 pub fn call(5924 pub fn call(
...@@ -4354,7 +5942,16 @@ pub const WipFunction = struct {...@@ -4354,7 +5942,16 @@ pub const WipFunction = struct {
4354 .void => null,5942 .void => null,
4355 else => name,5943 else => name,
4356 }, .{5944 }, .{
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 },
4358 .data = self.addExtraAssumeCapacity(Instruction.Call{5955 .data = self.addExtraAssumeCapacity(Instruction.Call{
4359 .info = .{ .call_conv = call_conv },5956 .info = .{ .call_conv = call_conv },
4360 .attributes = function_attributes,5957 .attributes = function_attributes,
...@@ -4396,7 +5993,7 @@ pub const WipFunction = struct {...@@ -4396,7 +5993,7 @@ pub const WipFunction = struct {
4396 else => instruction.llvmName(self),5993 else => instruction.llvmName(self),
4397 },5994 },
4398 );5995 );
4399 llvm_instruction.setInstructionCallConv(@enumFromInt(@intFromEnum(call_conv)));5996 llvm_instruction.setInstructionCallConv(call_conv.toLlvm());
4400 llvm_instruction.setTailCallKind(switch (kind) {5997 llvm_instruction.setTailCallKind(switch (kind) {
4401 .normal, .fast => .None,5998 .normal, .fast => .None,
4402 .musttail, .musttail_fast => .MustTail,5999 .musttail, .musttail_fast => .MustTail,
...@@ -4404,9 +6001,8 @@ pub const WipFunction = struct {...@@ -4404,9 +6001,8 @@ pub const WipFunction = struct {
4404 .tail, .tail_fast => .Tail,6001 .tail, .tail_fast => .Tail,
4405 });6002 });
4406 for (0.., function_attributes.slice(self.builder)) |index, attributes| {6003 for (0.., function_attributes.slice(self.builder)) |index, attributes| {
4407 const attribute_index = @as(llvm.AttributeIndex, @intCast(index)) -% 1;
4408 for (attributes.slice(self.builder)) |attribute| llvm_instruction.addCallSiteAttribute(6004 for (attributes.slice(self.builder)) |attribute| llvm_instruction.addCallSiteAttribute(
4409 attribute_index,6005 @as(llvm.AttributeIndex, @intCast(index)) -% 1,
4410 attribute.toLlvm(self.builder),6006 attribute.toLlvm(self.builder),
4411 );6007 );
4412 }6008 }
...@@ -4419,7 +6015,7 @@ pub const WipFunction = struct {...@@ -4419,7 +6015,7 @@ pub const WipFunction = struct {
4419 self: *WipFunction,6015 self: *WipFunction,
4420 function_attributes: FunctionAttributes,6016 function_attributes: FunctionAttributes,
4421 ty: Type,6017 ty: Type,
4422 kind: Constant.Asm.Info,6018 kind: Constant.Assembly.Info,
4423 assembly: String,6019 assembly: String,
4424 constraints: String,6020 constraints: String,
4425 args: []const Value,6021 args: []const Value,
...@@ -4429,6 +6025,80 @@ pub const WipFunction = struct {...@@ -4429,6 +6025,80 @@ pub const WipFunction = struct {
4429 return self.call(.normal, CallConv.default, function_attributes, ty, callee, args, name);6025 return self.call(.normal, CallConv.default, function_attributes, ty, callee, args, name);
4430 }6026 }
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
4432 pub fn vaArg(self: *WipFunction, list: Value, ty: Type, name: []const u8) Allocator.Error!Value {6102 pub fn vaArg(self: *WipFunction, list: Value, ty: Type, name: []const u8) Allocator.Error!Value {
4433 try self.ensureUnusedExtraCapacity(1, Instruction.VaArg, 0);6103 try self.ensureUnusedExtraCapacity(1, Instruction.VaArg, 0);
4434 const instruction = try self.addInst(name, .{6104 const instruction = try self.addInst(name, .{
...@@ -4448,53 +6118,6 @@ pub const WipFunction = struct {...@@ -4448,53 +6118,6 @@ pub const WipFunction = struct {
4448 return instruction.toValue();6118 return instruction.toValue();
4449 }6119 }
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
4498 pub fn finish(self: *WipFunction) Allocator.Error!void {6121 pub fn finish(self: *WipFunction) Allocator.Error!void {
4499 const gpa = self.builder.gpa;6122 const gpa = self.builder.gpa;
4500 const function = self.function.ptr(self.builder);6123 const function = self.function.ptr(self.builder);
...@@ -4697,22 +6320,6 @@ pub const WipFunction = struct {...@@ -4697,22 +6320,6 @@ pub const WipFunction = struct {
4697 .@"icmp ugt",6320 .@"icmp ugt",
4698 .@"icmp ule",6321 .@"icmp ule",
4699 .@"icmp ult",6322 .@"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.",
4716 .lshr,6323 .lshr,
4717 .@"lshr exact",6324 .@"lshr exact",
4718 .mul,6325 .mul,
...@@ -4775,19 +6382,19 @@ pub const WipFunction = struct {...@@ -4775,19 +6382,19 @@ pub const WipFunction = struct {
4775 .arg,6382 .arg,
4776 .block,6383 .block,
4777 => unreachable,6384 => 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 },
4778 .br,6393 .br,
4779 .fence,6394 .fence,
4780 .@"ret void",6395 .@"ret void",
4781 .unimplemented,
4782 .@"unreachable",6396 .@"unreachable",
4783 => {},6397 => {},
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 },
4791 .br_cond => {6398 .br_cond => {
4792 const extra = self.extraData(Instruction.BrCond, instruction.data);6399 const extra = self.extraData(Instruction.BrCond, instruction.data);
4793 instruction.data = wip_extra.addExtra(Instruction.BrCond{6400 instruction.data = wip_extra.addExtra(Instruction.BrCond{
...@@ -4816,6 +6423,24 @@ pub const WipFunction = struct {...@@ -4816,6 +6423,24 @@ pub const WipFunction = struct {
4816 });6423 });
4817 wip_extra.appendMappedValues(args, instructions);6424 wip_extra.appendMappedValues(args, instructions);
4818 },6425 },
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 },
4819 .extractvalue => {6444 .extractvalue => {
4820 var extra = self.extraDataTrail(Instruction.ExtractValue, instruction.data);6445 var extra = self.extraDataTrail(Instruction.ExtractValue, instruction.data);
4821 const indices = extra.trail.next(extra.data.indices_len, u32, self);6446 const indices = extra.trail.next(extra.data.indices_len, u32, self);
...@@ -4828,22 +6453,6 @@ pub const WipFunction = struct {...@@ -4828,22 +6453,6 @@ pub const WipFunction = struct {
4828 .fneg,6453 .fneg,
4829 .@"fneg fast",6454 .@"fneg fast",
4830 .ret,6455 .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.",
4847 => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))),6456 => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))),
4848 .getelementptr,6457 .getelementptr,
4849 .@"getelementptr inbounds",6458 .@"getelementptr inbounds",
...@@ -4877,8 +6486,6 @@ pub const WipFunction = struct {...@@ -4877,8 +6486,6 @@ pub const WipFunction = struct {
4877 },6486 },
4878 .load,6487 .load,
4879 .@"load atomic",6488 .@"load atomic",
4880 .@"load atomic volatile",
4881 .@"load volatile",
4882 => {6489 => {
4883 const extra = self.extraData(Instruction.Load, instruction.data);6490 const extra = self.extraData(Instruction.Load, instruction.data);
4884 instruction.data = wip_extra.addExtra(Instruction.Load{6491 instruction.data = wip_extra.addExtra(Instruction.Load{
...@@ -4920,8 +6527,6 @@ pub const WipFunction = struct {...@@ -4920,8 +6527,6 @@ pub const WipFunction = struct {
4920 },6527 },
4921 .store,6528 .store,
4922 .@"store atomic",6529 .@"store atomic",
4923 .@"store atomic volatile",
4924 .@"store volatile",
4925 => {6530 => {
4926 const extra = self.extraData(Instruction.Store, instruction.data);6531 const extra = self.extraData(Instruction.Store, instruction.data);
4927 instruction.data = wip_extra.addExtra(Instruction.Store{6532 instruction.data = wip_extra.addExtra(Instruction.Store{
...@@ -4949,14 +6554,6 @@ pub const WipFunction = struct {...@@ -4949,14 +6554,6 @@ pub const WipFunction = struct {
4949 .type = extra.type,6554 .type = extra.type,
4950 });6555 });
4951 },6556 },
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 },
4960 }6557 }
4961 function.instructions.appendAssumeCapacity(instruction);6558 function.instructions.appendAssumeCapacity(instruction);
4962 names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip)6559 names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip)
...@@ -5365,6 +6962,24 @@ pub const FloatCondition = enum(u4) {...@@ -5365,6 +6962,24 @@ pub const FloatCondition = enum(u4) {
5365 ult = 12,6962 ult = 12,
5366 ule = 13,6963 ule = 13,
5367 une = 14,6964 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 }
5368};6983};
53696984
5370pub const IntegerCondition = enum(u6) {6985pub const IntegerCondition = enum(u6) {
...@@ -5378,11 +6993,34 @@ pub const IntegerCondition = enum(u6) {...@@ -5378,11 +6993,34 @@ pub const IntegerCondition = enum(u6) {
5378 sge = 39,6993 sge = 39,
5379 slt = 40,6994 slt = 40,
5380 sle = 41,6995 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 }
5381};7010};
53827011
5383pub const MemoryAccessKind = enum(u1) {7012pub const MemoryAccessKind = enum(u1) {
5384 normal,7013 normal,
5385 @"volatile",7014 @"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 }
5386};7024};
53877025
5388pub const SyncScope = enum(u1) {7026pub const SyncScope = enum(u1) {
...@@ -5396,7 +7034,7 @@ pub const SyncScope = enum(u1) {...@@ -5396,7 +7034,7 @@ pub const SyncScope = enum(u1) {
5396 writer: anytype,7034 writer: anytype,
5397 ) @TypeOf(writer).Error!void {7035 ) @TypeOf(writer).Error!void {
5398 if (self != .system) try writer.print(7036 if (self != .system) try writer.print(
5399 \\{s} syncscope("{s}")7037 \\{s}syncscope("{s}")
5400 , .{ prefix, @tagName(self) });7038 , .{ prefix, @tagName(self) });
5401 }7039 }
5402};7040};
...@@ -5416,15 +7054,30 @@ pub const AtomicOrdering = enum(u3) {...@@ -5416,15 +7054,30 @@ pub const AtomicOrdering = enum(u3) {
5416 _: std.fmt.FormatOptions,7054 _: std.fmt.FormatOptions,
5417 writer: anytype,7055 writer: anytype,
5418 ) @TypeOf(writer).Error!void {7056 ) @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 };
5420 }7070 }
5421};7071};
54227072
5423const MemoryAccessInfo = packed struct(u32) {7073const MemoryAccessInfo = packed struct(u32) {
5424 scope: SyncScope,7074 access_kind: MemoryAccessKind = .normal,
5425 ordering: AtomicOrdering,7075 atomic_rmw_operation: Function.Instruction.AtomicRmw.Operation = .none,
5426 alignment: Alignment,7076 sync_scope: SyncScope,
5427 _: u22 = undefined,7077 success_ordering: AtomicOrdering,
7078 failure_ordering: AtomicOrdering = .none,
7079 alignment: Alignment = .default,
7080 _: u13 = undefined,
5428};7081};
54297082
5430pub const FastMath = packed struct(u32) {7083pub const FastMath = packed struct(u32) {
...@@ -5447,6 +7100,18 @@ pub const FastMath = packed struct(u32) {...@@ -5447,6 +7100,18 @@ pub const FastMath = packed struct(u32) {
5447 };7100 };
5448};7101};
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
5450pub const Constant = enum(u32) {7115pub const Constant = enum(u32) {
5451 false,7116 false,
5452 true,7117 true,
...@@ -5516,6 +7181,7 @@ pub const Constant = enum(u32) {...@@ -5516,6 +7181,7 @@ pub const Constant = enum(u32) {
5516 @"and",7181 @"and",
5517 @"or",7182 @"or",
5518 xor,7183 xor,
7184 select,
5519 @"asm",7185 @"asm",
5520 @"asm sideeffect",7186 @"asm sideeffect",
5521 @"asm alignstack",7187 @"asm alignstack",
...@@ -5627,7 +7293,13 @@ pub const Constant = enum(u32) {...@@ -5627,7 +7293,13 @@ pub const Constant = enum(u32) {
5627 rhs: Constant,7293 rhs: Constant,
5628 };7294 };
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 {
5631 type: Type,7303 type: Type,
5632 assembly: String,7304 assembly: String,
5633 constraints: String,7305 constraints: String,
...@@ -5651,7 +7323,7 @@ pub const Constant = enum(u32) {...@@ -5651,7 +7323,7 @@ pub const Constant = enum(u32) {
5651 }7323 }
56527324
5653 pub fn toValue(self: Constant) Value {7325 pub fn toValue(self: Constant) Value {
5654 return @enumFromInt(@intFromEnum(Value.first_constant) + @intFromEnum(self));7326 return @enumFromInt(Value.first_constant + @intFromEnum(self));
5655 }7327 }
56567328
5657 pub fn typeOf(self: Constant, builder: *Builder) Type {7329 pub fn typeOf(self: Constant, builder: *Builder) Type {
...@@ -5758,6 +7430,7 @@ pub const Constant = enum(u32) {...@@ -5758,6 +7430,7 @@ pub const Constant = enum(u32) {
5758 .@"or",7430 .@"or",
5759 .xor,7431 .xor,
5760 => builder.constantExtraData(Binary, item.data).lhs.typeOf(builder),7432 => builder.constantExtraData(Binary, item.data).lhs.typeOf(builder),
7433 .select => builder.constantExtraData(Select, item.data).lhs.typeOf(builder),
5761 .@"asm",7434 .@"asm",
5762 .@"asm sideeffect",7435 .@"asm sideeffect",
5763 .@"asm alignstack",7436 .@"asm alignstack",
...@@ -5852,7 +7525,7 @@ pub const Constant = enum(u32) {...@@ -5852,7 +7525,7 @@ pub const Constant = enum(u32) {
5852 }7525 }
5853 },7526 },
5854 .global => |global| switch (global.ptrConst(builder).kind) {7527 .global => |global| switch (global.ptrConst(builder).kind) {
5855 .alias => |alias| cur = alias.ptrConst(builder).init,7528 .alias => |alias| cur = alias.ptrConst(builder).aliasee,
5856 .variable, .function => return global,7529 .variable, .function => return global,
5857 .replaced => unreachable,7530 .replaced => unreachable,
5858 },7531 },
...@@ -5926,9 +7599,34 @@ pub const Constant = enum(u32) {...@@ -5926,9 +7599,34 @@ pub const Constant = enum(u32) {
5926 .bfloat => 16,7599 .bfloat => 16,
5927 else => unreachable,7600 else => unreachable,
5928 } }),7601 } }),
5929 .float => try writer.print("0x{X:0>16}", .{7602 .float => {
5930 @as(u64, @bitCast(@as(f64, @as(f32, @bitCast(item.data))))),7603 const Float = struct {
5931 }),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 },
5932 .double => {7630 .double => {
5933 const extra = data.builder.constantExtraData(Double, item.data);7631 const extra = data.builder.constantExtraData(Double, item.data);
5934 try writer.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });7632 try writer.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });
...@@ -6122,6 +7820,15 @@ pub const Constant = enum(u32) {...@@ -6122,6 +7820,15 @@ pub const Constant = enum(u32) {
6122 extra.rhs.fmt(data.builder),7820 extra.rhs.fmt(data.builder),
6123 });7821 });
6124 },7822 },
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 },
6125 .@"asm",7832 .@"asm",
6126 .@"asm sideeffect",7833 .@"asm sideeffect",
6127 .@"asm alignstack",7834 .@"asm alignstack",
...@@ -6139,7 +7846,7 @@ pub const Constant = enum(u32) {...@@ -6139,7 +7846,7 @@ pub const Constant = enum(u32) {
6139 .@"asm alignstack inteldialect unwind",7846 .@"asm alignstack inteldialect unwind",
6140 .@"asm sideeffect alignstack inteldialect unwind",7847 .@"asm sideeffect alignstack inteldialect unwind",
6141 => |tag| {7848 => |tag| {
6142 const extra = data.builder.constantExtraData(Asm, item.data);7849 const extra = data.builder.constantExtraData(Assembly, item.data);
6143 try writer.print("{s} {\"}, {\"}", .{7850 try writer.print("{s} {\"}, {\"}", .{
6144 @tagName(tag),7851 @tagName(tag),
6145 extra.assembly.fmt(data.builder),7852 extra.assembly.fmt(data.builder),
...@@ -6157,27 +7864,31 @@ pub const Constant = enum(u32) {...@@ -6157,27 +7864,31 @@ pub const Constant = enum(u32) {
61577864
6158 pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value {7865 pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value {
6159 assert(builder.useLibLlvm());7866 assert(builder.useLibLlvm());
6160 return switch (self.unwrap()) {7867 const llvm_value = switch (self.unwrap()) {
6161 .constant => |constant| builder.llvm.constants.items[constant],7868 .constant => |constant| builder.llvm.constants.items[constant],
6162 .global => |global| global.toLlvm(builder),7869 .global => |global| return global.toLlvm(builder),
6163 };7870 };
7871 const global = builder.llvm.replacements.get(llvm_value) orelse return llvm_value;
7872 return global.toLlvm(builder);
6164 }7873 }
6165};7874};
61667875
6167pub const Value = enum(u32) {7876pub const Value = enum(u32) {
6168 none = std.math.maxInt(u31),7877 none = std.math.maxInt(u31),
7878 false = first_constant + @intFromEnum(Constant.false),
7879 true = first_constant + @intFromEnum(Constant.true),
6169 _,7880 _,
61707881
6171 const first_constant: Value = @enumFromInt(1 << 31);7882 const first_constant = 1 << 31;
61727883
6173 pub fn unwrap(self: Value) union(enum) {7884 pub fn unwrap(self: Value) union(enum) {
6174 instruction: Function.Instruction.Index,7885 instruction: Function.Instruction.Index,
6175 constant: Constant,7886 constant: Constant,
6176 } {7887 } {
6177 return if (@intFromEnum(self) < @intFromEnum(first_constant))7888 return if (@intFromEnum(self) < first_constant)
6178 .{ .instruction = @enumFromInt(@intFromEnum(self)) }7889 .{ .instruction = @enumFromInt(@intFromEnum(self)) }
6179 else7890 else
6180 .{ .constant = @enumFromInt(@intFromEnum(self) - @intFromEnum(first_constant)) };7891 .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) };
6181 }7892 }
61827893
6183 pub fn typeOfWip(self: Value, wip: *const WipFunction) Type {7894 pub fn typeOfWip(self: Value, wip: *const WipFunction) Type {
...@@ -6295,6 +8006,7 @@ pub fn init(options: Options) InitError!Builder {...@@ -6295,6 +8006,7 @@ pub fn init(options: Options) InitError!Builder {
6295 .types = .{},8006 .types = .{},
6296 .globals = .{},8007 .globals = .{},
6297 .constants = .{},8008 .constants = .{},
8009 .replacements = .{},
6298 };8010 };
6299 errdefer self.deinit();8011 errdefer self.deinit();
63008012
...@@ -6304,7 +8016,7 @@ pub fn init(options: Options) InitError!Builder {...@@ -6304,7 +8016,7 @@ pub fn init(options: Options) InitError!Builder {
6304 if (options.name.len > 0) self.source_filename = try self.string(options.name);8016 if (options.name.len > 0) self.source_filename = try self.string(options.name);
6305 self.initializeLLVMTarget(options.target.cpu.arch);8017 self.initializeLLVMTarget(options.target.cpu.arch);
6306 if (self.useLibLlvm()) self.llvm.module = llvm.Module.createWithName(8018 if (self.useLibLlvm()) self.llvm.module = llvm.Module.createWithName(
6307 (self.source_filename.slice(&self) orelse "").ptr,8019 (self.source_filename.slice(&self) orelse ""),
6308 self.llvm.context,8020 self.llvm.context,
6309 );8021 );
63108022
...@@ -6349,8 +8061,11 @@ pub fn init(options: Options) InitError!Builder {...@@ -6349,8 +8061,11 @@ pub fn init(options: Options) InitError!Builder {
6349 inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits|8061 inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits|
6350 assert(self.intTypeAssumeCapacity(bits) ==8062 assert(self.intTypeAssumeCapacity(bits) ==
6351 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));8063 @field(Type, std.fmt.comptimePrint("i{d}", .{bits})));
6352 inline for (.{0}) |addr_space|8064 inline for (.{ 0, 4 }) |addr_space_index| {
6353 assert(self.ptrTypeAssumeCapacity(@enumFromInt(addr_space)) == .ptr);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 }
6354 }8069 }
63558070
6356 {8071 {
...@@ -6371,6 +8086,20 @@ pub fn init(options: Options) InitError!Builder {...@@ -6371,6 +8086,20 @@ pub fn init(options: Options) InitError!Builder {
6371}8086}
63728087
6373pub fn deinit(self: *Builder) void {8088pub 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
6374 self.module_asm.deinit(self.gpa);8103 self.module_asm.deinit(self.gpa);
63758104
6376 self.string_map.deinit(self.gpa);8105 self.string_map.deinit(self.gpa);
...@@ -6400,16 +8129,6 @@ pub fn deinit(self: *Builder) void {...@@ -6400,16 +8129,6 @@ pub fn deinit(self: *Builder) void {
6400 self.constant_extra.deinit(self.gpa);8129 self.constant_extra.deinit(self.gpa);
6401 self.constant_limbs.deinit(self.gpa);8130 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 }
6413 self.* = undefined;8132 self.* = undefined;
6414}8133}
64158134
...@@ -6763,16 +8482,16 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde...@@ -6763,16 +8482,16 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde
6763 gop.value_ptr.* = {};8482 gop.value_ptr.* = {};
6764 if (self.useLibLlvm()) self.llvm.attributes.appendAssumeCapacity(switch (attribute) {8483 if (self.useLibLlvm()) self.llvm.attributes.appendAssumeCapacity(switch (attribute) {
6765 else => llvm_attr: {8484 else => llvm_attr: {
6766 const kind_id = &self.llvm.attribute_kind_ids.?[@intFromEnum(attribute)];8485 const llvm_kind_id = attribute.getKind().toLlvm(self);
6767 if (kind_id.* == 0) {8486 if (llvm_kind_id.* == 0) {
6768 const name = @tagName(attribute);8487 const name = @tagName(attribute);
6769 kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len);8488 llvm_kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len);
6770 assert(kind_id.* != 0);8489 assert(llvm_kind_id.* != 0);
6771 }8490 }
6772 break :llvm_attr switch (attribute) {8491 break :llvm_attr switch (attribute) {
6773 else => switch (attribute) {8492 else => switch (attribute) {
6774 inline else => |value| self.llvm.context.createEnumAttribute(8493 inline else => |value| self.llvm.context.createEnumAttribute(
6775 kind_id.*,8494 llvm_kind_id.*,
6776 switch (@TypeOf(value)) {8495 switch (@TypeOf(value)) {
6777 void => 0,8496 void => 0,
6778 u32 => value,8497 u32 => value,
...@@ -6806,7 +8525,7 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde...@@ -6806,7 +8525,7 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde
6806 .inalloca,8525 .inalloca,
6807 .sret,8526 .sret,
6808 .elementtype,8527 .elementtype,
6809 => |ty| self.llvm.context.createTypeAttribute(kind_id.*, ty.toLlvm(self)),8528 => |ty| self.llvm.context.createTypeAttribute(llvm_kind_id.*, ty.toLlvm(self)),
6810 .string, .none => unreachable,8529 .string, .none => unreachable,
6811 };8530 };
6812 },8531 },
...@@ -6866,10 +8585,10 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo...@@ -6866,10 +8585,10 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo
6866 const global_gop = self.globals.getOrPutAssumeCapacity(id);8585 const global_gop = self.globals.getOrPutAssumeCapacity(id);
6867 if (!global_gop.found_existing) {8586 if (!global_gop.found_existing) {
6868 global_gop.value_ptr.* = global;8587 global_gop.value_ptr.* = global;
6869 global_gop.value_ptr.updateAttributes();8588 const global_index: Global.Index = @enumFromInt(global_gop.index);
6870 const index: Global.Index = @enumFromInt(global_gop.index);8589 global_index.updateDsoLocal(self);
6871 index.updateName(self);8590 global_index.updateName(self);
6872 return index;8591 return global_index;
6873 }8592 }
68748593
6875 const unique_gop = self.next_unique_global_id.getOrPutAssumeCapacity(name);8594 const unique_gop = self.next_unique_global_id.getOrPutAssumeCapacity(name);
...@@ -6883,17 +8602,221 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index {...@@ -6883,17 +8602,221 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index {
6883 return @enumFromInt(self.globals.getIndex(name) orelse return null);8602 return @enumFromInt(self.globals.getIndex(name) orelse return null);
6884}8603}
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
6886pub fn intConst(self: *Builder, ty: Type, value: anytype) Allocator.Error!Constant {8806pub 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 };
6887 var limbs: [8812 var limbs: [
6888 switch (@typeInfo(@TypeOf(value))) {8813 switch (@typeInfo(@TypeOf(int_value))) {
6889 .Int => |info| std.math.big.int.calcTwosCompLimbCount(info.bits),8814 .Int => |info| std.math.big.int.calcTwosCompLimbCount(info.bits),
6890 .ComptimeInt => std.math.big.int.calcLimbLen(value),8815 .ComptimeInt => std.math.big.int.calcLimbLen(int_value),
6891 else => @compileError(8816 else => unreachable,
6892 "intConst expected an integral value, got " ++ @typeName(@TypeOf(value)),
6893 ),
6894 }8817 }
6895 ]std.math.big.Limb = undefined;8818 ]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());
6897}8820}
68988821
6899pub fn intValue(self: *Builder, ty: Type, value: anytype) Allocator.Error!Value {8822pub 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)...@@ -7301,27 +9224,75 @@ pub fn binValue(self: *Builder, tag: Constant.Tag, lhs: Constant, rhs: Constant)
7301 return (try self.binConst(tag, lhs, rhs)).toValue();9224 return (try self.binConst(tag, lhs, rhs)).toValue();
7302}9225}
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
7304pub fn asmConst(9241pub fn asmConst(
7305 self: *Builder,9242 self: *Builder,
7306 ty: Type,9243 ty: Type,
7307 info: Constant.Asm.Info,9244 info: Constant.Assembly.Info,
7308 assembly: String,9245 assembly: String,
7309 constraints: String,9246 constraints: String,
7310) Allocator.Error!Constant {9247) Allocator.Error!Constant {
7311 try self.ensureUnusedConstantCapacity(1, Constant.Asm, 0);9248 try self.ensureUnusedConstantCapacity(1, Constant.Assembly, 0);
7312 return self.asmConstAssumeCapacity(ty, info, assembly, constraints);9249 return self.asmConstAssumeCapacity(ty, info, assembly, constraints);
7313}9250}
73149251
7315pub fn asmValue(9252pub fn asmValue(
7316 self: *Builder,9253 self: *Builder,
7317 ty: Type,9254 ty: Type,
7318 info: Constant.Asm.Info,9255 info: Constant.Assembly.Info,
7319 assembly: String,9256 assembly: String,
7320 constraints: String,9257 constraints: String,
7321) Allocator.Error!Value {9258) Allocator.Error!Value {
7322 return (try self.asmConst(ty, info, assembly, constraints)).toValue();9259 return (try self.asmConst(ty, info, assembly, constraints)).toValue();
7323}9260}
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
7325pub fn dump(self: *Builder) void {9296pub fn dump(self: *Builder) void {
7326 if (self.useLibLlvm())9297 if (self.useLibLlvm())
7327 self.llvm.module.?.dump()9298 self.llvm.module.?.dump()
...@@ -7413,7 +9384,7 @@ pub fn printUnbuffered(...@@ -7413,7 +9384,7 @@ pub fn printUnbuffered(
7413 if (variable.global.getReplacement(self) != .none) continue;9384 if (variable.global.getReplacement(self) != .none) continue;
7414 const global = variable.global.ptrConst(self);9385 const global = variable.global.ptrConst(self);
7415 try writer.print(9386 try writer.print(
7416 \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{,}9387 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }
7417 \\9388 \\
7418 , .{9389 , .{
7419 variable.global.fmt(self),9390 variable.global.fmt(self),
...@@ -7434,557 +9405,521 @@ pub fn printUnbuffered(...@@ -7434,557 +9405,521 @@ pub fn printUnbuffered(
7434 need_newline = true;9405 need_newline = true;
7435 }9406 }
74369407
7437 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};9408 if (self.aliases.items.len > 0) {
7438 defer attribute_groups.deinit(self.gpa);
7439
7440 if (self.functions.items.len > 0) {
7441 if (need_newline) try writer.writeByte('\n');9409 if (need_newline) try writer.writeByte('\n');
7442 for (0.., self.functions.items) |function_i, function| {9410 for (self.aliases.items) |alias| {
7443 if (function_i > 0) try writer.writeByte('\n');9411 if (alias.global.getReplacement(self) != .none) continue;
7444 const function_index: Function.Index = @enumFromInt(function_i);9412 const global = alias.global.ptrConst(self);
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)});
7453 try writer.print(9413 try writer.print(
7454 \\{s}{}{}{}{}{}{"} {} {}(9414 \\{} ={}{}{}{}{ }{} alias {%}, {%}
9415 \\
7455 , .{9416 , .{
7456 if (function.instructions.len > 0) "define" else "declare",9417 alias.global.fmt(self),
7457 global.linkage,9418 global.linkage,
7458 global.preemption,9419 global.preemption,
7459 global.visibility,9420 global.visibility,
7460 global.dll_storage_class,9421 global.dll_storage_class,
7461 function.call_conv,9422 alias.thread_local,
7462 function.attributes.ret(self).fmt(self),9423 global.unnamed_addr,
7463 global.type.functionReturn(self).fmt(self),9424 global.type.fmt(self),
7464 function.global.fmt(self),9425 alias.aliasee.fmt(self),
7465 });9426 });
7466 for (0..params_len) |arg| {9427 }
7467 if (arg > 0) try writer.writeAll(", ");9428 need_newline = true;
7468 try writer.print(9429 }
7469 \\{%}{"}9430
7470 , .{9431 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};
7471 global.type.functionParameters(self)[arg].fmt(self),9432 defer attribute_groups.deinit(self.gpa);
7472 function.attributes.param(arg, self).fmt(self),9433
7473 });9434 for (0.., self.functions.items) |function_i, function| {
7474 if (function.instructions.len > 0)9435 if (function.global.getReplacement(self) != .none) continue;
7475 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)});9436 if (need_newline) try writer.writeByte('\n');
7476 }9437 const function_index: Function.Index = @enumFromInt(function_i);
7477 switch (global.type.functionKind(self)) {9438 const global = function.global.ptrConst(self);
7478 .normal => {},9439 const params_len = global.type.functionParameters(self).len;
7479 .vararg => {9440 const function_attributes = function.attributes.func(self);
7480 if (params_len > 0) try writer.writeAll(", ");9441 if (function_attributes != .none) try writer.print(
7481 try writer.writeAll("...");9442 \\; Function Attrs:{}
7482 },9443 \\
7483 }9444 , .{function_attributes.fmt(self)});
7484 try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space });9445 try writer.print(
7485 if (function_attributes != .none) try writer.print(" #{d}", .{9446 \\{s}{}{}{}{}{}{"} {} {}(
7486 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,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),
7487 });9465 });
7488 try writer.print("{}", .{function.alignment});9466 if (function.instructions.len > 0)
7489 if (function.instructions.len > 0) {9467 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)})
7490 var block_incoming_len: u32 = undefined;9468 else
7491 try writer.writeAll(" {\n");9469 try writer.print(" %{d}", .{arg});
7492 for (params_len..function.instructions.len) |instruction_i| {9470 }
7493 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);9471 switch (global.type.functionKind(self)) {
7494 const instruction = function.instructions.get(@intFromEnum(instruction_index));9472 .normal => {},
7495 switch (instruction.tag) {9473 .vararg => {
7496 .add,9474 if (params_len > 0) try writer.writeAll(", ");
7497 .@"add nsw",9475 try writer.writeAll("...");
7498 .@"add nuw",9476 },
7499 .@"add nuw nsw",9477 }
7500 .@"and",9478 try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });
7501 .ashr,9479 if (function_attributes != .none) try writer.print(" #{d}", .{
7502 .@"ashr exact",9480 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
7503 .fadd,9481 });
7504 .@"fadd fast",9482 try writer.print("{ }", .{function.alignment});
7505 .@"fcmp false",9483 if (function.instructions.len > 0) {
7506 .@"fcmp fast false",9484 var block_incoming_len: u32 = undefined;
7507 .@"fcmp fast oeq",9485 try writer.writeAll(" {\n");
7508 .@"fcmp fast oge",9486 for (params_len..function.instructions.len) |instruction_i| {
7509 .@"fcmp fast ogt",9487 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
7510 .@"fcmp fast ole",9488 const instruction = function.instructions.get(@intFromEnum(instruction_index));
7511 .@"fcmp fast olt",9489 switch (instruction.tag) {
7512 .@"fcmp fast one",9490 .add,
7513 .@"fcmp fast ord",9491 .@"add nsw",
7514 .@"fcmp fast true",9492 .@"add nuw",
7515 .@"fcmp fast ueq",9493 .@"add nuw nsw",
7516 .@"fcmp fast uge",9494 .@"and",
7517 .@"fcmp fast ugt",9495 .ashr,
7518 .@"fcmp fast ule",9496 .@"ashr exact",
7519 .@"fcmp fast ult",9497 .fadd,
7520 .@"fcmp fast une",9498 .@"fadd fast",
7521 .@"fcmp fast uno",9499 .@"fcmp false",
7522 .@"fcmp oeq",9500 .@"fcmp fast false",
7523 .@"fcmp oge",9501 .@"fcmp fast oeq",
7524 .@"fcmp ogt",9502 .@"fcmp fast oge",
7525 .@"fcmp ole",9503 .@"fcmp fast ogt",
7526 .@"fcmp olt",9504 .@"fcmp fast ole",
7527 .@"fcmp one",9505 .@"fcmp fast olt",
7528 .@"fcmp ord",9506 .@"fcmp fast one",
7529 .@"fcmp true",9507 .@"fcmp fast ord",
7530 .@"fcmp ueq",9508 .@"fcmp fast true",
7531 .@"fcmp uge",9509 .@"fcmp fast ueq",
7532 .@"fcmp ugt",9510 .@"fcmp fast uge",
7533 .@"fcmp ule",9511 .@"fcmp fast ugt",
7534 .@"fcmp ult",9512 .@"fcmp fast ule",
7535 .@"fcmp une",9513 .@"fcmp fast ult",
7536 .@"fcmp uno",9514 .@"fcmp fast une",
7537 .fdiv,9515 .@"fcmp fast uno",
7538 .@"fdiv fast",9516 .@"fcmp oeq",
7539 .fmul,9517 .@"fcmp oge",
7540 .@"fmul fast",9518 .@"fcmp ogt",
7541 .frem,9519 .@"fcmp ole",
7542 .@"frem fast",9520 .@"fcmp olt",
7543 .fsub,9521 .@"fcmp one",
7544 .@"fsub fast",9522 .@"fcmp ord",
7545 .@"icmp eq",9523 .@"fcmp true",
7546 .@"icmp ne",9524 .@"fcmp ueq",
7547 .@"icmp sge",9525 .@"fcmp uge",
7548 .@"icmp sgt",9526 .@"fcmp ugt",
7549 .@"icmp sle",9527 .@"fcmp ule",
7550 .@"icmp slt",9528 .@"fcmp ult",
7551 .@"icmp uge",9529 .@"fcmp une",
7552 .@"icmp ugt",9530 .@"fcmp uno",
7553 .@"icmp ule",9531 .fdiv,
7554 .@"icmp ult",9532 .@"fdiv fast",
7555 .lshr,9533 .fmul,
7556 .@"lshr exact",9534 .@"fmul fast",
7557 .mul,9535 .frem,
7558 .@"mul nsw",9536 .@"frem fast",
7559 .@"mul nuw",9537 .fsub,
7560 .@"mul nuw nsw",9538 .@"fsub fast",
7561 .@"or",9539 .@"icmp eq",
7562 .sdiv,9540 .@"icmp ne",
7563 .@"sdiv exact",9541 .@"icmp sge",
7564 .srem,9542 .@"icmp sgt",
7565 .shl,9543 .@"icmp sle",
7566 .@"shl nsw",9544 .@"icmp slt",
7567 .@"shl nuw",9545 .@"icmp uge",
7568 .@"shl nuw nsw",9546 .@"icmp ugt",
7569 .sub,9547 .@"icmp ule",
7570 .@"sub nsw",9548 .@"icmp ult",
7571 .@"sub nuw",9549 .lshr,
7572 .@"sub nuw nsw",9550 .@"lshr exact",
7573 .udiv,9551 .mul,
7574 .@"udiv exact",9552 .@"mul nsw",
7575 .urem,9553 .@"mul nuw",
7576 .xor,9554 .@"mul nuw nsw",
7577 => |tag| {9555 .@"or",
7578 const extra =9556 .sdiv,
7579 function.extraData(Function.Instruction.Binary, instruction.data);9557 .@"sdiv exact",
7580 try writer.print(" %{} = {s} {%}, {}\n", .{9558 .srem,
7581 instruction_index.name(&function).fmt(self),9559 .shl,
7582 @tagName(tag),9560 .@"shl nsw",
7583 extra.lhs.fmt(function_index, self),9561 .@"shl nuw",
7584 extra.rhs.fmt(function_index, self),9562 .@"shl nuw nsw",
7585 });9563 .sub,
7586 },9564 .@"sub nsw",
7587 .addrspacecast,9565 .@"sub nuw",
7588 .bitcast,9566 .@"sub nuw nsw",
7589 .fpext,9567 .udiv,
7590 .fptosi,9568 .@"udiv exact",
7591 .fptoui,9569 .urem,
7592 .fptrunc,9570 .xor,
7593 .inttoptr,9571 => |tag| {
7594 .ptrtoint,9572 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
7595 .sext,9573 try writer.print(" %{} = {s} {%}, {}\n", .{
7596 .sitofp,9574 instruction_index.name(&function).fmt(self),
7597 .trunc,9575 @tagName(tag),
7598 .uitofp,9576 extra.lhs.fmt(function_index, self),
7599 .zext,9577 extra.rhs.fmt(function_index, self),
7600 => |tag| {9578 });
7601 const extra =9579 },
7602 function.extraData(Function.Instruction.Cast, instruction.data);9580 .addrspacecast,
7603 try writer.print(" %{} = {s} {%} to {%}\n", .{9581 .bitcast,
7604 instruction_index.name(&function).fmt(self),9582 .fpext,
7605 @tagName(tag),9583 .fptosi,
7606 extra.val.fmt(function_index, self),9584 .fptoui,
7607 extra.type.fmt(self),9585 .fptrunc,
7608 });9586 .inttoptr,
7609 },9587 .ptrtoint,
7610 .alloca,9588 .sext,
7611 .@"alloca inalloca",9589 .sitofp,
7612 => |tag| {9590 .trunc,
7613 const extra =9591 .uitofp,
7614 function.extraData(Function.Instruction.Alloca, instruction.data);9592 .zext,
7615 try writer.print(" %{} = {s} {%}{,%}{,}{,}\n", .{9593 => |tag| {
7616 instruction_index.name(&function).fmt(self),9594 const extra = function.extraData(Function.Instruction.Cast, instruction.data);
7617 @tagName(tag),9595 try writer.print(" %{} = {s} {%} to {%}\n", .{
7618 extra.type.fmt(self),9596 instruction_index.name(&function).fmt(self),
7619 extra.len.fmt(function_index, self),9597 @tagName(tag),
7620 extra.info.alignment,9598 extra.val.fmt(function_index, self),
7621 extra.info.addr_space,9599 extra.type.fmt(self),
7622 });9600 });
7623 },9601 },
7624 .arg => unreachable,9602 .alloca,
7625 .block => {9603 .@"alloca inalloca",
7626 block_incoming_len = instruction.data;9604 => |tag| {
7627 const name = instruction_index.name(&function);9605 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
7628 if (@intFromEnum(instruction_index) > params_len)9606 try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{
7629 try writer.writeByte('\n');9607 instruction_index.name(&function).fmt(self),
7630 try writer.print("{}:\n", .{name.fmt(self)});9608 @tagName(tag),
7631 },9609 extra.type.fmt(self),
7632 .br => |tag| {9610 extra.len.fmt(function_index, self),
7633 const target: Function.Block.Index = @enumFromInt(instruction.data);9611 extra.info.alignment,
7634 try writer.print(" {s} {%}\n", .{9612 extra.info.addr_space,
7635 @tagName(tag), target.toInst(&function).fmt(function_index, self),9613 });
7636 });9614 },
7637 },9615 .arg => unreachable,
7638 .br_cond => {9616 .atomicrmw => |tag| {
7639 const extra =9617 const extra =
7640 function.extraData(Function.Instruction.BrCond, instruction.data);9618 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
7641 try writer.print(" br {%}, {%}, {%}\n", .{9619 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{
7642 extra.cond.fmt(function_index, self),9620 instruction_index.name(&function).fmt(self),
7643 extra.then.toInst(&function).fmt(function_index, self),9621 @tagName(tag),
7644 extra.@"else".toInst(&function).fmt(function_index, self),9622 extra.info.access_kind,
7645 });9623 @tagName(extra.info.atomic_rmw_operation),
7646 },9624 extra.ptr.fmt(function_index, self),
7647 .call,9625 extra.val.fmt(function_index, self),
7648 .@"call fast",9626 extra.info.sync_scope,
7649 .@"musttail call",9627 extra.info.success_ordering,
7650 .@"musttail call fast",9628 extra.info.alignment,
7651 .@"notail call",9629 });
7652 .@"notail call fast",9630 },
7653 .@"tail call",9631 .block => {
7654 .@"tail call fast",9632 block_incoming_len = instruction.data;
7655 => |tag| {9633 const name = instruction_index.name(&function);
7656 var extra =9634 if (@intFromEnum(instruction_index) > params_len)
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 }
7873 try writer.writeByte('\n');9635 try writer.writeByte('\n');
7874 },9636 try writer.print("{}:\n", .{name.fmt(self)});
7875 .@"ret void",9637 },
7876 .@"unreachable",9638 .br => |tag| {
7877 => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),9639 const target: Function.Block.Index = @enumFromInt(instruction.data);
7878 .select,9640 try writer.print(" {s} {%}\n", .{
7879 .@"select fast",9641 @tagName(tag), target.toInst(&function).fmt(function_index, self),
7880 => |tag| {9642 });
7881 const extra =9643 },
7882 function.extraData(Function.Instruction.Select, instruction.data);9644 .br_cond => {
7883 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{9645 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
7884 instruction_index.name(&function).fmt(self),9646 try writer.print(" br {%}, {%}, {%}\n", .{
7885 @tagName(tag),9647 extra.cond.fmt(function_index, self),
7886 extra.cond.fmt(function_index, self),9648 extra.then.toInst(&function).fmt(function_index, self),
7887 extra.lhs.fmt(function_index, self),9649 extra.@"else".toInst(&function).fmt(function_index, self),
7888 extra.rhs.fmt(function_index, self),9650 });
7889 });9651 },
7890 },9652 .call,
7891 .shufflevector => |tag| {9653 .@"call fast",
7892 const extra = function.extraData(9654 .@"musttail call",
7893 Function.Instruction.ShuffleVector,9655 .@"musttail call fast",
7894 instruction.data,9656 .@"notail call",
7895 );9657 .@"notail call fast",
7896 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{9658 .@"tail call",
7897 instruction_index.name(&function).fmt(self),9659 .@"tail call fast",
7898 @tagName(tag),9660 => |tag| {
7899 extra.lhs.fmt(function_index, self),9661 var extra =
7900 extra.rhs.fmt(function_index, self),9662 function.extraDataTrail(Function.Instruction.Call, instruction.data);
7901 extra.mask.fmt(function_index, self),9663 const args = extra.trail.next(extra.data.args_len, Value, &function);
7902 });9664 try writer.writeAll(" ");
7903 },9665 const ret_ty = extra.data.ty.functionReturn(self);
7904 .store,9666 switch (ret_ty) {
7905 .@"store atomic",9667 .void => {},
7906 .@"store atomic volatile",9668 else => try writer.print("%{} = ", .{
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", .{
7963 instruction_index.name(&function).fmt(self),9669 instruction_index.name(&function).fmt(self),
7964 @tagName(tag),9670 }),
7965 extra.list.fmt(function_index, self),9671 .none => unreachable,
7966 extra.type.fmt(self),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),
7967 });9690 });
7968 },9691 }
7969 .@"llvm.fma." => {9692 try writer.writeByte(')');
7970 const extra =9693 const call_function_attributes = extra.data.attributes.func(self);
7971 function.extraData(Function.Instruction.FusedMultiplyAdd, instruction.data);9694 if (call_function_attributes != .none) try writer.print(" #{d}", .{
7972 const ty = instruction_index.typeOf(function_index, self);9695 (try attribute_groups.getOrPutValue(
7973 try writer.print(" %{} = call {%} @llvm.fma.{m}({%}, {%}, {%})\n", .{9696 self.gpa,
7974 instruction_index.name(&function).fmt(self),9697 call_function_attributes,
7975 ty.fmt(self),9698 {},
7976 ty.fmt(self),9699 )).index,
7977 extra.a.fmt(function_index, self),9700 });
7978 extra.b.fmt(function_index, self),9701 try writer.writeByte('\n');
7979 extra.c.fmt(function_index, self),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),
7980 });9838 });
7981 },9839 }
7982 }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 },
7983 }9918 }
7984 try writer.writeByte('}');
7985 }9919 }
7986 try writer.writeByte('\n');9920 try writer.writeByte('}');
7987 }9921 }
9922 try writer.writeByte('\n');
7988 need_newline = true;9923 need_newline = true;
7989 }9924 }
79909925
...@@ -8080,7 +10015,7 @@ fn fnTypeAssumeCapacity(...@@ -8080,7 +10015,7 @@ fn fnTypeAssumeCapacity(
8080 gop.key_ptr.* = {};10015 gop.key_ptr.* = {};
8081 gop.value_ptr.* = {};10016 gop.value_ptr.* = {};
8082 self.type_items.appendAssumeCapacity(.{10017 self.type_items.appendAssumeCapacity(.{
8083 .tag = .function,10018 .tag = tag,
8084 .data = self.addTypeExtraAssumeCapacity(Type.Function{10019 .data = self.addTypeExtraAssumeCapacity(Type.Function{
8085 .ret = ret,10020 .ret = ret,
8086 .params_len = @intCast(params.len),10021 .params_len = @intCast(params.len),
...@@ -9378,7 +11313,7 @@ fn icmpConstAssumeCapacity(...@@ -9378,7 +11313,7 @@ fn icmpConstAssumeCapacity(
9378 .data = self.addConstantExtraAssumeCapacity(data),11313 .data = self.addConstantExtraAssumeCapacity(data),
9379 });11314 });
9380 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(11315 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)),
9382 );11317 );
9383 }11318 }
9384 return @enumFromInt(gop.index);11319 return @enumFromInt(gop.index);
...@@ -9415,7 +11350,7 @@ fn fcmpConstAssumeCapacity(...@@ -9415,7 +11350,7 @@ fn fcmpConstAssumeCapacity(
9415 .data = self.addConstantExtraAssumeCapacity(data),11350 .data = self.addConstantExtraAssumeCapacity(data),
9416 });11351 });
9417 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(11352 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)),
9419 );11354 );
9420 }11355 }
9421 return @enumFromInt(gop.index);11356 return @enumFromInt(gop.index);
...@@ -9601,16 +11536,52 @@ fn binConstAssumeCapacity(...@@ -9601,16 +11536,52 @@ fn binConstAssumeCapacity(
9601 return @enumFromInt(gop.index);11536 return @enumFromInt(gop.index);
9602}11537}
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
9604fn asmConstAssumeCapacity(11575fn asmConstAssumeCapacity(
9605 self: *Builder,11576 self: *Builder,
9606 ty: Type,11577 ty: Type,
9607 info: Constant.Asm.Info,11578 info: Constant.Assembly.Info,
9608 assembly: String,11579 assembly: String,
9609 constraints: String,11580 constraints: String,
9610) Constant {11581) Constant {
9611 assert(ty.functionKind(self) == .normal);11582 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 };
9614 const Adapter = struct {11585 const Adapter = struct {
9615 builder: *const Builder,11586 builder: *const Builder,
9616 pub fn hash(_: @This(), key: Key) u32 {11587 pub fn hash(_: @This(), key: Key) u32 {
...@@ -9622,7 +11593,7 @@ fn asmConstAssumeCapacity(...@@ -9622,7 +11593,7 @@ fn asmConstAssumeCapacity(
9622 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {11593 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
9623 if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false;11594 if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false;
9624 const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];11595 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);
9626 return std.meta.eql(lhs_key.extra, rhs_extra);11597 return std.meta.eql(lhs_key.extra, rhs_extra);
9627 }11598 }
9628 };11599 };
src/codegen/llvm/bindings.zig+14-315
...@@ -93,17 +93,6 @@ pub const Context = opaque {...@@ -93,17 +93,6 @@ pub const Context = opaque {
93 pub const constString = LLVMConstStringInContext;93 pub const constString = LLVMConstStringInContext;
94 extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) *Value;94 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
107 pub const appendBasicBlock = LLVMAppendBasicBlockInContext;96 pub const appendBasicBlock = LLVMAppendBasicBlockInContext;
108 extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*:0]const u8) *BasicBlock;97 extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*:0]const u8) *BasicBlock;
10998
...@@ -115,18 +104,18 @@ pub const Context = opaque {...@@ -115,18 +104,18 @@ pub const Context = opaque {
115};104};
116105
117pub const Value = opaque {106pub const Value = opaque {
118 pub const addAttributeAtIndex = ZigLLVMAddAttributeAtIndex;107 pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;
119 extern fn ZigLLVMAddAttributeAtIndex(*Value, Idx: AttributeIndex, A: *Attribute) void;108 extern fn LLVMAddAttributeAtIndex(F: *Value, Idx: AttributeIndex, A: *Attribute) void;
120109
121 pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex;110 pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex;
122 extern fn LLVMRemoveEnumAttributeAtIndex(F: *Value, Idx: AttributeIndex, KindID: c_uint) void;111 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
124 pub const getFirstBasicBlock = LLVMGetFirstBasicBlock;116 pub const getFirstBasicBlock = LLVMGetFirstBasicBlock;
125 extern fn LLVMGetFirstBasicBlock(Fn: *Value) ?*BasicBlock;117 extern fn LLVMGetFirstBasicBlock(Fn: *Value) ?*BasicBlock;
126118
127 pub const appendExistingBasicBlock = LLVMAppendExistingBasicBlock;
128 extern fn LLVMAppendExistingBasicBlock(Fn: *Value, BB: *BasicBlock) void;
129
130 pub const addIncoming = LLVMAddIncoming;119 pub const addIncoming = LLVMAddIncoming;
131 extern fn LLVMAddIncoming(120 extern fn LLVMAddIncoming(
132 PhiNode: *Value,121 PhiNode: *Value,
...@@ -135,9 +124,6 @@ pub const Value = opaque {...@@ -135,9 +124,6 @@ pub const Value = opaque {
135 Count: c_uint,124 Count: c_uint,
136 ) void;125 ) void;
137126
138 pub const getNextInstruction = LLVMGetNextInstruction;
139 extern fn LLVMGetNextInstruction(Inst: *Value) ?*Value;
140
141 pub const setGlobalConstant = LLVMSetGlobalConstant;127 pub const setGlobalConstant = LLVMSetGlobalConstant;
142 extern fn LLVMSetGlobalConstant(GlobalVar: *Value, IsConstant: Bool) void;128 extern fn LLVMSetGlobalConstant(GlobalVar: *Value, IsConstant: Bool) void;
143129
...@@ -156,33 +142,18 @@ pub const Value = opaque {...@@ -156,33 +142,18 @@ pub const Value = opaque {
156 pub const setSection = LLVMSetSection;142 pub const setSection = LLVMSetSection;
157 extern fn LLVMSetSection(Global: *Value, Section: [*:0]const u8) void;143 extern fn LLVMSetSection(Global: *Value, Section: [*:0]const u8) void;
158144
159 pub const deleteGlobal = LLVMDeleteGlobal;145 pub const removeGlobalValue = ZigLLVMRemoveGlobalValue;
160 extern fn LLVMDeleteGlobal(GlobalVar: *Value) void;146 extern fn ZigLLVMRemoveGlobalValue(GlobalVal: *Value) void;
161147
162 pub const getNextGlobalAlias = LLVMGetNextGlobalAlias;148 pub const eraseGlobalValue = ZigLLVMEraseGlobalValue;
163 extern fn LLVMGetNextGlobalAlias(GA: *Value) *Value;149 extern fn ZigLLVMEraseGlobalValue(GlobalVal: *Value) void;
164150
165 pub const getAliasee = LLVMAliasGetAliasee;151 pub const deleteGlobalValue = ZigLLVMDeleteGlobalValue;
166 extern fn LLVMAliasGetAliasee(Alias: *Value) *Value;152 extern fn ZigLLVMDeleteGlobalValue(GlobalVal: *Value) void;
167153
168 pub const setAliasee = LLVMAliasSetAliasee;154 pub const setAliasee = LLVMAliasSetAliasee;
169 extern fn LLVMAliasSetAliasee(Alias: *Value, Aliasee: *Value) void;155 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
186 pub const constAdd = LLVMConstAdd;157 pub const constAdd = LLVMConstAdd;
187 extern fn LLVMConstAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;158 extern fn LLVMConstAdd(LHSConstant: *Value, RHSConstant: *Value) *Value;
188159
...@@ -306,9 +277,6 @@ pub const Value = opaque {...@@ -306,9 +277,6 @@ pub const Value = opaque {
306 pub const setVolatile = LLVMSetVolatile;277 pub const setVolatile = LLVMSetVolatile;
307 extern fn LLVMSetVolatile(MemoryAccessInst: *Value, IsVolatile: Bool) void;278 extern fn LLVMSetVolatile(MemoryAccessInst: *Value, IsVolatile: Bool) void;
308279
309 pub const setAtomicSingleThread = LLVMSetAtomicSingleThread;
310 extern fn LLVMSetAtomicSingleThread(AtomicInst: *Value, SingleThread: Bool) void;
311
312 pub const setAlignment = LLVMSetAlignment;280 pub const setAlignment = LLVMSetAlignment;
313 extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void;281 extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void;
314282
...@@ -327,32 +295,17 @@ pub const Value = opaque {...@@ -327,32 +295,17 @@ pub const Value = opaque {
327 pub const fnSetSubprogram = ZigLLVMFnSetSubprogram;295 pub const fnSetSubprogram = ZigLLVMFnSetSubprogram;
328 extern fn ZigLLVMFnSetSubprogram(f: *Value, subprogram: *DISubprogram) void;296 extern fn ZigLLVMFnSetSubprogram(f: *Value, subprogram: *DISubprogram) void;
329297
330 pub const setValueName = LLVMSetValueName;298 pub const setValueName = LLVMSetValueName2;
331 extern fn LLVMSetValueName(Val: *Value, Name: [*:0]const u8) void;
332
333 pub const setValueName2 = LLVMSetValueName2;
334 extern fn LLVMSetValueName2(Val: *Value, Name: [*]const u8, NameLen: usize) void;299 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
339 pub const takeName = ZigLLVMTakeName;301 pub const takeName = ZigLLVMTakeName;
340 extern fn ZigLLVMTakeName(new_owner: *Value, victim: *Value) void;302 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
351 pub const getParam = LLVMGetParam;304 pub const getParam = LLVMGetParam;
352 extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;305 extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
353306
354 pub const setInitializer = LLVMSetInitializer;307 pub const setInitializer = ZigLLVMSetInitializer;
355 extern fn LLVMSetInitializer(GlobalVar: *Value, ConstantVal: *Value) void;308 extern fn ZigLLVMSetInitializer(GlobalVar: *Value, ConstantVal: ?*Value) void;
356309
357 pub const setDLLStorageClass = LLVMSetDLLStorageClass;310 pub const setDLLStorageClass = LLVMSetDLLStorageClass;
358 extern fn LLVMSetDLLStorageClass(Global: *Value, Class: DLLStorageClass) void;311 extern fn LLVMSetDLLStorageClass(Global: *Value, Class: DLLStorageClass) void;
...@@ -363,21 +316,6 @@ pub const Value = opaque {...@@ -363,21 +316,6 @@ pub const Value = opaque {
363 pub const replaceAllUsesWith = LLVMReplaceAllUsesWith;316 pub const replaceAllUsesWith = LLVMReplaceAllUsesWith;
364 extern fn LLVMReplaceAllUsesWith(OldVal: *Value, NewVal: *Value) void;317 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
381 pub const attachMetaData = ZigLLVMAttachMetaData;319 pub const attachMetaData = ZigLLVMAttachMetaData;
382 extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void;320 extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void;
383321
...@@ -389,9 +327,6 @@ pub const Type = opaque {...@@ -389,9 +327,6 @@ pub const Type = opaque {
389 pub const constNull = LLVMConstNull;327 pub const constNull = LLVMConstNull;
390 extern fn LLVMConstNull(Ty: *Type) *Value;328 extern fn LLVMConstNull(Ty: *Type) *Value;
391329
392 pub const constAllOnes = LLVMConstAllOnes;
393 extern fn LLVMConstAllOnes(Ty: *Type) *Value;
394
395 pub const constInt = LLVMConstInt;330 pub const constInt = LLVMConstInt;
396 extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) *Value;331 extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) *Value;
397332
...@@ -479,39 +414,18 @@ pub const Module = opaque {...@@ -479,39 +414,18 @@ pub const Module = opaque {
479 pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel;414 pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel;
480 extern fn ZigLLVMSetModuleCodeModel(module: *Module, code_model: CodeModel) void;415 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
485 pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace;417 pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace;
486 extern fn ZigLLVMAddFunctionInAddressSpace(*Module, Name: [*:0]const u8, FunctionTy: *Type, AddressSpace: c_uint) *Value;418 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
494 pub const printToString = LLVMPrintModuleToString;420 pub const printToString = LLVMPrintModuleToString;
495 extern fn LLVMPrintModuleToString(*Module) [*:0]const u8;421 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
500 pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace;423 pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace;
501 extern fn LLVMAddGlobalInAddressSpace(M: *Module, Ty: *Type, Name: [*:0]const u8, AddressSpace: c_uint) *Value;424 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
506 pub const dump = LLVMDumpModule;426 pub const dump = LLVMDumpModule;
507 extern fn LLVMDumpModule(M: *Module) void;427 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
515 pub const addAlias = LLVMAddAlias2;429 pub const addAlias = LLVMAddAlias2;
516 extern fn LLVMAddAlias2(430 extern fn LLVMAddAlias2(
517 M: *Module,431 M: *Module,
...@@ -521,16 +435,6 @@ pub const Module = opaque {...@@ -521,16 +435,6 @@ pub const Module = opaque {
521 Name: [*:0]const u8,435 Name: [*:0]const u8,
522 ) *Value;436 ) *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
534 pub const setTarget = LLVMSetTarget;438 pub const setTarget = LLVMSetTarget;
535 extern fn LLVMSetTarget(M: *Module, Triple: [*:0]const u8) void;439 extern fn LLVMSetTarget(M: *Module, Triple: [*:0]const u8) void;
536440
...@@ -553,9 +457,6 @@ pub const Module = opaque {...@@ -553,9 +457,6 @@ pub const Module = opaque {
553 extern fn LLVMWriteBitcodeToFile(M: *Module, Path: [*:0]const u8) c_int;457 extern fn LLVMWriteBitcodeToFile(M: *Module, Path: [*:0]const u8) c_int;
554};458};
555459
556pub const lookupIntrinsicID = LLVMLookupIntrinsicID;
557extern fn LLVMLookupIntrinsicID(Name: [*]const u8, NameLen: usize) c_uint;
558
559pub const disposeMessage = LLVMDisposeMessage;460pub const disposeMessage = LLVMDisposeMessage;
560extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;461extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;
561462
...@@ -616,12 +517,6 @@ pub const Builder = opaque {...@@ -616,12 +517,6 @@ pub const Builder = opaque {
616 Instr: ?*Value,517 Instr: ?*Value,
617 ) void;518 ) 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
625 pub const buildZExt = LLVMBuildZExt;520 pub const buildZExt = LLVMBuildZExt;
626 extern fn LLVMBuildZExt(521 extern fn LLVMBuildZExt(
627 *Builder,522 *Builder,
...@@ -630,14 +525,6 @@ pub const Builder = opaque {...@@ -630,14 +525,6 @@ pub const Builder = opaque {
630 Name: [*:0]const u8,525 Name: [*:0]const u8,
631 ) *Value;526 ) *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
641 pub const buildSExt = LLVMBuildSExt;528 pub const buildSExt = LLVMBuildSExt;
642 extern fn LLVMBuildSExt(529 extern fn LLVMBuildSExt(
643 *Builder,530 *Builder,
...@@ -646,14 +533,6 @@ pub const Builder = opaque {...@@ -646,14 +533,6 @@ pub const Builder = opaque {
646 Name: [*:0]const u8,533 Name: [*:0]const u8,
647 ) *Value;534 ) *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
657 pub const buildCall = LLVMBuildCall2;536 pub const buildCall = LLVMBuildCall2;
658 extern fn LLVMBuildCall2(537 extern fn LLVMBuildCall2(
659 *Builder,538 *Builder,
...@@ -664,18 +543,6 @@ pub const Builder = opaque {...@@ -664,18 +543,6 @@ pub const Builder = opaque {
664 Name: [*:0]const u8,543 Name: [*:0]const u8,
665 ) *Value;544 ) *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
679 pub const buildRetVoid = LLVMBuildRetVoid;546 pub const buildRetVoid = LLVMBuildRetVoid;
680 extern fn LLVMBuildRetVoid(*Builder) *Value;547 extern fn LLVMBuildRetVoid(*Builder) *Value;
681548
...@@ -694,12 +561,6 @@ pub const Builder = opaque {...@@ -694,12 +561,6 @@ pub const Builder = opaque {
694 pub const buildLoad = LLVMBuildLoad2;561 pub const buildLoad = LLVMBuildLoad2;
695 extern fn LLVMBuildLoad2(*Builder, Ty: *Type, PointerVal: *Value, Name: [*:0]const u8) *Value;562 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
703 pub const buildFAdd = LLVMBuildFAdd;564 pub const buildFAdd = LLVMBuildFAdd;
704 extern fn LLVMBuildFAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;565 extern fn LLVMBuildFAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
705566
...@@ -712,12 +573,6 @@ pub const Builder = opaque {...@@ -712,12 +573,6 @@ pub const Builder = opaque {
712 pub const buildNUWAdd = LLVMBuildNUWAdd;573 pub const buildNUWAdd = LLVMBuildNUWAdd;
713 extern fn LLVMBuildNUWAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;574 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
721 pub const buildFSub = LLVMBuildFSub;576 pub const buildFSub = LLVMBuildFSub;
722 extern fn LLVMBuildFSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;577 extern fn LLVMBuildFSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
723578
...@@ -733,12 +588,6 @@ pub const Builder = opaque {...@@ -733,12 +588,6 @@ pub const Builder = opaque {
733 pub const buildNUWSub = LLVMBuildNUWSub;588 pub const buildNUWSub = LLVMBuildNUWSub;
734 extern fn LLVMBuildNUWSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;589 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
742 pub const buildFMul = LLVMBuildFMul;591 pub const buildFMul = LLVMBuildFMul;
743 extern fn LLVMBuildFMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;592 extern fn LLVMBuildFMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
744593
...@@ -751,12 +600,6 @@ pub const Builder = opaque {...@@ -751,12 +600,6 @@ pub const Builder = opaque {
751 pub const buildNUWMul = LLVMBuildNUWMul;600 pub const buildNUWMul = LLVMBuildNUWMul;
752 extern fn LLVMBuildNUWMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;601 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
760 pub const buildUDiv = LLVMBuildUDiv;603 pub const buildUDiv = LLVMBuildUDiv;
761 extern fn LLVMBuildUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;604 extern fn LLVMBuildUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
762605
...@@ -799,21 +642,12 @@ pub const Builder = opaque {...@@ -799,21 +642,12 @@ pub const Builder = opaque {
799 pub const buildNSWShl = ZigLLVMBuildNSWShl;642 pub const buildNSWShl = ZigLLVMBuildNSWShl;
800 extern fn ZigLLVMBuildNSWShl(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;643 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
808 pub const buildOr = LLVMBuildOr;645 pub const buildOr = LLVMBuildOr;
809 extern fn LLVMBuildOr(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;646 extern fn LLVMBuildOr(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
810647
811 pub const buildXor = LLVMBuildXor;648 pub const buildXor = LLVMBuildXor;
812 extern fn LLVMBuildXor(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;649 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
817 pub const buildBitCast = LLVMBuildBitCast;651 pub const buildBitCast = LLVMBuildBitCast;
818 extern fn LLVMBuildBitCast(*Builder, Val: *Value, DestTy: *Type, Name: [*:0]const u8) *Value;652 extern fn LLVMBuildBitCast(*Builder, Val: *Value, DestTy: *Type, Name: [*:0]const u8) *Value;
819653
...@@ -999,102 +833,6 @@ pub const Builder = opaque {...@@ -999,102 +833,6 @@ pub const Builder = opaque {
999 Name: [*:0]const u8,833 Name: [*:0]const u8,
1000 ) *Value;834 ) *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
1098 pub const buildExactUDiv = LLVMBuildExactUDiv;836 pub const buildExactUDiv = LLVMBuildExactUDiv;
1099 extern fn LLVMBuildExactUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;837 extern fn LLVMBuildExactUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value;
1100838
...@@ -1116,39 +854,6 @@ pub const Builder = opaque {...@@ -1116,39 +854,6 @@ pub const Builder = opaque {
1116 pub const buildShuffleVector = LLVMBuildShuffleVector;854 pub const buildShuffleVector = LLVMBuildShuffleVector;
1117 extern fn LLVMBuildShuffleVector(*Builder, V1: *Value, V2: *Value, Mask: *Value, Name: [*:0]const u8) *Value;855 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
1152 pub const setFastMath = ZigLLVMSetFastMath;857 pub const setFastMath = ZigLLVMSetFastMath;
1153 extern fn ZigLLVMSetFastMath(B: *Builder, on_state: bool) void;858 extern fn ZigLLVMSetFastMath(B: *Builder, on_state: bool) void;
1154859
...@@ -1563,9 +1268,6 @@ extern fn ZigLLVMWriteImportLibrary(...@@ -1563,9 +1268,6 @@ extern fn ZigLLVMWriteImportLibrary(
1563 kill_at: bool,1268 kill_at: bool,
1564) bool;1269) bool;
15651270
1566pub const setCallElemTypeAttr = ZigLLVMSetCallElemTypeAttr;
1567extern fn ZigLLVMSetCallElemTypeAttr(Call: *Value, arg_index: usize, return_type: *Type) void;
1568
1569pub const Linkage = enum(c_uint) {1271pub const Linkage = enum(c_uint) {
1570 External,1272 External,
1571 AvailableExternally,1273 AvailableExternally,
...@@ -1784,9 +1486,6 @@ pub const DIGlobalVariable = opaque {...@@ -1784,9 +1486,6 @@ pub const DIGlobalVariable = opaque {
1784pub const DIGlobalVariableExpression = opaque {1486pub const DIGlobalVariableExpression = opaque {
1785 pub const getVariable = ZigLLVMGlobalGetVariable;1487 pub const getVariable = ZigLLVMGlobalGetVariable;
1786 extern fn ZigLLVMGlobalGetVariable(global_variable: *DIGlobalVariableExpression) *DIGlobalVariable;1488 extern fn ZigLLVMGlobalGetVariable(global_variable: *DIGlobalVariableExpression) *DIGlobalVariable;
1787
1788 pub const getExpression = ZigLLVMGlobalGetExpression;
1789 extern fn ZigLLVMGlobalGetExpression(global_variable: *DIGlobalVariableExpression) *DIGlobalExpression;
1790};1489};
1791pub const DIType = opaque {1490pub const DIType = opaque {
1792 pub const toScope = ZigLLVMTypeToScope;1491 pub const toScope = ZigLLVMTypeToScope;
src/value.zig+2-2
...@@ -3831,7 +3831,7 @@ pub const Value = struct {...@@ -3831,7 +3831,7 @@ pub const Value = struct {
38313831
3832 /// If the value is represented in-memory as a series of bytes that all3832 /// If the value is represented in-memory as a series of bytes that all
3833 /// have the same value, return that byte value, otherwise null.3833 /// 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 {
3835 const abi_size = std.math.cast(usize, ty.abiSize(mod)) orelse return null;3835 const abi_size = std.math.cast(usize, ty.abiSize(mod)) orelse return null;
3836 assert(abi_size >= 1);3836 assert(abi_size >= 1);
3837 const byte_buffer = try mod.gpa.alloc(u8, abi_size);3837 const byte_buffer = try mod.gpa.alloc(u8, abi_size);
...@@ -3852,7 +3852,7 @@ pub const Value = struct {...@@ -3852,7 +3852,7 @@ pub const Value = struct {
3852 for (byte_buffer[1..]) |byte| {3852 for (byte_buffer[1..]) |byte| {
3853 if (byte != first_byte) return null;3853 if (byte != first_byte) return null;
3854 }3854 }
3855 return try mod.intValue(Type.u8, first_byte);3855 return first_byte;
3856 }3856 }
38573857
3858 pub fn isGenericPoison(val: Value) bool {3858 pub fn isGenericPoison(val: Value) bool {
src/zig_llvm.cpp+34-436
...@@ -78,30 +78,6 @@...@@ -78,30 +78,6 @@
7878
79using namespace llvm;79using 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
105#ifndef NDEBUG81#ifndef NDEBUG
106static const bool assertions_on = true;82static const bool assertions_on = true;
107#else83#else
...@@ -179,14 +155,6 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri...@@ -179,14 +155,6 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri
179 return reinterpret_cast<LLVMTargetMachineRef>(TM);155 return reinterpret_cast<LLVMTargetMachineRef>(TM);
180}156}
181157
182unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD) {
183 return unwrap(TD)->getStackAlignment().value();
184}
185
186unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) {
187 return unwrap(TD)->getProgramAddressSpace();
188}
189
190namespace {158namespace {
191// LLVM's time profiler can provide a hierarchy view of the time spent159// LLVM's time profiler can provide a hierarchy view of the time spent
192// in each component. It generates JSON report in Chrome's "Trace Event"160// in each component. It generates JSON report in Chrome's "Trace Event"
...@@ -410,12 +378,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -410,12 +378,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
410 return false;378 return false;
411}379}
412380
413ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {381void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {
414 return wrap(Type::getTokenTy(*unwrap(context_ref)));
415}
416
417
418ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {
419 static OptBisect opt_bisect;382 static OptBisect opt_bisect;
420 opt_bisect.setLimit(limit);383 opt_bisect.setLimit(limit);
421 unwrap(context_ref)->setOptPassGate(opt_bisect);384 unwrap(context_ref)->setOptPassGate(opt_bisect);
...@@ -426,241 +389,23 @@ LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,...@@ -426,241 +389,23 @@ LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
426 return wrap(func);389 return wrap(func);
427}390}
428391
429LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,392void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind) {
430 LLVMValueRef *Args, unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr,393 CallInst::TailCallKind TCK;
431 const char *Name)394 switch (TailCallKind) {
432{395 case ZigLLVMTailCallKindNone:
433 FunctionType *FTy = unwrap<FunctionType>(Ty);396 TCK = CallInst::TCK_None;
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:
439 break;397 break;
440 case ZigLLVM_CallAttrNeverTail:398 case ZigLLVMTailCallKindTail:
441 call_inst->setTailCallKind(CallInst::TCK_NoTail);399 TCK = CallInst::TCK_Tail;
442 break;400 break;
443 case ZigLLVM_CallAttrNeverInline:401 case ZigLLVMTailCallKindMustTail:
444 call_inst->addFnAttr(Attribute::NoInline);402 TCK = CallInst::TCK_MustTail;
445 break;403 break;
446 case ZigLLVM_CallAttrAlwaysTail:404 case ZigLLVMTailCallKindNoTail:
447 call_inst->setTailCallKind(CallInst::TCK_MustTail);405 TCK = CallInst::TCK_NoTail;
448 break;406 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));
465 }407 }
466}408 unwrap<CallInst>(Call)->setTailCallKind(TCK);
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);
664}409}
665410
666void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram) {411void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram) {
...@@ -1181,82 +926,10 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {...@@ -1181,82 +926,10 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {
1181 }926 }
1182}927}
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
1222void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {929void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
1223 cl::ParseCommandLineOptions(argc, argv);930 cl::ParseCommandLineOptions(argc, argv);
1224}931}
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
1260void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64) {933void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64) {
1261 unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);934 unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);
1262 unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4);935 unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4);
...@@ -1314,50 +987,6 @@ LLVMValueRef ZigLLVMBuildAllocaInAddressSpace(LLVMBuilderRef builder, LLVMTypeRe...@@ -1314,50 +987,6 @@ LLVMValueRef ZigLLVMBuildAllocaInAddressSpace(LLVMBuilderRef builder, LLVMTypeRe
1314 return wrap(unwrap(builder)->CreateAlloca(unwrap(Ty), AddressSpace, nullptr, Name));987 return wrap(unwrap(builder)->CreateAlloca(unwrap(Ty), AddressSpace, nullptr, Name));
1315}988}
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
1361bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch,990bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch,
1362 const char *output_lib_path, bool kill_at)991 const char *output_lib_path, bool kill_at)
1363{992{
...@@ -1489,72 +1118,41 @@ bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disab...@@ -1489,72 +1118,41 @@ bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disab
1489 return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);1118 return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
1490}1119}
14911120
1492inline LLVMAttributeRef wrap(Attribute Attr) {1121void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) {
1493 return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer());1122 unwrap(new_owner)->takeName(unwrap(victim));
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)));
1530}1123}
15311124
1532LLVMValueRef ZigLLVMBuildMulReduce(LLVMBuilderRef B, LLVMValueRef Val) {1125void ZigLLVMRemoveGlobalValue(LLVMValueRef GlobalVal) {
1533 return wrap(unwrap(B)->CreateMulReduce(unwrap(Val)));1126 unwrap<GlobalValue>(GlobalVal)->removeFromParent();
1534}1127}
15351128
1536LLVMValueRef ZigLLVMBuildFPAddReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val) {1129void ZigLLVMEraseGlobalValue(LLVMValueRef GlobalVal) {
1537 return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc), unwrap(Val)));1130 unwrap<GlobalValue>(GlobalVal)->eraseFromParent();
1538}1131}
15391132
1540LLVMValueRef ZigLLVMBuildFPMulReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val) {1133void ZigLLVMDeleteGlobalValue(LLVMValueRef GlobalVal) {
1541 return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc), unwrap(Val)));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 }
1542}1144}
15431145
1544void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) {1146void ZigLLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal) {
1545 unwrap(new_owner)->takeName(unwrap(victim));1147 unwrap<GlobalVariable>(GlobalVar)->setInitializer(ConstantVal ? unwrap<Constant>(ConstantVal) : nullptr);
1546}1148}
15471149
1548ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {1150ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
1549 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());1151 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());
1554}1152}
15551153
1556void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression) {1154void 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));
1558}1156}
15591157
1560static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");1158static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");
src/zig_llvm.h+13-105
...@@ -43,13 +43,6 @@ struct ZigLLVMInsertionPoint;...@@ -43,13 +43,6 @@ struct ZigLLVMInsertionPoint;
43struct ZigLLVMDINode;43struct ZigLLVMDINode;
44struct ZigLLVMMDString;44struct 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
53ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,46ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
54 char **error_message, bool is_debug,47 char **error_message, bool is_debug,
55 bool is_small, bool time_report, bool tsan, bool lto,48 bool is_small, bool time_report, bool tsan, bool lto,
...@@ -67,13 +60,20 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co...@@ -67,13 +60,20 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co
67 const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,60 const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
68 LLVMCodeModel CodeModel, bool function_sections, enum ZigLLVMABIType float_abi, const char *abi_name);61 LLVMCodeModel CodeModel, bool function_sections, enum ZigLLVMABIType float_abi, const char *abi_name);
6962
70ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
71
72ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit);63ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit);
7364
74ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,65ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
75 LLVMTypeRef FunctionTy, unsigned AddressSpace);66 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
77enum ZigLLVM_CallingConv {77enum ZigLLVM_CallingConv {
78 ZigLLVM_C = 0,78 ZigLLVM_C = 0,
79 ZigLLVM_Fast = 8,79 ZigLLVM_Fast = 8,
...@@ -122,66 +122,6 @@ enum ZigLLVM_CallingConv {...@@ -122,66 +122,6 @@ enum ZigLLVM_CallingConv {
122 ZigLLVM_MaxID = 1023,122 ZigLLVM_MaxID = 1023,
123};123};
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
185ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,125ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
186 const char *name);126 const char *name);
187ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,127ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
...@@ -345,22 +285,10 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBu...@@ -345,22 +285,10 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBu
345 struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref);285 struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref);
346286
347ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);287ZIG_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
360ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);289ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);
361290
362ZIG_EXTERN_C ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression);291ZIG_EXTERN_C ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression);
363ZIG_EXTERN_C ZigLLVMDIGlobalExpression* ZigLLVMGlobalGetExpression(ZigLLVMDIGlobalVariableExpression *global_variable_expression);
364ZIG_EXTERN_C void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression);292ZIG_EXTERN_C void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression);
365293
366294
...@@ -563,19 +491,11 @@ enum ZigLLVM_ObjectFormatType {...@@ -563,19 +491,11 @@ enum ZigLLVM_ObjectFormatType {
563 ZigLLVM_XCOFF,491 ZigLLVM_XCOFF,
564};492};
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
578ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim);494ZIG_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
580#define ZigLLVM_DIFlags_Zero 0U500#define ZigLLVM_DIFlags_Zero 0U
581#define ZigLLVM_DIFlags_Private 1U501#define ZigLLVM_DIFlags_Private 1U
...@@ -610,11 +530,6 @@ ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim);...@@ -610,11 +530,6 @@ ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim);
610#define ZigLLVM_DIFlags_LittleEndian (1U << 28)530#define ZigLLVM_DIFlags_LittleEndian (1U << 28)
611#define ZigLLVM_DIFlags_AllCallsDescribed (1U << 29)531#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
618ZIG_EXTERN_C bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early, bool disable_output);533ZIG_EXTERN_C bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early, bool disable_output);
619ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output);534ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output);
620ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output);535ZIG_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...@@ -625,11 +540,4 @@ ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **fil
625ZIG_EXTERN_C bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch,540ZIG_EXTERN_C bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch,
626 const char *output_lib_path, bool kill_at);541 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
635#endif543#endif