authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-08 10:15:11-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-08 21:32:50-04:00
log2bdd180c6f6c76940ccfe8c8532fefec208661ea
tree95fa180ff9bd13bff056e10ee6048a712f3809c1
parent2499d8fb73b943640cbc7d0484377fffbee403c6

llvm: finish converting globals


5 files changed, 987 insertions(+), 791 deletions(-)

src/codegen/llvm.zig+446-637
...@@ -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
...@@ -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,
...@@ -991,9 +989,8 @@ pub const Object = struct {...@@ -991,9 +989,8 @@ pub const Object = struct {
991 }989 }
992990
993 fn genErrorNameTable(o: *Object) Allocator.Error!void {991 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.992 // 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;993 if (o.error_name_table == .none) return;
996 if (error_name_table_ptr_global == .none) return;
997994
998 const mod = o.module;995 const mod = o.module;
999996
...@@ -1003,72 +1000,42 @@ pub const Object = struct {...@@ -1003,72 +1000,42 @@ pub const Object = struct {
10031000
1004 // TODO: Address space1001 // TODO: Address space
1005 const slice_ty = Type.slice_const_u8_sentinel_0;1002 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);1003 const llvm_usize_ty = try o.lowerType(Type.usize);
1008 const llvm_slice_ty = try o.lowerType(slice_ty);1004 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);1005 const llvm_table_ty = try o.builder.arrayType(error_name_list.len, llvm_slice_ty);
10101006
1011 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);1007 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
1012 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name_nts| {1008 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {
1013 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_nts));1009 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
1014 const str_init = try o.builder.stringNullConst(name);1010 const name_init = try o.builder.stringNullConst(name_string);
1015 const str_ty = str_init.typeOf(&o.builder);1011 const name_variable_index =
1016 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");1012 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
1017 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));1013 try name_variable_index.setInitializer(name_init, &o.builder);
1018 str_llvm_global.setLinkage(.Private);1014 name_variable_index.setLinkage(.private, &o.builder);
1019 str_llvm_global.setGlobalConstant(.True);1015 name_variable_index.setMutability(.constant, &o.builder);
1020 str_llvm_global.setUnnamedAddr(.True);1016 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
1021 str_llvm_global.setAlignment(1);1017 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);
10381018
1039 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{1019 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
1040 global_index.toConst(),1020 name_variable_index.toConst(&o.builder),
1041 try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len),1021 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len),
1042 });1022 });
1043 }1023 }
10441024
1045 const error_name_table_init = try o.builder.arrayConst(llvm_table_ty, llvm_errors);1025 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), "");1026 try table_variable_index.setInitializer(
1047 error_name_table_global.setInitializer(error_name_table_init.toLlvm(&o.builder));1027 try o.builder.arrayConst(llvm_table_ty, llvm_errors),
1048 error_name_table_global.setLinkage(.Private);1028 &o.builder,
1049 error_name_table_global.setGlobalConstant(.True);1029 );
1050 error_name_table_global.setUnnamedAddr(.True);1030 table_variable_index.setLinkage(.private, &o.builder);
1051 error_name_table_global.setAlignment(slice_alignment); // TODO: Dont hardcode1031 table_variable_index.setMutability(.constant, &o.builder);
10521032 table_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
1053 var global = Builder.Global{1033 table_variable_index.setAlignment(
1054 .linkage = .private,1034 Builder.Alignment.fromByteUnits(slice_ty.abiAlignment(mod)),
1055 .unnamed_addr = .unnamed_addr,1035 &o.builder,
1056 .type = llvm_table_ty,1036 );
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);
10681037
1069 const error_name_table_ptr = error_name_table_global;1038 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 }1039 }
10731040
1074 fn genCmpLtErrorsLenFunction(o: *Object) !void {1041 fn genCmpLtErrorsLenFunction(o: *Object) !void {
...@@ -1181,17 +1148,7 @@ pub const Object = struct {...@@ -1181,17 +1148,7 @@ pub const Object = struct {
1181 }1148 }
1182 }1149 }
11831150
1184 if (comp.verbose_llvm_bc) |path| {1151 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 }
11951152
1196 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);1153 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
1197 defer arena_allocator.deinit();1154 defer arena_allocator.deinit();
...@@ -1200,20 +1157,10 @@ pub const Object = struct {...@@ -1200,20 +1157,10 @@ pub const Object = struct {
1200 const mod = comp.bin_file.options.module.?;1157 const mod = comp.bin_file.options.module.?;
1201 const cache_dir = mod.zig_cache_artifact_directory;1158 const cache_dir = mod.zig_cache_artifact_directory;
12021159
1203 if (std.debug.runtime_safety) {1160 if (std.debug.runtime_safety and !try self.builder.verify()) {
1204 var error_message: [*:0]const u8 = undefined;1161 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 error1162 _ = self.builder.printToFileZ(emit_llvm_ir_path);
1206 defer llvm.disposeMessage(error_message);1163 @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 }1164 }
12181165
1219 var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|1166 var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|
...@@ -1233,12 +1180,17 @@ pub const Object = struct {...@@ -1233,12 +1180,17 @@ pub const Object = struct {
1233 emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,1180 emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,
1234 });1181 });
12351182
1183 if (!self.builder.useLibLlvm()) {
1184 log.err("emitting without libllvm not implemented", .{});
1185 return error.FailedToEmit;
1186 }
1187
1236 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.1188 // 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.1189 // So we call the entire pipeline multiple times if this is requested.
1238 var error_message: [*:0]const u8 = undefined;1190 var error_message: [*:0]const u8 = undefined;
1239 if (emit_asm_path != null and emit_bin_path != null) {1191 if (emit_asm_path != null and emit_bin_path != null) {
1240 if (self.target_machine.emitToFile(1192 if (self.target_machine.emitToFile(
1241 self.llvm_module,1193 self.builder.llvm.module.?,
1242 &error_message,1194 &error_message,
1243 comp.bin_file.options.optimize_mode == .Debug,1195 comp.bin_file.options.optimize_mode == .Debug,
1244 comp.bin_file.options.optimize_mode == .ReleaseSmall,1196 comp.bin_file.options.optimize_mode == .ReleaseSmall,
...@@ -1262,7 +1214,7 @@ pub const Object = struct {...@@ -1262,7 +1214,7 @@ pub const Object = struct {
1262 }1214 }
12631215
1264 if (self.target_machine.emitToFile(1216 if (self.target_machine.emitToFile(
1265 self.llvm_module,1217 self.builder.llvm.module.?,
1266 &error_message,1218 &error_message,
1267 comp.bin_file.options.optimize_mode == .Debug,1219 comp.bin_file.options.optimize_mode == .Debug,
1268 comp.bin_file.options.optimize_mode == .ReleaseSmall,1220 comp.bin_file.options.optimize_mode == .ReleaseSmall,
...@@ -1305,11 +1257,9 @@ pub const Object = struct {...@@ -1305,11 +1257,9 @@ pub const Object = struct {
1305 .err_msg = null,1257 .err_msg = null,
1306 };1258 };
13071259
1308 const function = try o.resolveLlvmFunction(decl_index);1260 const function_index = try o.resolveLlvmFunction(decl_index);
1309 const global = function.ptrConst(&o.builder).global;
1310 const llvm_func = global.toLlvm(&o.builder);
13111261
1312 var attributes = try function.ptrConst(&o.builder).attributes.toWip(&o.builder);1262 var attributes = try function_index.ptrConst(&o.builder).attributes.toWip(&o.builder);
1313 defer attributes.deinit(&o.builder);1263 defer attributes.deinit(&o.builder);
13141264
1315 if (func.analysis(ip).is_noinline) {1265 if (func.analysis(ip).is_noinline) {
...@@ -1354,17 +1304,14 @@ pub const Object = struct {...@@ -1354,17 +1304,14 @@ pub const Object = struct {
1354 } }, &o.builder);1304 } }, &o.builder);
1355 }1305 }
13561306
1357 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| {1307 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
1358 function.ptr(&o.builder).section = try o.builder.string(section);1308 function_index.setSection(try o.builder.string(section), &o.builder);
1359 llvm_func.setSection(section);
1360 }
13611309
1362 var deinit_wip = true;1310 var deinit_wip = true;
1363 var wip = try Builder.WipFunction.init(&o.builder, function);1311 var wip = try Builder.WipFunction.init(&o.builder, function_index);
1364 defer if (deinit_wip) wip.deinit();1312 defer if (deinit_wip) wip.deinit();
1365 wip.cursor = .{ .block = try wip.block(0, "Entry") };1313 wip.cursor = .{ .block = try wip.block(0, "Entry") };
13661314
1367 const builder = wip.llvm.builder;
1368 var llvm_arg_i: u32 = 0;1315 var llvm_arg_i: u32 = 0;
13691316
1370 // This gets the LLVM values from the function and stores them in `dg.args`.1317 // This gets the LLVM values from the function and stores them in `dg.args`.
...@@ -1566,7 +1513,7 @@ pub const Object = struct {...@@ -1566,7 +1513,7 @@ pub const Object = struct {
1566 }1513 }
1567 }1514 }
15681515
1569 function.setAttributes(try attributes.finish(&o.builder), &o.builder);1516 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
15701517
1571 var di_file: ?*llvm.DIFile = null;1518 var di_file: ?*llvm.DIFile = null;
1572 var di_scope: ?*llvm.DIScope = null;1519 var di_scope: ?*llvm.DIScope = null;
...@@ -1585,7 +1532,7 @@ pub const Object = struct {...@@ -1585,7 +1532,7 @@ pub const Object = struct {
1585 const subprogram = dib.createFunction(1532 const subprogram = dib.createFunction(
1586 di_file.?.toScope(),1533 di_file.?.toScope(),
1587 ip.stringToSlice(decl.name),1534 ip.stringToSlice(decl.name),
1588 llvm_func.getValueName(),1535 function_index.name(&o.builder).slice(&o.builder).?,
1589 di_file.?,1536 di_file.?,
1590 line_number,1537 line_number,
1591 decl_di_ty,1538 decl_di_ty,
...@@ -1598,7 +1545,7 @@ pub const Object = struct {...@@ -1598,7 +1545,7 @@ pub const Object = struct {
1598 );1545 );
1599 try o.di_map.put(gpa, decl, subprogram.toNode());1546 try o.di_map.put(gpa, decl, subprogram.toNode());
16001547
1601 llvm_func.fnSetSubprogram(subprogram);1548 function_index.toLlvm(&o.builder).fnSetSubprogram(subprogram);
16021549
1603 di_scope = subprogram.toScope();1550 di_scope = subprogram.toScope();
1604 }1551 }
...@@ -1609,7 +1556,6 @@ pub const Object = struct {...@@ -1609,7 +1556,6 @@ pub const Object = struct {
1609 .liveness = liveness,1556 .liveness = liveness,
1610 .dg = &dg,1557 .dg = &dg,
1611 .wip = wip,1558 .wip = wip,
1612 .builder = builder,
1613 .ret_ptr = ret_ptr,1559 .ret_ptr = ret_ptr,
1614 .args = args.items,1560 .args = args.items,
1615 .arg_index = 0,1561 .arg_index = 0,
...@@ -1670,8 +1616,7 @@ pub const Object = struct {...@@ -1670,8 +1616,7 @@ pub const Object = struct {
1670 const gpa = mod.gpa;1616 const gpa = mod.gpa;
1671 // If the module does not already have the function, we ignore this function call1617 // If the module does not already have the function, we ignore this function call
1672 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.1618 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
1673 const global = self.decl_map.get(decl_index) orelse return;1619 const global_index = self.decl_map.get(decl_index) orelse return;
1674 const llvm_global = global.toLlvm(&self.builder);
1675 const decl = mod.declPtr(decl_index);1620 const decl = mod.declPtr(decl_index);
1676 if (decl.isExtern(mod)) {1621 if (decl.isExtern(mod)) {
1677 const decl_name = decl_name: {1622 const decl_name = decl_name: {
...@@ -1689,114 +1634,91 @@ pub const Object = struct {...@@ -1689,114 +1634,91 @@ pub const Object = struct {
1689 };1634 };
16901635
1691 if (self.builder.getGlobal(decl_name)) |other_global| {1636 if (self.builder.getGlobal(decl_name)) |other_global| {
1692 if (other_global.toLlvm(&self.builder) != llvm_global) {1637 if (other_global != global_index) {
1693 try self.extern_collisions.put(gpa, decl_index, {});1638 try self.extern_collisions.put(gpa, decl_index, {});
1694 }1639 }
1695 }1640 }
16961641
1697 try global.rename(decl_name, &self.builder);1642 try global_index.rename(decl_name, &self.builder);
1698 global.ptr(&self.builder).unnamed_addr = .default;1643 global_index.setLinkage(.external, &self.builder);
1699 llvm_global.setUnnamedAddr(.False);1644 global_index.setUnnamedAddr(.default, &self.builder);
1700 global.ptr(&self.builder).linkage = .external;1645 if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder);
1701 llvm_global.setLinkage(.External);
1702 if (mod.wantDllExports()) {
1703 global.ptr(&self.builder).dll_storage_class = .default;
1704 llvm_global.setDLLStorageClass(.Default);
1705 }
1706 if (self.di_map.get(decl)) |di_node| {1646 if (self.di_map.get(decl)) |di_node| {
1707 const decl_name_slice = decl_name.slice(&self.builder).?;1647 const decl_name_slice = decl_name.slice(&self.builder).?;
1708 if (try decl.isFunction(mod)) {1648 if (try decl.isFunction(mod)) {
1709 const di_func: *llvm.DISubprogram = @ptrCast(di_node);1649 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
1710 const linkage_name = llvm.MDString.get(self.builder.llvm.context, decl_name_slice.ptr, decl_name_slice.len);1650 const linkage_name = llvm.MDString.get(
1651 self.builder.llvm.context,
1652 decl_name_slice.ptr,
1653 decl_name_slice.len,
1654 );
1711 di_func.replaceLinkageName(linkage_name);1655 di_func.replaceLinkageName(linkage_name);
1712 } else {1656 } else {
1713 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);1657 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
1714 const linkage_name = llvm.MDString.get(self.builder.llvm.context, decl_name_slice.ptr, decl_name_slice.len);1658 const linkage_name = llvm.MDString.get(
1659 self.builder.llvm.context,
1660 decl_name_slice.ptr,
1661 decl_name_slice.len,
1662 );
1715 di_global.replaceLinkageName(linkage_name);1663 di_global.replaceLinkageName(linkage_name);
1716 }1664 }
1717 }1665 }
1718 if (decl.val.getVariable(mod)) |decl_var| {1666 if (decl.val.getVariable(mod)) |decl_var| {
1719 if (decl_var.is_threadlocal) {1667 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1720 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =1668 if (decl_var.is_threadlocal) .generaldynamic else .default,
1721 .generaldynamic;1669 &self.builder,
1722 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1670 );
1723 } else {1671 if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder);
1724 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1725 .default;
1726 llvm_global.setThreadLocalMode(.NotThreadLocal);
1727 }
1728 if (decl_var.is_weak_linkage) {
1729 global.ptr(&self.builder).linkage = .extern_weak;
1730 llvm_global.setLinkage(.ExternalWeak);
1731 }
1732 }1672 }
1733 global.ptr(&self.builder).updateAttributes();
1734 } else if (exports.len != 0) {1673 } else if (exports.len != 0) {
1735 const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exports[0].opts.name));1674 const main_exp_name = try self.builder.string(
1736 try global.rename(exp_name, &self.builder);1675 mod.intern_pool.stringToSlice(exports[0].opts.name),
1737 global.ptr(&self.builder).unnamed_addr = .default;1676 );
1738 llvm_global.setUnnamedAddr(.False);1677 try global_index.rename(main_exp_name, &self.builder);
1739 if (mod.wantDllExports()) {1678 global_index.setUnnamedAddr(.default, &self.builder);
1740 global.ptr(&self.builder).dll_storage_class = .dllexport;1679 if (mod.wantDllExports()) global_index.setDllStorageClass(.dllexport, &self.builder);
1741 llvm_global.setDLLStorageClass(.DLLExport);
1742 }
1743 if (self.di_map.get(decl)) |di_node| {1680 if (self.di_map.get(decl)) |di_node| {
1744 const exp_name_slice = exp_name.slice(&self.builder).?;1681 const main_exp_name_slice = main_exp_name.slice(&self.builder).?;
1745 if (try decl.isFunction(mod)) {1682 if (try decl.isFunction(mod)) {
1746 const di_func: *llvm.DISubprogram = @ptrCast(di_node);1683 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
1747 const linkage_name = llvm.MDString.get(self.builder.llvm.context, exp_name_slice.ptr, exp_name_slice.len);1684 const linkage_name = llvm.MDString.get(
1685 self.builder.llvm.context,
1686 main_exp_name_slice.ptr,
1687 main_exp_name_slice.len,
1688 );
1748 di_func.replaceLinkageName(linkage_name);1689 di_func.replaceLinkageName(linkage_name);
1749 } else {1690 } else {
1750 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);1691 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
1751 const linkage_name = llvm.MDString.get(self.builder.llvm.context, exp_name_slice.ptr, exp_name_slice.len);1692 const linkage_name = llvm.MDString.get(
1693 self.builder.llvm.context,
1694 main_exp_name_slice.ptr,
1695 main_exp_name_slice.len,
1696 );
1752 di_global.replaceLinkageName(linkage_name);1697 di_global.replaceLinkageName(linkage_name);
1753 }1698 }
1754 }1699 }
1755 switch (exports[0].opts.linkage) {1700 global_index.setLinkage(switch (exports[0].opts.linkage) {
1756 .Internal => unreachable,1701 .Internal => unreachable,
1757 .Strong => {1702 .Strong => .external,
1758 global.ptr(&self.builder).linkage = .external;1703 .Weak => .weak_odr,
1759 llvm_global.setLinkage(.External);1704 .LinkOnce => .linkonce_odr,
1760 },1705 }, &self.builder);
1761 .Weak => {1706 global_index.setVisibility(switch (exports[0].opts.visibility) {
1762 global.ptr(&self.builder).linkage = .weak_odr;1707 .default => .default,
1763 llvm_global.setLinkage(.WeakODR);1708 .hidden => .hidden,
1764 },1709 .protected => .protected,
1765 .LinkOnce => {1710 }, &self.builder);
1766 global.ptr(&self.builder).linkage = .linkonce_odr;1711 if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section|
1767 llvm_global.setLinkage(.LinkOnceODR);1712 switch (global_index.ptrConst(&self.builder).kind) {
1768 },1713 inline .variable, .function => |impl_index| impl_index.setSection(
1769 }
1770 switch (exports[0].opts.visibility) {
1771 .default => {
1772 global.ptr(&self.builder).visibility = .default;
1773 llvm_global.setVisibility(.Default);
1774 },
1775 .hidden => {
1776 global.ptr(&self.builder).visibility = .hidden;
1777 llvm_global.setVisibility(.Hidden);
1778 },
1779 .protected => {
1780 global.ptr(&self.builder).visibility = .protected;
1781 llvm_global.setVisibility(.Protected);
1782 },
1783 }
1784 if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section| {
1785 switch (global.ptrConst(&self.builder).kind) {
1786 inline .variable, .function => |impl_index| impl_index.ptr(&self.builder).section =
1787 try self.builder.string(section),1714 try self.builder.string(section),
1715 &self.builder,
1716 ),
1788 else => unreachable,1717 else => unreachable,
1789 }1718 };
1790 llvm_global.setSection(section);1719 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
1791 }1720 global_index.ptrConst(&self.builder).kind
1792 if (decl.val.getVariable(mod)) |decl_var| {1721 .variable.setThreadLocal(.generaldynamic, &self.builder);
1793 if (decl_var.is_threadlocal) {
1794 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1795 .generaldynamic;
1796 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1797 }
1798 }
1799 global.ptr(&self.builder).updateAttributes();
18001722
1801 // If a Decl is exported more than one time (which is rare),1723 // If a Decl is exported more than one time (which is rare),
1802 // we add aliases for all but the first export.1724 // we add aliases for all but the first export.
...@@ -1805,49 +1727,47 @@ pub const Object = struct {...@@ -1805,49 +1727,47 @@ pub const Object = struct {
1805 // Until then we iterate over existing aliases and make them point1727 // Until then we iterate over existing aliases and make them point
1806 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.1728 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.
1807 for (exports[1..]) |exp| {1729 for (exports[1..]) |exp| {
1808 const exp_name_z = mod.intern_pool.stringToSlice(exp.opts.name);1730 const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exp.opts.name));
18091731 if (self.builder.getGlobal(exp_name)) |global| {
1810 if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| {1732 switch (global.ptrConst(&self.builder).kind) {
1811 alias.setAliasee(llvm_global);1733 .alias => |alias| {
1812 } else {1734 alias.setAliasee(global_index.toConst(), &self.builder);
1813 _ = self.llvm_module.addAlias(1735 continue;
1814 global.ptrConst(&self.builder).type.toLlvm(&self.builder),1736 },
1815 0,1737 .variable, .function => {},
1816 llvm_global,1738 else => unreachable,
1817 exp_name_z,1739 }
1818 );
1819 }1740 }
1741 _ = try self.builder.addAlias(
1742 exp_name,
1743 global_index.typeOf(&self.builder),
1744 .default,
1745 global_index.toConst(),
1746 );
1820 }1747 }
1821 } else {1748 } else {
1822 const fqn = try self.builder.string(mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)));1749 const fqn = try self.builder.string(
1823 try global.rename(fqn, &self.builder);1750 mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)),
1824 global.ptr(&self.builder).linkage = .internal;1751 );
1825 llvm_global.setLinkage(.Internal);1752 try global_index.rename(fqn, &self.builder);
1826 if (mod.wantDllExports()) {1753 global_index.setLinkage(.internal, &self.builder);
1827 global.ptr(&self.builder).dll_storage_class = .default;1754 if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder);
1828 llvm_global.setDLLStorageClass(.Default);1755 global_index.setUnnamedAddr(.unnamed_addr, &self.builder);
1829 }
1830 global.ptr(&self.builder).unnamed_addr = .unnamed_addr;
1831 llvm_global.setUnnamedAddr(.True);
1832 if (decl.val.getVariable(mod)) |decl_var| {1756 if (decl.val.getVariable(mod)) |decl_var| {
1833 const single_threaded = mod.comp.bin_file.options.single_threaded;1757 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1834 if (decl_var.is_threadlocal and !single_threaded) {1758 if (decl_var.is_threadlocal and !mod.comp.bin_file.options.single_threaded)
1835 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =1759 .generaldynamic
1836 .generaldynamic;1760 else
1837 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);1761 .default,
1838 } else {1762 &self.builder,
1839 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =1763 );
1840 .default;
1841 llvm_global.setThreadLocalMode(.NotThreadLocal);
1842 }
1843 }1764 }
1844 global.ptr(&self.builder).updateAttributes();
1845 }1765 }
1846 }1766 }
18471767
1848 pub fn freeDecl(self: *Object, decl_index: Module.Decl.Index) void {1768 pub fn freeDecl(self: *Object, decl_index: Module.Decl.Index) void {
1849 const global = self.decl_map.get(decl_index) orelse return;1769 const global = self.decl_map.get(decl_index) orelse return;
1850 global.toLlvm(&self.builder).deleteGlobal();1770 global.delete(&self.builder);
1851 }1771 }
18521772
1853 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {1773 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {
...@@ -2883,8 +2803,12 @@ pub const Object = struct {...@@ -2883,8 +2803,12 @@ pub const Object = struct {
2883 /// If the llvm function does not exist, create it.2803 /// If the llvm function does not exist, create it.
2884 /// Note that this can be called before the function's semantic analysis has2804 /// Note that this can be called before the function's semantic analysis has
2885 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.2805 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.
2886 fn resolveLlvmFunction(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Function.Index {2806 fn resolveLlvmFunction(
2807 o: *Object,
2808 decl_index: Module.Decl.Index,
2809 ) Allocator.Error!Builder.Function.Index {
2887 const mod = o.module;2810 const mod = o.module;
2811 const ip = &mod.intern_pool;
2888 const gpa = o.gpa;2812 const gpa = o.gpa;
2889 const decl = mod.declPtr(decl_index);2813 const decl = mod.declPtr(decl_index);
2890 const zig_fn_type = decl.ty;2814 const zig_fn_type = decl.ty;
...@@ -2896,31 +2820,20 @@ pub const Object = struct {...@@ -2896,31 +2820,20 @@ pub const Object = struct {
2896 const target = mod.getTarget();2820 const target = mod.getTarget();
2897 const sret = firstParamSRet(fn_info, mod);2821 const sret = firstParamSRet(fn_info, mod);
28982822
2899 const fn_type = try o.lowerType(zig_fn_type);2823 const function_index = try o.builder.addFunction(
29002824 try o.lowerType(zig_fn_type),
2901 const ip = &mod.intern_pool;2825 try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))),
2902 const fqn = try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod)));2826 toLlvmAddressSpace(decl.@"addrspace", target),
29032827 );
2904 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);2828 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
2905 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(fqn.slice(&o.builder).?, fn_type.toLlvm(&o.builder), @intFromEnum(llvm_addrspace));
2906
2907 var global = Builder.Global{
2908 .type = fn_type,
2909 .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) },
2910 };
2911 var function = Builder.Function{
2912 .global = @enumFromInt(o.builder.globals.count()),
2913 };
29142829
2915 var attributes: Builder.FunctionAttributes.Wip = .{};2830 var attributes: Builder.FunctionAttributes.Wip = .{};
2916 defer attributes.deinit(&o.builder);2831 defer attributes.deinit(&o.builder);
29172832
2918 const is_extern = decl.isExtern(mod);2833 const is_extern = decl.isExtern(mod);
2919 if (!is_extern) {2834 if (!is_extern) {
2920 global.linkage = .internal;2835 function_index.setLinkage(.internal, &o.builder);
2921 llvm_fn.setLinkage(.Internal);2836 function_index.setUnnamedAddr(.unnamed_addr, &o.builder);
2922 global.unnamed_addr = .unnamed_addr;
2923 llvm_fn.setUnnamedAddr(.True);
2924 } else {2837 } else {
2925 if (target.isWasm()) {2838 if (target.isWasm()) {
2926 try attributes.addFnAttr(.{ .string = .{2839 try attributes.addFnAttr(.{ .string = .{
...@@ -2957,35 +2870,22 @@ pub const Object = struct {...@@ -2957,35 +2870,22 @@ pub const Object = struct {
2957 }2870 }
29582871
2959 switch (fn_info.cc) {2872 switch (fn_info.cc) {
2960 .Unspecified, .Inline => {2873 .Unspecified, .Inline => function_index.setCallConv(.fastcc, &o.builder),
2961 function.call_conv = .fastcc;2874 .Naked => try attributes.addFnAttr(.naked, &o.builder),
2962 llvm_fn.setFunctionCallConv(.Fast);
2963 },
2964 .Naked => {
2965 try attributes.addFnAttr(.naked, &o.builder);
2966 },
2967 .Async => {2875 .Async => {
2968 function.call_conv = .fastcc;2876 function_index.setCallConv(.fastcc, &o.builder);
2969 llvm_fn.setFunctionCallConv(.Fast);
2970 @panic("TODO: LLVM backend lower async function");2877 @panic("TODO: LLVM backend lower async function");
2971 },2878 },
2972 else => {2879 else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),
2973 function.call_conv = toLlvmCallConv(fn_info.cc, target);
2974 llvm_fn.setFunctionCallConv(@enumFromInt(@intFromEnum(function.call_conv)));
2975 },
2976 }2880 }
29772881
2978 if (fn_info.alignment.toByteUnitsOptional()) |a| {2882 if (fn_info.alignment.toByteUnitsOptional()) |alignment|
2979 function.alignment = Builder.Alignment.fromByteUnits(a);2883 function_index.setAlignment(Builder.Alignment.fromByteUnits(alignment), &o.builder);
2980 llvm_fn.setAlignment(@intCast(a));
2981 }
29822884
2983 // Function attributes that are independent of analysis results of the function body.2885 // Function attributes that are independent of analysis results of the function body.
2984 try o.addCommonFnAttributes(&attributes);2886 try o.addCommonFnAttributes(&attributes);
29852887
2986 if (fn_info.return_type == .noreturn_type) {2888 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
2987 try attributes.addFnAttr(.noreturn, &o.builder);
2988 }
29892889
2990 // Add parameter attributes. We handle only the case of extern functions (no body)2890 // Add parameter attributes. We handle only the case of extern functions (no body)
2991 // because functions with bodies are handled in `updateFunc`.2891 // because functions with bodies are handled in `updateFunc`.
...@@ -3007,9 +2907,7 @@ pub const Object = struct {...@@ -3007,9 +2907,7 @@ pub const Object = struct {
3007 Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod));2907 Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod));
3008 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);2908 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
3009 },2909 },
3010 .byref_mut => {2910 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
3011 try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder);
3012 },
3013 // No attributes needed for these.2911 // No attributes needed for these.
3014 .no_bits,2912 .no_bits,
3015 .abi_sized_int,2913 .abi_sized_int,
...@@ -3025,11 +2923,8 @@ pub const Object = struct {...@@ -3025,11 +2923,8 @@ pub const Object = struct {
3025 };2923 };
3026 }2924 }
30272925
3028 try o.builder.llvm.globals.append(o.gpa, llvm_fn);2926 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
3029 gop.value_ptr.* = try o.builder.addGlobal(fqn, global);2927 return function_index;
3030 try o.builder.functions.append(o.gpa, function);
3031 global.kind.function.setAttributes(try attributes.finish(&o.builder), &o.builder);
3032 return global.kind.function;
3033 }2928 }
30342929
3035 fn addCommonFnAttributes(2930 fn addCommonFnAttributes(
...@@ -3093,76 +2988,50 @@ pub const Object = struct {...@@ -3093,76 +2988,50 @@ pub const Object = struct {
3093 }2988 }
3094 }2989 }
30952990
3096 fn resolveGlobalDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Variable.Index {2991 fn resolveGlobalDecl(
2992 o: *Object,
2993 decl_index: Module.Decl.Index,
2994 ) Allocator.Error!Builder.Variable.Index {
3097 const gop = try o.decl_map.getOrPut(o.gpa, decl_index);2995 const gop = try o.decl_map.getOrPut(o.gpa, decl_index);
3098 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;2996 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;
3099 errdefer assert(o.decl_map.remove(decl_index));2997 errdefer assert(o.decl_map.remove(decl_index));
31002998
3101 const mod = o.module;2999 const mod = o.module;
3102 const decl = mod.declPtr(decl_index);3000 const decl = mod.declPtr(decl_index);
3103 const fqn = try o.builder.string(mod.intern_pool.stringToSlice(
3104 try decl.getFullyQualifiedName(mod),
3105 ));
3106
3107 const target = mod.getTarget();
3108
3109 var global = Builder.Global{
3110 .addr_space = toLlvmGlobalAddressSpace(decl.@"addrspace", target),
3111 .type = try o.lowerType(decl.ty),
3112 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
3113 };
3114 var variable = Builder.Variable{
3115 .global = @enumFromInt(o.builder.globals.count()),
3116 };
3117
3118 const is_extern = decl.isExtern(mod);3001 const is_extern = decl.isExtern(mod);
3119 const name = if (is_extern)3002
3120 try o.builder.string(mod.intern_pool.stringToSlice(decl.name))3003 const variable_index = try o.builder.addVariable(
3121 else3004 try o.builder.string(mod.intern_pool.stringToSlice(
3122 fqn;3005 if (is_extern) decl.name else try decl.getFullyQualifiedName(mod),
3123 const llvm_global = o.llvm_module.addGlobalInAddressSpace(3006 )),
3124 global.type.toLlvm(&o.builder),3007 try o.lowerType(decl.ty),
3125 fqn.slice(&o.builder).?,3008 toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()),
3126 @intFromEnum(global.addr_space),
3127 );3009 );
3010 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
31283011
3129 // This is needed for declarations created by `@extern`.3012 // This is needed for declarations created by `@extern`.
3130 if (is_extern) {3013 if (is_extern) {
3131 global.unnamed_addr = .default;3014 variable_index.setLinkage(.external, &o.builder);
3132 llvm_global.setUnnamedAddr(.False);3015 variable_index.setUnnamedAddr(.default, &o.builder);
3133 global.linkage = .external;
3134 llvm_global.setLinkage(.External);
3135 if (decl.val.getVariable(mod)) |decl_var| {3016 if (decl.val.getVariable(mod)) |decl_var| {
3136 const single_threaded = mod.comp.bin_file.options.single_threaded;3017 const single_threaded = mod.comp.bin_file.options.single_threaded;
3137 if (decl_var.is_threadlocal and !single_threaded) {3018 variable_index.setThreadLocal(
3138 variable.thread_local = .generaldynamic;3019 if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default,
3139 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);3020 &o.builder,
3140 } else {3021 );
3141 variable.thread_local = .default;3022 if (decl_var.is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder);
3142 llvm_global.setThreadLocalMode(.NotThreadLocal);
3143 }
3144 if (decl_var.is_weak_linkage) {
3145 global.linkage = .extern_weak;
3146 llvm_global.setLinkage(.ExternalWeak);
3147 }
3148 }3023 }
3149 } else {3024 } else {
3150 global.linkage = .internal;3025 variable_index.setLinkage(.internal, &o.builder);
3151 llvm_global.setLinkage(.Internal);3026 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
3152 global.unnamed_addr = .unnamed_addr;
3153 llvm_global.setUnnamedAddr(.True);
3154 }3027 }
31553028 return variable_index;
3156 try o.builder.llvm.globals.append(o.gpa, llvm_global);
3157 gop.value_ptr.* = try o.builder.addGlobal(name, global);
3158 try o.builder.variables.append(o.gpa, variable);
3159 return global.kind.variable;
3160 }3029 }
31613030
3162 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {3031 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
3163 const ty = try o.lowerTypeInner(t);3032 const ty = try o.lowerTypeInner(t);
3164 const mod = o.module;3033 const mod = o.module;
3165 if (std.debug.runtime_safety and false) check: {3034 if (std.debug.runtime_safety and o.builder.useLibLlvm() and false) check: {
3166 const llvm_ty = ty.toLlvm(&o.builder);3035 const llvm_ty = ty.toLlvm(&o.builder);
3167 if (t.zigTypeTag(mod) == .Opaque) break :check;3036 if (t.zigTypeTag(mod) == .Opaque) break :check;
3168 if (!t.hasRuntimeBits(mod)) break :check;3037 if (!t.hasRuntimeBits(mod)) break :check;
...@@ -4533,65 +4402,22 @@ pub const DeclGen = struct {...@@ -4533,65 +4402,22 @@ pub const DeclGen = struct {
4533 if (decl.val.getExternFunc(mod)) |extern_func| {4402 if (decl.val.getExternFunc(mod)) |extern_func| {
4534 _ = try o.resolveLlvmFunction(extern_func.decl);4403 _ = try o.resolveLlvmFunction(extern_func.decl);
4535 } else {4404 } else {
4536 const target = mod.getTarget();4405 const variable_index = try o.resolveGlobalDecl(decl_index);
4537 const variable = try o.resolveGlobalDecl(decl_index);4406 variable_index.setAlignment(
4538 const global = variable.ptrConst(&o.builder).global;4407 Builder.Alignment.fromByteUnits(decl.getAlignment(mod)),
4539 var llvm_global = global.toLlvm(&o.builder);4408 &o.builder,
4540 variable.ptr(&o.builder).alignment = Builder.Alignment.fromByteUnits(decl.getAlignment(mod));4409 );
4541 llvm_global.setAlignment(decl.getAlignment(mod));4410 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
4542 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| {4411 variable_index.setSection(try o.builder.string(section), &o.builder);
4543 variable.ptr(&o.builder).section = try o.builder.string(section);
4544 llvm_global.setSection(section);
4545 }
4546 assert(decl.has_tv);4412 assert(decl.has_tv);
4547 const init_val = if (decl.val.getVariable(mod)) |decl_var| decl_var.init else init_val: {4413 const init_val = if (decl.val.getVariable(mod)) |decl_var| decl_var.init else init_val: {
4548 variable.ptr(&o.builder).mutability = .constant;4414 variable_index.setMutability(.constant, &o.builder);
4549 llvm_global.setGlobalConstant(.True);
4550 break :init_val decl.val.toIntern();4415 break :init_val decl.val.toIntern();
4551 };4416 };
4552 if (init_val != .none) {4417 try variable_index.setInitializer(switch (init_val) {
4553 const llvm_init = try o.lowerValue(init_val);4418 .none => .no_init,
4554 const llvm_init_ty = llvm_init.typeOf(&o.builder);4419 else => try o.lowerValue(init_val),
4555 if (global.ptrConst(&o.builder).type == llvm_init_ty) {4420 }, &o.builder);
4556 llvm_global.setInitializer(llvm_init.toLlvm(&o.builder));
4557 } else {
4558 // LLVM does not allow us to change the type of globals. So we must
4559 // create a new global with the correct type, copy all its attributes,
4560 // and then update all references to point to the new global,
4561 // delete the original, and rename the new one to the old one's name.
4562 // This is necessary because LLVM does not support const bitcasting
4563 // a struct with padding bytes, which is needed to lower a const union value
4564 // to LLVM, when a field other than the most-aligned is active. Instead,
4565 // we must lower to an unnamed struct, and pointer cast at usage sites
4566 // of the global. Such an unnamed struct is the cause of the global type
4567 // mismatch, because we don't have the LLVM type until the *value* is created,
4568 // whereas the global needs to be created based on the type alone, because
4569 // lowering the value may reference the global as a pointer.
4570 // Related: https://github.com/ziglang/zig/issues/13265
4571 const llvm_global_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
4572 const new_global = o.llvm_module.addGlobalInAddressSpace(
4573 llvm_init_ty.toLlvm(&o.builder),
4574 "",
4575 @intFromEnum(llvm_global_addrspace),
4576 );
4577 new_global.setLinkage(llvm_global.getLinkage());
4578 new_global.setUnnamedAddr(llvm_global.getUnnamedAddress());
4579 new_global.setAlignment(llvm_global.getAlignment());
4580 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
4581 new_global.setSection(section);
4582 new_global.setInitializer(llvm_init.toLlvm(&o.builder));
4583 // TODO: How should this work then the address space of a global changed?
4584 llvm_global.replaceAllUsesWith(new_global);
4585 new_global.takeName(llvm_global);
4586 o.builder.llvm.globals.items[@intFromEnum(variable.ptrConst(&o.builder).global)] =
4587 new_global;
4588 llvm_global.deleteGlobal();
4589 llvm_global = new_global;
4590 variable.ptr(&o.builder).mutability = .global;
4591 global.ptr(&o.builder).type = llvm_init_ty;
4592 }
4593 variable.ptr(&o.builder).init = llvm_init;
4594 }
45954421
4596 if (o.di_builder) |dib| {4422 if (o.di_builder) |dib| {
4597 const di_file = try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope);4423 const di_file = try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
...@@ -4601,7 +4427,7 @@ pub const DeclGen = struct {...@@ -4601,7 +4427,7 @@ pub const DeclGen = struct {
4601 const di_global = dib.createGlobalVariableExpression(4427 const di_global = dib.createGlobalVariableExpression(
4602 di_file.toScope(),4428 di_file.toScope(),
4603 mod.intern_pool.stringToSlice(decl.name),4429 mod.intern_pool.stringToSlice(decl.name),
4604 llvm_global.getValueName(),4430 variable_index.name(&o.builder).slice(&o.builder).?,
4605 di_file,4431 di_file,
4606 line_number,4432 line_number,
4607 try o.lowerDebugType(decl.ty, .full),4433 try o.lowerDebugType(decl.ty, .full),
...@@ -4609,7 +4435,8 @@ pub const DeclGen = struct {...@@ -4609,7 +4435,8 @@ pub const DeclGen = struct {
4609 );4435 );
46104436
4611 try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode());4437 try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode());
4612 if (!is_internal_linkage or decl.isExtern(mod)) llvm_global.attachMetaData(di_global);4438 if (!is_internal_linkage or decl.isExtern(mod))
4439 variable_index.toLlvm(&o.builder).attachMetaData(di_global);
4613 }4440 }
4614 }4441 }
4615 }4442 }
...@@ -4621,7 +4448,6 @@ pub const FuncGen = struct {...@@ -4621,7 +4448,6 @@ pub const FuncGen = struct {
4621 air: Air,4448 air: Air,
4622 liveness: Liveness,4449 liveness: Liveness,
4623 wip: Builder.WipFunction,4450 wip: Builder.WipFunction,
4624 builder: *llvm.Builder,
4625 di_scope: ?*llvm.DIScope,4451 di_scope: ?*llvm.DIScope,
4626 di_file: ?*llvm.DIFile,4452 di_file: ?*llvm.DIFile,
4627 base_line: u32,4453 base_line: u32,
...@@ -4710,38 +4536,22 @@ pub const FuncGen = struct {...@@ -4710,38 +4536,22 @@ pub const FuncGen = struct {
4710 // We have an LLVM value but we need to create a global constant and4536 // We have an LLVM value but we need to create a global constant and
4711 // set the value as its initializer, and then return a pointer to the global.4537 // set the value as its initializer, and then return a pointer to the global.
4712 const target = mod.getTarget();4538 const target = mod.getTarget();
4713 const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target);4539 const variable_index = try o.builder.addVariable(
4714 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target);4540 .empty,
4715 const llvm_ty = llvm_val.typeOf(&o.builder);4541 llvm_val.typeOf(&o.builder),
4716 const llvm_alignment = tv.ty.abiAlignment(mod);4542 toLlvmGlobalAddressSpace(.generic, target),
4717 const llvm_global = o.llvm_module.addGlobalInAddressSpace(llvm_ty.toLlvm(&o.builder), "", @intFromEnum(llvm_actual_addrspace));4543 );
4718 llvm_global.setInitializer(llvm_val.toLlvm(&o.builder));4544 try variable_index.setInitializer(llvm_val, &o.builder);
4719 llvm_global.setLinkage(.Private);4545 variable_index.setLinkage(.private, &o.builder);
4720 llvm_global.setGlobalConstant(.True);4546 variable_index.setMutability(.constant, &o.builder);
4721 llvm_global.setUnnamedAddr(.True);4547 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4722 llvm_global.setAlignment(llvm_alignment);4548 variable_index.setAlignment(Builder.Alignment.fromByteUnits(
47234549 tv.ty.abiAlignment(mod),
4724 var global = Builder.Global{4550 ), &o.builder);
4725 .linkage = .private,
4726 .unnamed_addr = .unnamed_addr,
4727 .addr_space = llvm_actual_addrspace,
4728 .type = llvm_ty,
4729 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
4730 };
4731 var variable = Builder.Variable{
4732 .global = @enumFromInt(o.builder.globals.count()),
4733 .mutability = .constant,
4734 .init = llvm_val,
4735 .alignment = Builder.Alignment.fromByteUnits(llvm_alignment),
4736 };
4737 try o.builder.llvm.globals.append(o.gpa, llvm_global);
4738 const global_index = try o.builder.addGlobal(.empty, global);
4739 try o.builder.variables.append(o.gpa, variable);
4740
4741 return o.builder.convConst(4551 return o.builder.convConst(
4742 .unneeded,4552 .unneeded,
4743 global_index.toConst(),4553 variable_index.toConst(&o.builder),
4744 try o.builder.ptrType(llvm_wanted_addrspace),4554 try o.builder.ptrType(toLlvmAddressSpace(.generic, target)),
4745 );4555 );
4746 }4556 }
47474557
...@@ -4768,18 +4578,18 @@ pub const FuncGen = struct {...@@ -4768,18 +4578,18 @@ pub const FuncGen = struct {
47684578
4769 const val: Builder.Value = switch (air_tags[inst]) {4579 const val: Builder.Value = switch (air_tags[inst]) {
4770 // zig fmt: off4580 // zig fmt: off
4771 .add => try self.airAdd(inst, false),4581 .add => try self.airAdd(inst, .normal),
4772 .add_optimized => try self.airAdd(inst, true),4582 .add_optimized => try self.airAdd(inst, .fast),
4773 .add_wrap => try self.airAddWrap(inst),4583 .add_wrap => try self.airAddWrap(inst),
4774 .add_sat => try self.airAddSat(inst),4584 .add_sat => try self.airAddSat(inst),
47754585
4776 .sub => try self.airSub(inst, false),4586 .sub => try self.airSub(inst, .normal),
4777 .sub_optimized => try self.airSub(inst, true),4587 .sub_optimized => try self.airSub(inst, .fast),
4778 .sub_wrap => try self.airSubWrap(inst),4588 .sub_wrap => try self.airSubWrap(inst),
4779 .sub_sat => try self.airSubSat(inst),4589 .sub_sat => try self.airSubSat(inst),
47804590
4781 .mul => try self.airMul(inst, false),4591 .mul => try self.airMul(inst, .normal),
4782 .mul_optimized => try self.airMul(inst, true),4592 .mul_optimized => try self.airMul(inst, .fast),
4783 .mul_wrap => try self.airMulWrap(inst),4593 .mul_wrap => try self.airMulWrap(inst),
4784 .mul_sat => try self.airMulSat(inst),4594 .mul_sat => try self.airMulSat(inst),
47854595
...@@ -4787,12 +4597,12 @@ pub const FuncGen = struct {...@@ -4787,12 +4597,12 @@ pub const FuncGen = struct {
4787 .sub_safe => try self.airSafeArithmetic(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),4597 .sub_safe => try self.airSafeArithmetic(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
4788 .mul_safe => try self.airSafeArithmetic(inst, .@"smul.with.overflow", .@"umul.with.overflow"),4598 .mul_safe => try self.airSafeArithmetic(inst, .@"smul.with.overflow", .@"umul.with.overflow"),
47894599
4790 .div_float => try self.airDivFloat(inst, false),4600 .div_float => try self.airDivFloat(inst, .normal),
4791 .div_trunc => try self.airDivTrunc(inst, false),4601 .div_trunc => try self.airDivTrunc(inst, .normal),
4792 .div_floor => try self.airDivFloor(inst, false),4602 .div_floor => try self.airDivFloor(inst, .normal),
4793 .div_exact => try self.airDivExact(inst, false),4603 .div_exact => try self.airDivExact(inst, .normal),
4794 .rem => try self.airRem(inst, false),4604 .rem => try self.airRem(inst, .normal),
4795 .mod => try self.airMod(inst, false),4605 .mod => try self.airMod(inst, .normal),
4796 .ptr_add => try self.airPtrAdd(inst),4606 .ptr_add => try self.airPtrAdd(inst),
4797 .ptr_sub => try self.airPtrSub(inst),4607 .ptr_sub => try self.airPtrSub(inst),
4798 .shl => try self.airShl(inst),4608 .shl => try self.airShl(inst),
...@@ -4803,12 +4613,12 @@ pub const FuncGen = struct {...@@ -4803,12 +4613,12 @@ pub const FuncGen = struct {
4803 .slice => try self.airSlice(inst),4613 .slice => try self.airSlice(inst),
4804 .mul_add => try self.airMulAdd(inst),4614 .mul_add => try self.airMulAdd(inst),
48054615
4806 .div_float_optimized => try self.airDivFloat(inst, true),4616 .div_float_optimized => try self.airDivFloat(inst, .fast),
4807 .div_trunc_optimized => try self.airDivTrunc(inst, true),4617 .div_trunc_optimized => try self.airDivTrunc(inst, .fast),
4808 .div_floor_optimized => try self.airDivFloor(inst, true),4618 .div_floor_optimized => try self.airDivFloor(inst, .fast),
4809 .div_exact_optimized => try self.airDivExact(inst, true),4619 .div_exact_optimized => try self.airDivExact(inst, .fast),
4810 .rem_optimized => try self.airRem(inst, true),4620 .rem_optimized => try self.airRem(inst, .fast),
4811 .mod_optimized => try self.airMod(inst, true),4621 .mod_optimized => try self.airMod(inst, .fast),
48124622
4813 .add_with_overflow => try self.airOverflow(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"),4623 .add_with_overflow => try self.airOverflow(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"),
4814 .sub_with_overflow => try self.airOverflow(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),4624 .sub_with_overflow => try self.airOverflow(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
...@@ -4836,25 +4646,25 @@ pub const FuncGen = struct {...@@ -4836,25 +4646,25 @@ pub const FuncGen = struct {
4836 .round => try self.airUnaryOp(inst, .round),4646 .round => try self.airUnaryOp(inst, .round),
4837 .trunc_float => try self.airUnaryOp(inst, .trunc),4647 .trunc_float => try self.airUnaryOp(inst, .trunc),
48384648
4839 .neg => try self.airNeg(inst, false),4649 .neg => try self.airNeg(inst, .normal),
4840 .neg_optimized => try self.airNeg(inst, true),4650 .neg_optimized => try self.airNeg(inst, .fast),
48414651
4842 .cmp_eq => try self.airCmp(inst, .eq, false),4652 .cmp_eq => try self.airCmp(inst, .eq, .normal),
4843 .cmp_gt => try self.airCmp(inst, .gt, false),4653 .cmp_gt => try self.airCmp(inst, .gt, .normal),
4844 .cmp_gte => try self.airCmp(inst, .gte, false),4654 .cmp_gte => try self.airCmp(inst, .gte, .normal),
4845 .cmp_lt => try self.airCmp(inst, .lt, false),4655 .cmp_lt => try self.airCmp(inst, .lt, .normal),
4846 .cmp_lte => try self.airCmp(inst, .lte, false),4656 .cmp_lte => try self.airCmp(inst, .lte, .normal),
4847 .cmp_neq => try self.airCmp(inst, .neq, false),4657 .cmp_neq => try self.airCmp(inst, .neq, .normal),
48484658
4849 .cmp_eq_optimized => try self.airCmp(inst, .eq, true),4659 .cmp_eq_optimized => try self.airCmp(inst, .eq, .fast),
4850 .cmp_gt_optimized => try self.airCmp(inst, .gt, true),4660 .cmp_gt_optimized => try self.airCmp(inst, .gt, .fast),
4851 .cmp_gte_optimized => try self.airCmp(inst, .gte, true),4661 .cmp_gte_optimized => try self.airCmp(inst, .gte, .fast),
4852 .cmp_lt_optimized => try self.airCmp(inst, .lt, true),4662 .cmp_lt_optimized => try self.airCmp(inst, .lt, .fast),
4853 .cmp_lte_optimized => try self.airCmp(inst, .lte, true),4663 .cmp_lte_optimized => try self.airCmp(inst, .lte, .fast),
4854 .cmp_neq_optimized => try self.airCmp(inst, .neq, true),4664 .cmp_neq_optimized => try self.airCmp(inst, .neq, .fast),
48554665
4856 .cmp_vector => try self.airCmpVector(inst, false),4666 .cmp_vector => try self.airCmpVector(inst, .normal),
4857 .cmp_vector_optimized => try self.airCmpVector(inst, true),4667 .cmp_vector_optimized => try self.airCmpVector(inst, .fast),
4858 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),4668 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
48594669
4860 .is_non_null => try self.airIsNonNull(inst, false, .ne),4670 .is_non_null => try self.airIsNonNull(inst, false, .ne),
...@@ -4906,8 +4716,8 @@ pub const FuncGen = struct {...@@ -4906,8 +4716,8 @@ pub const FuncGen = struct {
4906 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),4716 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
4907 .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),4717 .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),
49084718
4909 .int_from_float => try self.airIntFromFloat(inst, false),4719 .int_from_float => try self.airIntFromFloat(inst, .normal),
4910 .int_from_float_optimized => try self.airIntFromFloat(inst, true),4720 .int_from_float_optimized => try self.airIntFromFloat(inst, .fast),
49114721
4912 .array_to_slice => try self.airArrayToSlice(inst),4722 .array_to_slice => try self.airArrayToSlice(inst),
4913 .float_from_int => try self.airFloatFromInt(inst),4723 .float_from_int => try self.airFloatFromInt(inst),
...@@ -4939,8 +4749,8 @@ pub const FuncGen = struct {...@@ -4939,8 +4749,8 @@ pub const FuncGen = struct {
4939 .is_named_enum_value => try self.airIsNamedEnumValue(inst),4749 .is_named_enum_value => try self.airIsNamedEnumValue(inst),
4940 .error_set_has_value => try self.airErrorSetHasValue(inst),4750 .error_set_has_value => try self.airErrorSetHasValue(inst),
49414751
4942 .reduce => try self.airReduce(inst, false),4752 .reduce => try self.airReduce(inst, .normal),
4943 .reduce_optimized => try self.airReduce(inst, true),4753 .reduce_optimized => try self.airReduce(inst, .fast),
49444754
4945 .atomic_store_unordered => try self.airAtomicStore(inst, .unordered),4755 .atomic_store_unordered => try self.airAtomicStore(inst, .unordered),
4946 .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),4756 .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),
...@@ -5466,7 +5276,7 @@ pub const FuncGen = struct {...@@ -5466,7 +5276,7 @@ pub const FuncGen = struct {
5466 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));5276 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
5467 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);
54685278
5469 _ = try self.wip.callIntrinsic(.none, .va_copy, &.{}, &.{ dest_list, src_list }, "");5279 _ = try self.wip.callIntrinsic(.normal, .none, .va_copy, &.{}, &.{ dest_list, src_list }, "");
5470 return if (isByRef(va_list_ty, mod))5280 return if (isByRef(va_list_ty, mod))
5471 dest_list5281 dest_list
5472 else5282 else
...@@ -5477,7 +5287,7 @@ pub const FuncGen = struct {...@@ -5477,7 +5287,7 @@ pub const FuncGen = struct {
5477 const un_op = self.air.instructions.items(.data)[inst].un_op;5287 const un_op = self.air.instructions.items(.data)[inst].un_op;
5478 const src_list = try self.resolveInst(un_op);5288 const src_list = try self.resolveInst(un_op);
54795289
5480 _ = try self.wip.callIntrinsic(.none, .va_end, &.{}, &.{src_list}, "");5290 _ = try self.wip.callIntrinsic(.normal, .none, .va_end, &.{}, &.{src_list}, "");
5481 return .none;5291 return .none;
5482 }5292 }
54835293
...@@ -5490,27 +5300,28 @@ pub const FuncGen = struct {...@@ -5490,27 +5300,28 @@ pub const FuncGen = struct {
5490 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));5300 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
5491 const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);5301 const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
54925302
5493 _ = try self.wip.callIntrinsic(.none, .va_start, &.{}, &.{dest_list}, "");5303 _ = try self.wip.callIntrinsic(.normal, .none, .va_start, &.{}, &.{dest_list}, "");
5494 return if (isByRef(va_list_ty, mod))5304 return if (isByRef(va_list_ty, mod))
5495 dest_list5305 dest_list
5496 else5306 else
5497 try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, "");5307 try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, "");
5498 }5308 }
54995309
5500 fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !Builder.Value {5310 fn airCmp(
5501 self.builder.setFastMath(want_fast_math);5311 self: *FuncGen,
55025312 inst: Air.Inst.Index,
5313 op: math.CompareOperator,
5314 fast: Builder.FastMathKind,
5315 ) !Builder.Value {
5503 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5316 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5504 const lhs = try self.resolveInst(bin_op.lhs);5317 const lhs = try self.resolveInst(bin_op.lhs);
5505 const rhs = try self.resolveInst(bin_op.rhs);5318 const rhs = try self.resolveInst(bin_op.rhs);
5506 const operand_ty = self.typeOf(bin_op.lhs);5319 const operand_ty = self.typeOf(bin_op.lhs);
55075320
5508 return self.cmp(lhs, rhs, operand_ty, op);5321 return self.cmp(fast, op, operand_ty, lhs, rhs);
5509 }5322 }
55105323
5511 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 {
5512 self.builder.setFastMath(want_fast_math);
5513
5514 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5325 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5515 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;5326 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
55165327
...@@ -5519,7 +5330,7 @@ pub const FuncGen = struct {...@@ -5519,7 +5330,7 @@ pub const FuncGen = struct {
5519 const vec_ty = self.typeOf(extra.lhs);5330 const vec_ty = self.typeOf(extra.lhs);
5520 const cmp_op = extra.compareOperator();5331 const cmp_op = extra.compareOperator();
55215332
5522 return self.cmp(lhs, rhs, vec_ty, cmp_op);5333 return self.cmp(fast, cmp_op, vec_ty, lhs, rhs);
5523 }5334 }
55245335
5525 fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {5336 fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -5540,10 +5351,11 @@ pub const FuncGen = struct {...@@ -5540,10 +5351,11 @@ pub const FuncGen = struct {
55405351
5541 fn cmp(5352 fn cmp(
5542 self: *FuncGen,5353 self: *FuncGen,
5354 fast: Builder.FastMathKind,
5355 op: math.CompareOperator,
5356 operand_ty: Type,
5543 lhs: Builder.Value,5357 lhs: Builder.Value,
5544 rhs: Builder.Value,5358 rhs: Builder.Value,
5545 operand_ty: Type,
5546 op: math.CompareOperator,
5547 ) Allocator.Error!Builder.Value {5359 ) Allocator.Error!Builder.Value {
5548 const o = self.dg.object;5360 const o = self.dg.object;
5549 const mod = o.module;5361 const mod = o.module;
...@@ -5595,7 +5407,7 @@ pub const FuncGen = struct {...@@ -5595,7 +5407,7 @@ pub const FuncGen = struct {
5595 self.wip.cursor = .{ .block = both_pl_block };5407 self.wip.cursor = .{ .block = both_pl_block };
5596 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);
5597 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);
5598 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);
5599 _ = try self.wip.br(end_block);5411 _ = try self.wip.br(end_block);
5600 const both_pl_block_end = self.wip.cursor.block;5412 const both_pl_block_end = self.wip.cursor.block;
56015413
...@@ -5624,7 +5436,7 @@ pub const FuncGen = struct {...@@ -5624,7 +5436,7 @@ pub const FuncGen = struct {
5624 );5436 );
5625 return phi.toValue();5437 return phi.toValue();
5626 },5438 },
5627 .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }),5439 .Float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }),
5628 else => unreachable,5440 else => unreachable,
5629 };5441 };
5630 const is_signed = int_ty.isSignedInt(mod);5442 const is_signed = int_ty.isSignedInt(mod);
...@@ -5995,8 +5807,12 @@ pub const FuncGen = struct {...@@ -5995,8 +5807,12 @@ pub const FuncGen = struct {
5995 );5807 );
5996 }5808 }
59975809
5998 fn airIntFromFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {5810 fn airIntFromFloat(
5999 self.builder.setFastMath(want_fast_math);5811 self: *FuncGen,
5812 inst: Air.Inst.Index,
5813 fast: Builder.FastMathKind,
5814 ) !Builder.Value {
5815 _ = fast;
60005816
6001 const o = self.dg.object;5817 const o = self.dg.object;
6002 const mod = o.module;5818 const mod = o.module;
...@@ -6414,6 +6230,8 @@ pub const FuncGen = struct {...@@ -6414,6 +6230,8 @@ pub const FuncGen = struct {
6414 }6230 }
64156231
6416 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
6417 const di_scope = self.di_scope orelse return .none;6235 const di_scope = self.di_scope orelse return .none;
6418 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;6236 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
6419 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);
...@@ -6422,12 +6240,19 @@ pub const FuncGen = struct {...@@ -6422,12 +6240,19 @@ pub const FuncGen = struct {
6422 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc6240 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc
6423 else6241 else
6424 null;6242 null;
6425 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 );
6426 return .none;6249 return .none;
6427 }6250 }
64286251
6429 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6252 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6430 const o = self.dg.object;6253 const o = self.dg.object;
6254 if (!o.builder.useLibLlvm()) return .none;
6255
6431 const dib = o.di_builder orelse return .none;6256 const dib = o.di_builder orelse return .none;
6432 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;6257 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
64336258
...@@ -6438,7 +6263,7 @@ pub const FuncGen = struct {...@@ -6438,7 +6263,7 @@ pub const FuncGen = struct {
6438 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);
6439 self.di_file = di_file;6264 self.di_file = di_file;
6440 const line_number = decl.src_line + 1;6265 const line_number = decl.src_line + 1;
6441 const cur_debug_location = self.builder.getCurrentDebugLocation2();6266 const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2();
64426267
6443 try self.dbg_inlined.append(self.gpa, .{6268 try self.dbg_inlined.append(self.gpa, .{
6444 .loc = @ptrCast(cur_debug_location),6269 .loc = @ptrCast(cur_debug_location),
...@@ -6486,6 +6311,8 @@ pub const FuncGen = struct {...@@ -6486,6 +6311,8 @@ pub const FuncGen = struct {
64866311
6487 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6312 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6488 const o = self.dg.object;6313 const o = self.dg.object;
6314 if (!o.builder.useLibLlvm()) return .none;
6315
6489 if (o.di_builder == null) return .none;6316 if (o.di_builder == null) return .none;
6490 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;6317 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
64916318
...@@ -6501,6 +6328,8 @@ pub const FuncGen = struct {...@@ -6501,6 +6328,8 @@ pub const FuncGen = struct {
65016328
6502 fn airDbgBlockBegin(self: *FuncGen) !Builder.Value {6329 fn airDbgBlockBegin(self: *FuncGen) !Builder.Value {
6503 const o = self.dg.object;6330 const o = self.dg.object;
6331 if (!o.builder.useLibLlvm()) return .none;
6332
6504 const dib = o.di_builder orelse return .none;6333 const dib = o.di_builder orelse return .none;
6505 const old_scope = self.di_scope.?;6334 const old_scope = self.di_scope.?;
6506 try self.dbg_block_stack.append(self.gpa, old_scope);6335 try self.dbg_block_stack.append(self.gpa, old_scope);
...@@ -6511,6 +6340,8 @@ pub const FuncGen = struct {...@@ -6511,6 +6340,8 @@ pub const FuncGen = struct {
65116340
6512 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {6341 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {
6513 const o = self.dg.object;6342 const o = self.dg.object;
6343 if (!o.builder.useLibLlvm()) return .none;
6344
6514 if (o.di_builder == null) return .none;6345 if (o.di_builder == null) return .none;
6515 self.di_scope = self.dbg_block_stack.pop();6346 self.di_scope = self.dbg_block_stack.pop();
6516 return .none;6347 return .none;
...@@ -6518,6 +6349,8 @@ pub const FuncGen = struct {...@@ -6518,6 +6349,8 @@ pub const FuncGen = struct {
65186349
6519 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6350 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6520 const o = self.dg.object;6351 const o = self.dg.object;
6352 if (!o.builder.useLibLlvm()) return .none;
6353
6521 const mod = o.module;6354 const mod = o.module;
6522 const dib = o.di_builder orelse return .none;6355 const dib = o.di_builder orelse return .none;
6523 const pl_op = self.air.instructions.items(.data)[inst].pl_op;6356 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
...@@ -6546,6 +6379,8 @@ pub const FuncGen = struct {...@@ -6546,6 +6379,8 @@ pub const FuncGen = struct {
65466379
6547 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6380 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6548 const o = self.dg.object;6381 const o = self.dg.object;
6382 if (!o.builder.useLibLlvm()) return .none;
6383
6549 const dib = o.di_builder orelse return .none;6384 const dib = o.di_builder orelse return .none;
6550 const pl_op = self.air.instructions.items(.data)[inst].pl_op;6385 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
6551 const operand = try self.resolveInst(pl_op.operand);6386 const operand = try self.resolveInst(pl_op.operand);
...@@ -7346,7 +7181,7 @@ pub const FuncGen = struct {...@@ -7346,7 +7181,7 @@ pub const FuncGen = struct {
7346 const o = self.dg.object;7181 const o = self.dg.object;
7347 const pl_op = self.air.instructions.items(.data)[inst].pl_op;7182 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
7348 const index = pl_op.payload;7183 const index = pl_op.payload;
7349 return self.wip.callIntrinsic(.none, .@"wasm.memory.size", &.{.i32}, &.{7184 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{.i32}, &.{
7350 try o.builder.intValue(.i32, index),7185 try o.builder.intValue(.i32, index),
7351 }, "");7186 }, "");
7352 }7187 }
...@@ -7355,7 +7190,7 @@ pub const FuncGen = struct {...@@ -7355,7 +7190,7 @@ pub const FuncGen = struct {
7355 const o = self.dg.object;7190 const o = self.dg.object;
7356 const pl_op = self.air.instructions.items(.data)[inst].pl_op;7191 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
7357 const index = pl_op.payload;7192 const index = pl_op.payload;
7358 return self.wip.callIntrinsic(.none, .@"wasm.memory.grow", &.{.i32}, &.{7193 return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{.i32}, &.{
7359 try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),7194 try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),
7360 }, "");7195 }, "");
7361 }7196 }
...@@ -7391,8 +7226,9 @@ pub const FuncGen = struct {...@@ -7391,8 +7226,9 @@ pub const FuncGen = struct {
7391 const inst_ty = self.typeOfIndex(inst);7226 const inst_ty = self.typeOfIndex(inst);
7392 const scalar_ty = inst_ty.scalarType(mod);7227 const scalar_ty = inst_ty.scalarType(mod);
73937228
7394 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, inst_ty, 2, .{ lhs, rhs });7229 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, .normal, inst_ty, 2, .{ lhs, rhs });
7395 return self.wip.callIntrinsic(7230 return self.wip.callIntrinsic(
7231 .normal,
7396 .none,7232 .none,
7397 if (scalar_ty.isSignedInt(mod)) .smin else .umin,7233 if (scalar_ty.isSignedInt(mod)) .smin else .umin,
7398 &.{try o.lowerType(inst_ty)},7234 &.{try o.lowerType(inst_ty)},
...@@ -7410,8 +7246,9 @@ pub const FuncGen = struct {...@@ -7410,8 +7246,9 @@ pub const FuncGen = struct {
7410 const inst_ty = self.typeOfIndex(inst);7246 const inst_ty = self.typeOfIndex(inst);
7411 const scalar_ty = inst_ty.scalarType(mod);7247 const scalar_ty = inst_ty.scalarType(mod);
74127248
7413 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, inst_ty, 2, .{ lhs, rhs });7249 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, .normal, inst_ty, 2, .{ lhs, rhs });
7414 return self.wip.callIntrinsic(7250 return self.wip.callIntrinsic(
7251 .normal,
7415 .none,7252 .none,
7416 if (scalar_ty.isSignedInt(mod)) .smax else .umax,7253 if (scalar_ty.isSignedInt(mod)) .smax else .umax,
7417 &.{try o.lowerType(inst_ty)},7254 &.{try o.lowerType(inst_ty)},
...@@ -7430,9 +7267,7 @@ pub const FuncGen = struct {...@@ -7430,9 +7267,7 @@ pub const FuncGen = struct {
7430 return self.wip.buildAggregate(try o.lowerType(inst_ty), &.{ ptr, len }, "");7267 return self.wip.buildAggregate(try o.lowerType(inst_ty), &.{ ptr, len }, "");
7431 }7268 }
74327269
7433 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 {
7434 self.builder.setFastMath(want_fast_math);
7435
7436 const o = self.dg.object;7271 const o = self.dg.object;
7437 const mod = o.module;7272 const mod = o.module;
7438 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7273 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7441,7 +7276,7 @@ pub const FuncGen = struct {...@@ -7441,7 +7276,7 @@ pub const FuncGen = struct {
7441 const inst_ty = self.typeOfIndex(inst);7276 const inst_ty = self.typeOfIndex(inst);
7442 const scalar_ty = inst_ty.scalarType(mod);7277 const scalar_ty = inst_ty.scalarType(mod);
74437278
7444 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 });
7445 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, "");
7446 }7281 }
74477282
...@@ -7463,12 +7298,13 @@ pub const FuncGen = struct {...@@ -7463,12 +7298,13 @@ pub const FuncGen = struct {
7463 const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;7298 const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
7464 const llvm_inst_ty = try o.lowerType(inst_ty);7299 const llvm_inst_ty = try o.lowerType(inst_ty);
7465 const results =7300 const results =
7466 try fg.wip.callIntrinsic(.none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, "");7301 try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, "");
74677302
7468 const overflow_bits = try fg.wip.extractValue(results, &.{1}, "");7303 const overflow_bits = try fg.wip.extractValue(results, &.{1}, "");
7469 const overflow_bits_ty = overflow_bits.typeOfWip(&fg.wip);7304 const overflow_bits_ty = overflow_bits.typeOfWip(&fg.wip);
7470 const overflow_bit = if (overflow_bits_ty.isVector(&o.builder))7305 const overflow_bit = if (overflow_bits_ty.isVector(&o.builder))
7471 try fg.wip.callIntrinsic(7306 try fg.wip.callIntrinsic(
7307 .normal,
7472 .none,7308 .none,
7473 .@"vector.reduce.or",7309 .@"vector.reduce.or",
7474 &.{overflow_bits_ty},7310 &.{overflow_bits_ty},
...@@ -7508,6 +7344,7 @@ pub const FuncGen = struct {...@@ -7508,6 +7344,7 @@ pub const FuncGen = struct {
75087344
7509 if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});7345 if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});
7510 return self.wip.callIntrinsic(7346 return self.wip.callIntrinsic(
7347 .normal,
7511 .none,7348 .none,
7512 if (scalar_ty.isSignedInt(mod)) .@"sadd.sat" else .@"uadd.sat",7349 if (scalar_ty.isSignedInt(mod)) .@"sadd.sat" else .@"uadd.sat",
7513 &.{try o.lowerType(inst_ty)},7350 &.{try o.lowerType(inst_ty)},
...@@ -7516,9 +7353,7 @@ pub const FuncGen = struct {...@@ -7516,9 +7353,7 @@ pub const FuncGen = struct {
7516 );7353 );
7517 }7354 }
75187355
7519 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 {
7520 self.builder.setFastMath(want_fast_math);
7521
7522 const o = self.dg.object;7357 const o = self.dg.object;
7523 const mod = o.module;7358 const mod = o.module;
7524 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7359 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7527,7 +7362,7 @@ pub const FuncGen = struct {...@@ -7527,7 +7362,7 @@ pub const FuncGen = struct {
7527 const inst_ty = self.typeOfIndex(inst);7362 const inst_ty = self.typeOfIndex(inst);
7528 const scalar_ty = inst_ty.scalarType(mod);7363 const scalar_ty = inst_ty.scalarType(mod);
75297364
7530 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 });
7531 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, "");
7532 }7367 }
75337368
...@@ -7550,6 +7385,7 @@ pub const FuncGen = struct {...@@ -7550,6 +7385,7 @@ pub const FuncGen = struct {
75507385
7551 if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});7386 if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});
7552 return self.wip.callIntrinsic(7387 return self.wip.callIntrinsic(
7388 .normal,
7553 .none,7389 .none,
7554 if (scalar_ty.isSignedInt(mod)) .@"ssub.sat" else .@"usub.sat",7390 if (scalar_ty.isSignedInt(mod)) .@"ssub.sat" else .@"usub.sat",
7555 &.{try o.lowerType(inst_ty)},7391 &.{try o.lowerType(inst_ty)},
...@@ -7558,9 +7394,7 @@ pub const FuncGen = struct {...@@ -7558,9 +7394,7 @@ pub const FuncGen = struct {
7558 );7394 );
7559 }7395 }
75607396
7561 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 {
7562 self.builder.setFastMath(want_fast_math);
7563
7564 const o = self.dg.object;7398 const o = self.dg.object;
7565 const mod = o.module;7399 const mod = o.module;
7566 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7400 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7569,7 +7403,7 @@ pub const FuncGen = struct {...@@ -7569,7 +7403,7 @@ pub const FuncGen = struct {
7569 const inst_ty = self.typeOfIndex(inst);7403 const inst_ty = self.typeOfIndex(inst);
7570 const scalar_ty = inst_ty.scalarType(mod);7404 const scalar_ty = inst_ty.scalarType(mod);
75717405
7572 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 });
7573 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, "");
7574 }7408 }
75757409
...@@ -7592,6 +7426,7 @@ pub const FuncGen = struct {...@@ -7592,6 +7426,7 @@ pub const FuncGen = struct {
75927426
7593 if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});7427 if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});
7594 return self.wip.callIntrinsic(7428 return self.wip.callIntrinsic(
7429 .normal,
7595 .none,7430 .none,
7596 if (scalar_ty.isSignedInt(mod)) .@"smul.fix.sat" else .@"umul.fix.sat",7431 if (scalar_ty.isSignedInt(mod)) .@"smul.fix.sat" else .@"umul.fix.sat",
7597 &.{try o.lowerType(inst_ty)},7432 &.{try o.lowerType(inst_ty)},
...@@ -7600,20 +7435,16 @@ pub const FuncGen = struct {...@@ -7600,20 +7435,16 @@ pub const FuncGen = struct {
7600 );7435 );
7601 }7436 }
76027437
7603 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 {
7604 self.builder.setFastMath(want_fast_math);
7605
7606 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7439 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7607 const lhs = try self.resolveInst(bin_op.lhs);7440 const lhs = try self.resolveInst(bin_op.lhs);
7608 const rhs = try self.resolveInst(bin_op.rhs);7441 const rhs = try self.resolveInst(bin_op.rhs);
7609 const inst_ty = self.typeOfIndex(inst);7442 const inst_ty = self.typeOfIndex(inst);
76107443
7611 return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7444 return self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7612 }7445 }
76137446
7614 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 {
7615 self.builder.setFastMath(want_fast_math);
7616
7617 const o = self.dg.object;7448 const o = self.dg.object;
7618 const mod = o.module;7449 const mod = o.module;
7619 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7450 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7623,15 +7454,13 @@ pub const FuncGen = struct {...@@ -7623,15 +7454,13 @@ pub const FuncGen = struct {
7623 const scalar_ty = inst_ty.scalarType(mod);7454 const scalar_ty = inst_ty.scalarType(mod);
76247455
7625 if (scalar_ty.isRuntimeFloat()) {7456 if (scalar_ty.isRuntimeFloat()) {
7626 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7457 const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7627 return self.buildFloatOp(.trunc, inst_ty, 1, .{result});7458 return self.buildFloatOp(.trunc, fast, inst_ty, 1, .{result});
7628 }7459 }
7629 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, "");
7630 }7461 }
76317462
7632 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 {
7633 self.builder.setFastMath(want_fast_math);
7634
7635 const o = self.dg.object;7464 const o = self.dg.object;
7636 const mod = o.module;7465 const mod = o.module;
7637 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7466 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7641,8 +7470,8 @@ pub const FuncGen = struct {...@@ -7641,8 +7470,8 @@ pub const FuncGen = struct {
7641 const scalar_ty = inst_ty.scalarType(mod);7470 const scalar_ty = inst_ty.scalarType(mod);
76427471
7643 if (scalar_ty.isRuntimeFloat()) {7472 if (scalar_ty.isRuntimeFloat()) {
7644 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });7473 const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7645 return self.buildFloatOp(.floor, inst_ty, 1, .{result});7474 return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result});
7646 }7475 }
7647 if (scalar_ty.isSignedInt(mod)) {7476 if (scalar_ty.isSignedInt(mod)) {
7648 const inst_llvm_ty = try o.lowerType(inst_ty);7477 const inst_llvm_ty = try o.lowerType(inst_ty);
...@@ -7657,15 +7486,13 @@ pub const FuncGen = struct {...@@ -7657,15 +7486,13 @@ pub const FuncGen = struct {
7657 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, "");
7658 const zero = try o.builder.zeroInitValue(inst_llvm_ty);7487 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
7659 const rem_nonzero = try self.wip.icmp(.ne, rem, zero, "");7488 const rem_nonzero = try self.wip.icmp(.ne, rem, zero, "");
7660 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, "");
7661 return self.wip.bin(.@"add nsw", div, correction, "");7490 return self.wip.bin(.@"add nsw", div, correction, "");
7662 }7491 }
7663 return self.wip.bin(.udiv, lhs, rhs, "");7492 return self.wip.bin(.udiv, lhs, rhs, "");
7664 }7493 }
76657494
7666 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 {
7667 self.builder.setFastMath(want_fast_math);
7668
7669 const o = self.dg.object;7496 const o = self.dg.object;
7670 const mod = o.module;7497 const mod = o.module;
7671 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7498 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7674,16 +7501,16 @@ pub const FuncGen = struct {...@@ -7674,16 +7501,16 @@ pub const FuncGen = struct {
7674 const inst_ty = self.typeOfIndex(inst);7501 const inst_ty = self.typeOfIndex(inst);
7675 const scalar_ty = inst_ty.scalarType(mod);7502 const scalar_ty = inst_ty.scalarType(mod);
76767503
7677 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 });
7678 return self.wip.bin(if (scalar_ty.isSignedInt(mod))7505 return self.wip.bin(
7679 .@"sdiv exact"7506 if (scalar_ty.isSignedInt(mod)) .@"sdiv exact" else .@"udiv exact",
7680 else7507 lhs,
7681 .@"udiv exact", lhs, rhs, "");7508 rhs,
7509 "",
7510 );
7682 }7511 }
76837512
7684 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 {
7685 self.builder.setFastMath(want_fast_math);
7686
7687 const o = self.dg.object;7514 const o = self.dg.object;
7688 const mod = o.module;7515 const mod = o.module;
7689 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7516 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7692,16 +7519,15 @@ pub const FuncGen = struct {...@@ -7692,16 +7519,15 @@ pub const FuncGen = struct {
7692 const inst_ty = self.typeOfIndex(inst);7519 const inst_ty = self.typeOfIndex(inst);
7693 const scalar_ty = inst_ty.scalarType(mod);7520 const scalar_ty = inst_ty.scalarType(mod);
76947521
7695 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 });
7696 return self.wip.bin(if (scalar_ty.isSignedInt(mod))7524 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
7697 .srem7525 .srem
7698 else7526 else
7699 .urem, lhs, rhs, "");7527 .urem, lhs, rhs, "");
7700 }7528 }
77017529
7702 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 {
7703 self.builder.setFastMath(want_fast_math);
7704
7705 const o = self.dg.object;7531 const o = self.dg.object;
7706 const mod = o.module;7532 const mod = o.module;
7707 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7533 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7712,12 +7538,12 @@ pub const FuncGen = struct {...@@ -7712,12 +7538,12 @@ pub const FuncGen = struct {
7712 const scalar_ty = inst_ty.scalarType(mod);7538 const scalar_ty = inst_ty.scalarType(mod);
77137539
7714 if (scalar_ty.isRuntimeFloat()) {7540 if (scalar_ty.isRuntimeFloat()) {
7715 const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });7541 const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs });
7716 const b = try self.buildFloatOp(.add, inst_ty, 2, .{ a, rhs });7542 const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs });
7717 const c = try self.buildFloatOp(.fmod, inst_ty, 2, .{ b, rhs });7543 const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs });
7718 const zero = try o.builder.zeroInitValue(inst_llvm_ty);7544 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
7719 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero });7545 const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero });
7720 return self.wip.select(ltz, c, a, "");7546 return self.wip.select(fast, ltz, c, a, "");
7721 }7547 }
7722 if (scalar_ty.isSignedInt(mod)) {7548 if (scalar_ty.isSignedInt(mod)) {
7723 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(
...@@ -7731,7 +7557,7 @@ pub const FuncGen = struct {...@@ -7731,7 +7557,7 @@ pub const FuncGen = struct {
7731 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, "");
7732 const zero = try o.builder.zeroInitValue(inst_llvm_ty);7558 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
7733 const rem_nonzero = try self.wip.icmp(.ne, rem, zero, "");7559 const rem_nonzero = try self.wip.icmp(.ne, rem, zero, "");
7734 const correction = try self.wip.select(rem_nonzero, rhs_masked, zero, "");7560 const correction = try self.wip.select(.normal, rem_nonzero, rhs_masked, zero, "");
7735 return self.wip.bin(.@"add nsw", rem, correction, "");7561 return self.wip.bin(.@"add nsw", rem, correction, "");
7736 }7562 }
7737 return self.wip.bin(.urem, lhs, rhs, "");7563 return self.wip.bin(.urem, lhs, rhs, "");
...@@ -7804,7 +7630,7 @@ pub const FuncGen = struct {...@@ -7804,7 +7630,7 @@ pub const FuncGen = struct {
7804 const llvm_inst_ty = try o.lowerType(inst_ty);7630 const llvm_inst_ty = try o.lowerType(inst_ty);
7805 const llvm_lhs_ty = try o.lowerType(lhs_ty);7631 const llvm_lhs_ty = try o.lowerType(lhs_ty);
7806 const results =7632 const results =
7807 try self.wip.callIntrinsic(.none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, "");7633 try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, "");
78087634
7809 const result_val = try self.wip.extractValue(results, &.{0}, "");7635 const result_val = try self.wip.extractValue(results, &.{0}, "");
7810 const overflow_bit = try self.wip.extractValue(results, &.{1}, "");7636 const overflow_bit = try self.wip.extractValue(results, &.{1}, "");
...@@ -7879,13 +7705,18 @@ pub const FuncGen = struct {...@@ -7879,13 +7705,18 @@ pub const FuncGen = struct {
7879 .function => |function| function,7705 .function => |function| function,
7880 else => unreachable,7706 else => unreachable,
7881 };7707 };
7882 return o.builder.addFunction(try o.builder.fnType(return_type, param_types, .normal), fn_name);7708 return o.builder.addFunction(
7709 try o.builder.fnType(return_type, param_types, .normal),
7710 fn_name,
7711 toLlvmAddressSpace(.generic, o.module.getTarget()),
7712 );
7883 }7713 }
78847714
7885 /// Creates a floating point comparison by lowering to the appropriate7715 /// Creates a floating point comparison by lowering to the appropriate
7886 /// hardware instruction or softfloat routine for the target7716 /// hardware instruction or softfloat routine for the target
7887 fn buildFloatCmp(7717 fn buildFloatCmp(
7888 self: *FuncGen,7718 self: *FuncGen,
7719 fast: Builder.FastMathKind,
7889 pred: math.CompareOperator,7720 pred: math.CompareOperator,
7890 ty: Type,7721 ty: Type,
7891 params: [2]Builder.Value,7722 params: [2]Builder.Value,
...@@ -7905,7 +7736,7 @@ pub const FuncGen = struct {...@@ -7905,7 +7736,7 @@ pub const FuncGen = struct {
7905 .gt => .ogt,7736 .gt => .ogt,
7906 .gte => .oge,7737 .gte => .oge,
7907 };7738 };
7908 return self.wip.fcmp(cond, params[0], params[1], "");7739 return self.wip.fcmp(fast, cond, params[0], params[1], "");
7909 }7740 }
79107741
7911 const float_bits = scalar_ty.floatBits(target);7742 const float_bits = scalar_ty.floatBits(target);
...@@ -7996,6 +7827,7 @@ pub const FuncGen = struct {...@@ -7996,6 +7827,7 @@ pub const FuncGen = struct {
7996 fn buildFloatOp(7827 fn buildFloatOp(
7997 self: *FuncGen,7828 self: *FuncGen,
7998 comptime op: FloatOp,7829 comptime op: FloatOp,
7830 fast: Builder.FastMathKind,
7999 ty: Type,7831 ty: Type,
8000 comptime params_len: usize,7832 comptime params_len: usize,
8001 params: [params_len]Builder.Value,7833 params: [params_len]Builder.Value,
...@@ -8009,13 +7841,23 @@ pub const FuncGen = struct {...@@ -8009,13 +7841,23 @@ pub const FuncGen = struct {
8009 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {7841 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
8010 // Some operations are dedicated LLVM instructions, not available as intrinsics7842 // Some operations are dedicated LLVM instructions, not available as intrinsics
8011 .neg => return self.wip.un(.fneg, params[0], ""),7843 .neg => return self.wip.un(.fneg, params[0], ""),
8012 .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (op) {7844 .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) {
8013 .add => .fadd,7845 .normal => switch (op) {
8014 .sub => .fsub,7846 .add => .fadd,
8015 .mul => .fmul,7847 .sub => .fsub,
8016 .div => .fdiv,7848 .mul => .fmul,
8017 .fmod => .frem,7849 .div => .fdiv,
8018 else => unreachable,7850 .fmod => .frem,
7851 else => unreachable,
7852 },
7853 .fast => switch (op) {
7854 .add => .@"fadd fast",
7855 .sub => .@"fsub fast",
7856 .mul => .@"fmul fast",
7857 .div => .@"fdiv fast",
7858 .fmod => .@"frem fast",
7859 else => unreachable,
7860 },
8019 }, params[0], params[1], ""),7861 }, params[0], params[1], ""),
8020 .fmax,7862 .fmax,
8021 .fmin,7863 .fmin,
...@@ -8033,7 +7875,7 @@ pub const FuncGen = struct {...@@ -8033,7 +7875,7 @@ pub const FuncGen = struct {
8033 .sqrt,7875 .sqrt,
8034 .trunc,7876 .trunc,
8035 .fma,7877 .fma,
8036 => return self.wip.callIntrinsic(.none, switch (op) {7878 => return self.wip.callIntrinsic(fast, .none, switch (op) {
8037 .fmax => .maxnum,7879 .fmax => .maxnum,
8038 .fmin => .minnum,7880 .fmin => .minnum,
8039 .ceil => .ceil,7881 .ceil => .ceil,
...@@ -8108,7 +7950,7 @@ pub const FuncGen = struct {...@@ -8108,7 +7950,7 @@ pub const FuncGen = struct {
8108 }7950 }
81097951
8110 return self.wip.call(7952 return self.wip.call(
8111 .normal,7953 fast.toCallKind(),
8112 .ccc,7954 .ccc,
8113 .none,7955 .none,
8114 libc_fn.typeOf(&o.builder),7956 libc_fn.typeOf(&o.builder),
...@@ -8127,7 +7969,7 @@ pub const FuncGen = struct {...@@ -8127,7 +7969,7 @@ pub const FuncGen = struct {
8127 const addend = try self.resolveInst(pl_op.operand);7969 const addend = try self.resolveInst(pl_op.operand);
81287970
8129 const ty = self.typeOfIndex(inst);7971 const ty = self.typeOfIndex(inst);
8130 return self.buildFloatOp(.fma, ty, 3, .{ mulend1, mulend2, addend });7972 return self.buildFloatOp(.fma, .normal, ty, 3, .{ mulend1, mulend2, addend });
8131 }7973 }
81327974
8133 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {7975 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -8248,6 +8090,7 @@ pub const FuncGen = struct {...@@ -8248,6 +8090,7 @@ pub const FuncGen = struct {
8248 const llvm_lhs_ty = try o.lowerType(lhs_ty);8090 const llvm_lhs_ty = try o.lowerType(lhs_ty);
8249 const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder);8091 const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder);
8250 const result = try self.wip.callIntrinsic(8092 const result = try self.wip.callIntrinsic(
8093 .normal,
8251 .none,8094 .none,
8252 if (lhs_scalar_ty.isSignedInt(mod)) .@"sshl.sat" else .@"ushl.sat",8095 if (lhs_scalar_ty.isSignedInt(mod)) .@"sshl.sat" else .@"ushl.sat",
8253 &.{llvm_lhs_ty},8096 &.{llvm_lhs_ty},
...@@ -8269,7 +8112,7 @@ pub const FuncGen = struct {...@@ -8269,7 +8112,7 @@ pub const FuncGen = struct {
8269 try o.builder.intConst(llvm_lhs_scalar_ty, -1),8112 try o.builder.intConst(llvm_lhs_scalar_ty, -1),
8270 );8113 );
8271 const in_range = try self.wip.icmp(.ult, rhs, bits, "");8114 const in_range = try self.wip.icmp(.ult, rhs, bits, "");
8272 return self.wip.select(in_range, result, lhs_max, "");8115 return self.wip.select(.normal, in_range, result, lhs_max, "");
8273 }8116 }
82748117
8275 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value {8118 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value {
...@@ -8682,14 +8525,14 @@ pub const FuncGen = struct {...@@ -8682,14 +8525,14 @@ pub const FuncGen = struct {
86828525
8683 fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8526 fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
8684 _ = inst;8527 _ = inst;
8685 _ = try self.wip.callIntrinsic(.none, .trap, &.{}, &.{}, "");8528 _ = try self.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, "");
8686 _ = try self.wip.@"unreachable"();8529 _ = try self.wip.@"unreachable"();
8687 return .none;8530 return .none;
8688 }8531 }
86898532
8690 fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8533 fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
8691 _ = inst;8534 _ = inst;
8692 _ = try self.wip.callIntrinsic(.none, .debugtrap, &.{}, &.{}, "");8535 _ = try self.wip.callIntrinsic(.normal, .none, .debugtrap, &.{}, &.{}, "");
8693 return .none;8536 return .none;
8694 }8537 }
86958538
...@@ -8701,7 +8544,7 @@ pub const FuncGen = struct {...@@ -8701,7 +8544,7 @@ pub const FuncGen = struct {
8701 // https://github.com/ziglang/zig/issues/119468544 // https://github.com/ziglang/zig/issues/11946
8702 return o.builder.intValue(llvm_usize, 0);8545 return o.builder.intValue(llvm_usize, 0);
8703 }8546 }
8704 const result = try self.wip.callIntrinsic(.none, .returnaddress, &.{}, &.{8547 const result = try self.wip.callIntrinsic(.normal, .none, .returnaddress, &.{}, &.{
8705 try o.builder.intValue(.i32, 0),8548 try o.builder.intValue(.i32, 0),
8706 }, "");8549 }, "");
8707 return self.wip.cast(.ptrtoint, result, llvm_usize, "");8550 return self.wip.cast(.ptrtoint, result, llvm_usize, "");
...@@ -8710,7 +8553,7 @@ pub const FuncGen = struct {...@@ -8710,7 +8553,7 @@ pub const FuncGen = struct {
8710 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {8553 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
8711 _ = inst;8554 _ = inst;
8712 const o = self.dg.object;8555 const o = self.dg.object;
8713 const result = try self.wip.callIntrinsic(.none, .frameaddress, &.{.ptr}, &.{8556 const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{
8714 try o.builder.intValue(.i32, 0),8557 try o.builder.intValue(.i32, 0),
8715 }, "");8558 }, "");
8716 return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), "");8559 return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), "");
...@@ -8768,7 +8611,7 @@ pub const FuncGen = struct {...@@ -8768,7 +8611,7 @@ pub const FuncGen = struct {
87688611
8769 if (optional_ty.optionalReprIsPayload(mod)) {8612 if (optional_ty.optionalReprIsPayload(mod)) {
8770 const zero = try o.builder.zeroInitValue(payload.typeOfWip(&self.wip));8613 const zero = try o.builder.zeroInitValue(payload.typeOfWip(&self.wip));
8771 return self.wip.select(success_bit, zero, payload, "");8614 return self.wip.select(.normal, success_bit, zero, payload, "");
8772 }8615 }
87738616
8774 comptime assert(optional_layout_version == 3);8617 comptime assert(optional_layout_version == 3);
...@@ -9053,8 +8896,8 @@ pub const FuncGen = struct {...@@ -9053,8 +8896,8 @@ pub const FuncGen = struct {
9053 access_kind: Builder.MemoryAccessKind,8896 access_kind: Builder.MemoryAccessKind,
9054 ) !void {8897 ) !void {
9055 const o = self.dg.object;8898 const o = self.dg.object;
9056 const llvm_usize_ty = try o.lowerType(Type.usize);8899 const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0);
9057 const cond = try self.cmp(len, try o.builder.intValue(llvm_usize_ty, 0), Type.usize, .neq);8900 const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero);
9058 const memset_block = try self.wip.block(1, "MemsetTrapSkip");8901 const memset_block = try self.wip.block(1, "MemsetTrapSkip");
9059 const end_block = try self.wip.block(2, "MemsetTrapEnd");8902 const end_block = try self.wip.block(2, "MemsetTrapEnd");
9060 _ = try self.wip.brCond(cond, memset_block, end_block);8903 _ = try self.wip.brCond(cond, memset_block, end_block);
...@@ -9087,8 +8930,8 @@ pub const FuncGen = struct {...@@ -9087,8 +8930,8 @@ pub const FuncGen = struct {
9087 std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and8930 std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and
9088 dest_ptr_ty.isSlice(mod))8931 dest_ptr_ty.isSlice(mod))
9089 {8932 {
9090 const zero_usize = try o.builder.intValue(try o.lowerType(Type.usize), 0);8933 const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0);
9091 const cond = try self.cmp(len, zero_usize, Type.usize, .neq);8934 const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero);
9092 const memcpy_block = try self.wip.block(1, "MemcpyTrapSkip");8935 const memcpy_block = try self.wip.block(1, "MemcpyTrapSkip");
9093 const end_block = try self.wip.block(2, "MemcpyTrapEnd");8936 const end_block = try self.wip.block(2, "MemcpyTrapEnd");
9094 _ = try self.wip.brCond(cond, memcpy_block, end_block);8937 _ = try self.wip.brCond(cond, memcpy_block, end_block);
...@@ -9166,17 +9009,15 @@ pub const FuncGen = struct {...@@ -9166,17 +9009,15 @@ pub const FuncGen = struct {
9166 const operand = try self.resolveInst(un_op);9009 const operand = try self.resolveInst(un_op);
9167 const operand_ty = self.typeOf(un_op);9010 const operand_ty = self.typeOf(un_op);
91689011
9169 return self.buildFloatOp(op, operand_ty, 1, .{operand});9012 return self.buildFloatOp(op, .normal, operand_ty, 1, .{operand});
9170 }9013 }
91719014
9172 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {9015 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
9173 self.builder.setFastMath(want_fast_math);
9174
9175 const un_op = self.air.instructions.items(.data)[inst].un_op;9016 const un_op = self.air.instructions.items(.data)[inst].un_op;
9176 const operand = try self.resolveInst(un_op);9017 const operand = try self.resolveInst(un_op);
9177 const operand_ty = self.typeOf(un_op);9018 const operand_ty = self.typeOf(un_op);
91789019
9179 return self.buildFloatOp(.neg, operand_ty, 1, .{operand});9020 return self.buildFloatOp(.neg, fast, operand_ty, 1, .{operand});
9180 }9021 }
91819022
9182 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value {9023 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value {
...@@ -9187,6 +9028,7 @@ pub const FuncGen = struct {...@@ -9187,6 +9028,7 @@ pub const FuncGen = struct {
9187 const operand = try self.resolveInst(ty_op.operand);9028 const operand = try self.resolveInst(ty_op.operand);
91889029
9189 const result = try self.wip.callIntrinsic(9030 const result = try self.wip.callIntrinsic(
9031 .normal,
9190 .none,9032 .none,
9191 intrinsic,9033 intrinsic,
9192 &.{try o.lowerType(operand_ty)},9034 &.{try o.lowerType(operand_ty)},
...@@ -9204,6 +9046,7 @@ pub const FuncGen = struct {...@@ -9204,6 +9046,7 @@ pub const FuncGen = struct {
9204 const operand = try self.resolveInst(ty_op.operand);9046 const operand = try self.resolveInst(ty_op.operand);
92059047
9206 const result = try self.wip.callIntrinsic(9048 const result = try self.wip.callIntrinsic(
9049 .normal,
9207 .none,9050 .none,
9208 intrinsic,9051 intrinsic,
9209 &.{try o.lowerType(operand_ty)},9052 &.{try o.lowerType(operand_ty)},
...@@ -9242,7 +9085,8 @@ pub const FuncGen = struct {...@@ -9242,7 +9085,8 @@ pub const FuncGen = struct {
9242 bits = bits + 8;9085 bits = bits + 8;
9243 }9086 }
92449087
9245 const result = try self.wip.callIntrinsic(.none, .bswap, &.{llvm_operand_ty}, &.{operand}, "");9088 const result =
9089 try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, "");
9246 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");9090 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
9247 }9091 }
92489092
...@@ -9309,20 +9153,18 @@ pub const FuncGen = struct {...@@ -9309,20 +9153,18 @@ pub const FuncGen = struct {
9309 const function_index = try o.builder.addFunction(9153 const function_index = try o.builder.addFunction(
9310 try o.builder.fnType(.i1, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),9154 try o.builder.fnType(.i1, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
9311 try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}),9155 try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}),
9156 toLlvmAddressSpace(.generic, mod.getTarget()),
9312 );9157 );
93139158
9314 var attributes: Builder.FunctionAttributes.Wip = .{};9159 var attributes: Builder.FunctionAttributes.Wip = .{};
9315 defer attributes.deinit(&o.builder);9160 defer attributes.deinit(&o.builder);
9316 try o.addCommonFnAttributes(&attributes);9161 try o.addCommonFnAttributes(&attributes);
9317 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
93189162
9319 function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;9163 function_index.setLinkage(.internal, &o.builder);
9320 function_index.ptr(&o.builder).call_conv = .fastcc;9164 function_index.setCallConv(.fastcc, &o.builder);
9165 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9321 gop.value_ptr.* = function_index;9166 gop.value_ptr.* = function_index;
93229167
9323 function_index.toLlvm(&o.builder).setLinkage(.Internal);
9324 function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
9325
9326 var wip = try Builder.WipFunction.init(&o.builder, function_index);9168 var wip = try Builder.WipFunction.init(&o.builder, function_index);
9327 defer wip.deinit();9169 defer wip.deinit();
9328 wip.cursor = .{ .block = try wip.block(0, "Entry") };9170 wip.cursor = .{ .block = try wip.block(0, "Entry") };
...@@ -9383,20 +9225,18 @@ pub const FuncGen = struct {...@@ -9383,20 +9225,18 @@ pub const FuncGen = struct {
9383 const function_index = try o.builder.addFunction(9225 const function_index = try o.builder.addFunction(
9384 try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),9226 try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
9385 try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}),9227 try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}),
9228 toLlvmAddressSpace(.generic, mod.getTarget()),
9386 );9229 );
93879230
9388 var attributes: Builder.FunctionAttributes.Wip = .{};9231 var attributes: Builder.FunctionAttributes.Wip = .{};
9389 defer attributes.deinit(&o.builder);9232 defer attributes.deinit(&o.builder);
9390 try o.addCommonFnAttributes(&attributes);9233 try o.addCommonFnAttributes(&attributes);
9391 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
93929234
9393 function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;9235 function_index.setLinkage(.internal, &o.builder);
9394 function_index.ptr(&o.builder).call_conv = .fastcc;9236 function_index.setCallConv(.fastcc, &o.builder);
9237 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9395 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;9238 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
93969239
9397 function_index.toLlvm(&o.builder).setLinkage(.Internal);
9398 function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
9399
9400 var wip = try Builder.WipFunction.init(&o.builder, function_index);9240 var wip = try Builder.WipFunction.init(&o.builder, function_index);
9401 defer wip.deinit();9241 defer wip.deinit();
9402 wip.cursor = .{ .block = try wip.block(0, "Entry") };9242 wip.cursor = .{ .block = try wip.block(0, "Entry") };
...@@ -9407,36 +9247,20 @@ pub const FuncGen = struct {...@@ -9407,36 +9247,20 @@ pub const FuncGen = struct {
9407 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));9247 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
9408 defer wip_switch.finish(&wip);9248 defer wip_switch.finish(&wip);
94099249
9410 for (enum_type.names, 0..) |name_ip, field_index| {9250 for (enum_type.names, 0..) |name, field_index| {
9411 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_ip));9251 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
9412 const str_init = try o.builder.stringNullConst(name);9252 const name_init = try o.builder.stringNullConst(name_string);
9413 const str_ty = str_init.typeOf(&o.builder);9253 const name_variable_index =
9414 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");9254 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
9415 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));9255 try name_variable_index.setInitializer(name_init, &o.builder);
9416 str_llvm_global.setLinkage(.Private);9256 name_variable_index.setLinkage(.private, &o.builder);
9417 str_llvm_global.setGlobalConstant(.True);9257 name_variable_index.setMutability(.constant, &o.builder);
9418 str_llvm_global.setUnnamedAddr(.True);9258 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
9419 str_llvm_global.setAlignment(1);9259 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
94209260
9421 var str_global = Builder.Global{9261 const name_val = try o.builder.structValue(ret_ty, &.{
9422 .linkage = .private,9262 name_variable_index.toConst(&o.builder),
9423 .unnamed_addr = .unnamed_addr,9263 try o.builder.intConst(usize_ty, name_string.slice(&o.builder).?.len),
9424 .type = str_ty,
9425 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
9426 };
9427 var str_variable = Builder.Variable{
9428 .global = @enumFromInt(o.builder.globals.count()),
9429 .mutability = .constant,
9430 .init = str_init,
9431 .alignment = comptime Builder.Alignment.fromByteUnits(1),
9432 };
9433 try o.builder.llvm.globals.append(o.gpa, str_llvm_global);
9434 const global_index = try o.builder.addGlobal(.empty, str_global);
9435 try o.builder.variables.append(o.gpa, str_variable);
9436
9437 const slice_val = try o.builder.structValue(ret_ty, &.{
9438 global_index.toConst(),
9439 try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len),
9440 });9264 });
94419265
9442 const return_block = try wip.block(1, "Name");9266 const return_block = try wip.block(1, "Name");
...@@ -9446,7 +9270,7 @@ pub const FuncGen = struct {...@@ -9446,7 +9270,7 @@ pub const FuncGen = struct {
9446 try wip_switch.addCase(this_tag_int_value, return_block, &wip);9270 try wip_switch.addCase(this_tag_int_value, return_block, &wip);
94479271
9448 wip.cursor = .{ .block = return_block };9272 wip.cursor = .{ .block = return_block };
9449 _ = try wip.ret(slice_val);9273 _ = try wip.ret(name_val);
9450 }9274 }
94519275
9452 wip.cursor = .{ .block = bad_value_block };9276 wip.cursor = .{ .block = bad_value_block };
...@@ -9465,19 +9289,16 @@ pub const FuncGen = struct {...@@ -9465,19 +9289,16 @@ pub const FuncGen = struct {
9465 const function_index = try o.builder.addFunction(9289 const function_index = try o.builder.addFunction(
9466 try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal),9290 try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal),
9467 name,9291 name,
9292 toLlvmAddressSpace(.generic, o.module.getTarget()),
9468 );9293 );
94699294
9470 var attributes: Builder.FunctionAttributes.Wip = .{};9295 var attributes: Builder.FunctionAttributes.Wip = .{};
9471 defer attributes.deinit(&o.builder);9296 defer attributes.deinit(&o.builder);
9472 try o.addCommonFnAttributes(&attributes);9297 try o.addCommonFnAttributes(&attributes);
9473 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9474
9475 function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal;
9476 function_index.ptr(&o.builder).call_conv = .fastcc;
9477
9478 function_index.toLlvm(&o.builder).setLinkage(.Internal);
9479 function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
94809298
9299 function_index.setLinkage(.internal, &o.builder);
9300 function_index.setCallConv(.fastcc, &o.builder);
9301 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9481 return function_index;9302 return function_index;
9482 }9303 }
94839304
...@@ -9511,7 +9332,7 @@ pub const FuncGen = struct {...@@ -9511,7 +9332,7 @@ pub const FuncGen = struct {
9511 const a = try self.resolveInst(extra.lhs);9332 const a = try self.resolveInst(extra.lhs);
9512 const b = try self.resolveInst(extra.rhs);9333 const b = try self.resolveInst(extra.rhs);
95139334
9514 return self.wip.select(pred, a, b, "");9335 return self.wip.select(.normal, pred, a, b, "");
9515 }9336 }
95169337
9517 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9338 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -9623,8 +9444,7 @@ pub const FuncGen = struct {...@@ -9623,8 +9444,7 @@ pub const FuncGen = struct {
9623 return self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, "");9444 return self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, "");
9624 }9445 }
96259446
9626 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {9447 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
9627 self.builder.setFastMath(want_fast_math);
9628 const o = self.dg.object;9448 const o = self.dg.object;
9629 const mod = o.module;9449 const mod = o.module;
9630 const target = mod.getTarget();9450 const target = mod.getTarget();
...@@ -9637,14 +9457,14 @@ pub const FuncGen = struct {...@@ -9637,14 +9457,14 @@ pub const FuncGen = struct {
9637 const llvm_scalar_ty = try o.lowerType(scalar_ty);9457 const llvm_scalar_ty = try o.lowerType(scalar_ty);
96389458
9639 switch (reduce.operation) {9459 switch (reduce.operation) {
9640 .And, .Or, .Xor => return self.wip.callIntrinsic(.none, switch (reduce.operation) {9460 .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
9641 .And => .@"vector.reduce.and",9461 .And => .@"vector.reduce.and",
9642 .Or => .@"vector.reduce.or",9462 .Or => .@"vector.reduce.or",
9643 .Xor => .@"vector.reduce.xor",9463 .Xor => .@"vector.reduce.xor",
9644 else => unreachable,9464 else => unreachable,
9645 }, &.{llvm_operand_ty}, &.{operand}, ""),9465 }, &.{llvm_operand_ty}, &.{operand}, ""),
9646 .Min, .Max => switch (scalar_ty.zigTypeTag(mod)) {9466 .Min, .Max => switch (scalar_ty.zigTypeTag(mod)) {
9647 .Int => return self.wip.callIntrinsic(.none, switch (reduce.operation) {9467 .Int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
9648 .Min => if (scalar_ty.isSignedInt(mod))9468 .Min => if (scalar_ty.isSignedInt(mod))
9649 .@"vector.reduce.smin"9469 .@"vector.reduce.smin"
9650 else9470 else
...@@ -9656,7 +9476,7 @@ pub const FuncGen = struct {...@@ -9656,7 +9476,7 @@ pub const FuncGen = struct {
9656 else => unreachable,9476 else => unreachable,
9657 }, &.{llvm_operand_ty}, &.{operand}, ""),9477 }, &.{llvm_operand_ty}, &.{operand}, ""),
9658 .Float => if (intrinsicsAllowed(scalar_ty, target))9478 .Float => if (intrinsicsAllowed(scalar_ty, target))
9659 return self.wip.callIntrinsic(.none, switch (reduce.operation) {9479 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
9660 .Min => .@"vector.reduce.fmin",9480 .Min => .@"vector.reduce.fmin",
9661 .Max => .@"vector.reduce.fmax",9481 .Max => .@"vector.reduce.fmax",
9662 else => unreachable,9482 else => unreachable,
...@@ -9664,13 +9484,13 @@ pub const FuncGen = struct {...@@ -9664,13 +9484,13 @@ pub const FuncGen = struct {
9664 else => unreachable,9484 else => unreachable,
9665 },9485 },
9666 .Add, .Mul => switch (scalar_ty.zigTypeTag(mod)) {9486 .Add, .Mul => switch (scalar_ty.zigTypeTag(mod)) {
9667 .Int => return self.wip.callIntrinsic(.none, switch (reduce.operation) {9487 .Int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
9668 .Add => .@"vector.reduce.add",9488 .Add => .@"vector.reduce.add",
9669 .Mul => .@"vector.reduce.mul",9489 .Mul => .@"vector.reduce.mul",
9670 else => unreachable,9490 else => unreachable,
9671 }, &.{llvm_operand_ty}, &.{operand}, ""),9491 }, &.{llvm_operand_ty}, &.{operand}, ""),
9672 .Float => if (intrinsicsAllowed(scalar_ty, target))9492 .Float => if (intrinsicsAllowed(scalar_ty, target))
9673 return self.wip.callIntrinsic(.none, switch (reduce.operation) {9493 return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
9674 .Add => .@"vector.reduce.fadd",9494 .Add => .@"vector.reduce.fadd",
9675 .Mul => .@"vector.reduce.fmul",9495 .Mul => .@"vector.reduce.fmul",
9676 else => unreachable,9496 else => unreachable,
...@@ -10021,7 +9841,7 @@ pub const FuncGen = struct {...@@ -10021,7 +9841,7 @@ pub const FuncGen = struct {
10021 .data => {},9841 .data => {},
10022 }9842 }
100239843
10024 _ = try self.wip.callIntrinsic(.none, .prefetch, &.{.ptr}, &.{9844 _ = try self.wip.callIntrinsic(.normal, .none, .prefetch, &.{.ptr}, &.{
10025 try self.resolveInst(prefetch.ptr),9845 try self.resolveInst(prefetch.ptr),
10026 try o.builder.intValue(.i32, prefetch.rw),9846 try o.builder.intValue(.i32, prefetch.rw),
10027 try o.builder.intValue(.i32, prefetch.locality),9847 try o.builder.intValue(.i32, prefetch.locality),
...@@ -10045,7 +9865,7 @@ pub const FuncGen = struct {...@@ -10045,7 +9865,7 @@ pub const FuncGen = struct {
10045 default: u32,9865 default: u32,
10046 comptime basename: []const u8,9866 comptime basename: []const u8,
10047 ) !Builder.Value {9867 ) !Builder.Value {
10048 return self.wip.callIntrinsic(.none, switch (dimension) {9868 return self.wip.callIntrinsic(.normal, .none, switch (dimension) {
10049 0 => @field(Builder.Intrinsic, basename ++ ".x"),9869 0 => @field(Builder.Intrinsic, basename ++ ".x"),
10050 1 => @field(Builder.Intrinsic, basename ++ ".y"),9870 1 => @field(Builder.Intrinsic, basename ++ ".y"),
10051 2 => @field(Builder.Intrinsic, basename ++ ".z"),9871 2 => @field(Builder.Intrinsic, basename ++ ".z"),
...@@ -10074,7 +9894,8 @@ pub const FuncGen = struct {...@@ -10074,7 +9894,8 @@ pub const FuncGen = struct {
100749894
10075 // Fetch the dispatch pointer, which points to this structure:9895 // Fetch the dispatch pointer, which points to this structure:
10076 // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L29139896 // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913
10077 const dispatch_ptr = try self.wip.callIntrinsic(.none, .@"amdgcn.dispatch.ptr", &.{}, &.{}, "");9897 const dispatch_ptr =
9898 try self.wip.callIntrinsic(.normal, .none, .@"amdgcn.dispatch.ptr", &.{}, &.{}, "");
100789899
10079 // Load the work_group_* member from the struct as u16.9900 // Load the work_group_* member from the struct as u16.
10080 // Just treat the dispatch pointer as an array of u16 to keep things simple.9901 // Just treat the dispatch pointer as an array of u16 to keep things simple.
...@@ -10097,40 +9918,24 @@ pub const FuncGen = struct {...@@ -10097,40 +9918,24 @@ pub const FuncGen = struct {
100979918
10098 fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index {9919 fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index {
10099 const o = self.dg.object;9920 const o = self.dg.object;
9921 const mod = o.module;
9922
10100 const table = o.error_name_table;9923 const table = o.error_name_table;
10101 if (table != .none) return table;9924 if (table != .none) return table;
101029925
10103 const mod = o.module;9926 // TODO: Address space
10104 const slice_ty = Type.slice_const_u8_sentinel_0;9927 const variable_index =
10105 const slice_alignment = slice_ty.abiAlignment(mod);9928 try o.builder.addVariable(try o.builder.string("__zig_err_name_table"), .ptr, .default);
10106 const undef_init = try o.builder.undefConst(.ptr); // TODO: Address space9929 variable_index.setLinkage(.private, &o.builder);
101079930 variable_index.setMutability(.constant, &o.builder);
10108 const name = try o.builder.string("__zig_err_name_table");9931 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
10109 const error_name_table_global = o.llvm_module.addGlobal(Builder.Type.ptr.toLlvm(&o.builder), name.slice(&o.builder).?);9932 variable_index.setAlignment(
10110 error_name_table_global.setInitializer(undef_init.toLlvm(&o.builder));9933 Builder.Alignment.fromByteUnits(Type.slice_const_u8_sentinel_0.abiAlignment(mod)),
10111 error_name_table_global.setLinkage(.Private);9934 &o.builder,
10112 error_name_table_global.setGlobalConstant(.True);9935 );
10113 error_name_table_global.setUnnamedAddr(.True);
10114 error_name_table_global.setAlignment(slice_alignment);
10115
10116 var global = Builder.Global{
10117 .linkage = .private,
10118 .unnamed_addr = .unnamed_addr,
10119 .type = .ptr,
10120 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
10121 };
10122 var variable = Builder.Variable{
10123 .global = @enumFromInt(o.builder.globals.count()),
10124 .mutability = .constant,
10125 .init = undef_init,
10126 .alignment = Builder.Alignment.fromByteUnits(slice_alignment),
10127 };
10128 try o.builder.llvm.globals.append(o.gpa, error_name_table_global);
10129 _ = try o.builder.addGlobal(name, global);
10130 try o.builder.variables.append(o.gpa, variable);
101319936
10132 o.error_name_table = global.kind.variable;9937 o.error_name_table = variable_index;
10133 return global.kind.variable;9938 return variable_index;
10134 }9939 }
101359940
10136 /// Assumes the optional is not pointer-like and payload has bits.9941 /// Assumes the optional is not pointer-like and payload has bits.
...@@ -11547,15 +11352,19 @@ fn buildAllocaInner(...@@ -11547,15 +11352,19 @@ fn buildAllocaInner(
1154711352
11548 const alloca = blk: {11353 const alloca = blk: {
11549 const prev_cursor = wip.cursor;11354 const prev_cursor = wip.cursor;
11550 const prev_debug_location = wip.llvm.builder.getCurrentDebugLocation2();11355 const prev_debug_location = if (wip.builder.useLibLlvm())
11356 wip.llvm.builder.getCurrentDebugLocation2()
11357 else
11358 undefined;
11551 defer {11359 defer {
11552 wip.cursor = prev_cursor;11360 wip.cursor = prev_cursor;
11553 if (wip.cursor.block == .entry) wip.cursor.instruction += 1;11361 if (wip.cursor.block == .entry) wip.cursor.instruction += 1;
11554 if (di_scope_non_null) wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location);11362 if (wip.builder.useLibLlvm() and di_scope_non_null)
11363 wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location);
11555 }11364 }
1155611365
11557 wip.cursor = .{ .block = .entry };11366 wip.cursor = .{ .block = .entry };
11558 wip.llvm.builder.clearCurrentDebugLocation();11367 if (wip.builder.useLibLlvm()) wip.llvm.builder.clearCurrentDebugLocation();
11559 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");11368 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");
11560 };11369 };
1156111370
src/codegen/llvm/Builder.zig+511-119
...@@ -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,
...@@ -1709,17 +1710,17 @@ pub const FunctionAttributes = enum(u32) {...@@ -1709,17 +1710,17 @@ pub const FunctionAttributes = enum(u32) {
1709};1710};
17101711
1711pub const Linkage = enum {1712pub const Linkage = enum {
1712 external,
1713 private,1713 private,
1714 internal,1714 internal,
1715 available_externally,
1716 linkonce,
1717 weak,1715 weak,
1718 common,1716 weak_odr,
1717 linkonce,
1718 linkonce_odr,
1719 available_externally,
1719 appending,1720 appending,
1721 common,
1720 extern_weak,1722 extern_weak,
1721 linkonce_odr,1723 external,
1722 weak_odr,
17231724
1724 pub fn format(1725 pub fn format(
1725 self: Linkage,1726 self: Linkage,
...@@ -1729,6 +1730,22 @@ pub const Linkage = enum {...@@ -1729,6 +1730,22 @@ pub const Linkage = enum {
1729 ) @TypeOf(writer).Error!void {1730 ) @TypeOf(writer).Error!void {
1730 if (self != .external) try writer.print(" {s}", .{@tagName(self)});1731 if (self != .external) try writer.print(" {s}", .{@tagName(self)});
1731 }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 }
1732};1749};
17331750
1734pub const Preemption = enum {1751pub const Preemption = enum {
...@@ -1759,6 +1776,14 @@ pub const Visibility = enum {...@@ -1759,6 +1776,14 @@ pub const Visibility = enum {
1759 ) @TypeOf(writer).Error!void {1776 ) @TypeOf(writer).Error!void {
1760 if (self != .default) try writer.print(" {s}", .{@tagName(self)});1777 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1761 }1778 }
1779
1780 fn toLlvm(self: Visibility) llvm.Visibility {
1781 return switch (self) {
1782 .default => .Default,
1783 .hidden => .Hidden,
1784 .protected => .Protected,
1785 };
1786 }
1762};1787};
17631788
1764pub const DllStorageClass = enum {1789pub const DllStorageClass = enum {
...@@ -1774,6 +1799,14 @@ pub const DllStorageClass = enum {...@@ -1774,6 +1799,14 @@ pub const DllStorageClass = enum {
1774 ) @TypeOf(writer).Error!void {1799 ) @TypeOf(writer).Error!void {
1775 if (self != .default) try writer.print(" {s}", .{@tagName(self)});1800 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1776 }1801 }
1802
1803 fn toLlvm(self: DllStorageClass) llvm.DLLStorageClass {
1804 return switch (self) {
1805 .default => .Default,
1806 .dllimport => .DLLImport,
1807 .dllexport => .DLLExport,
1808 };
1809 }
1777};1810};
17781811
1779pub const ThreadLocal = enum {1812pub const ThreadLocal = enum {
...@@ -1785,20 +1818,28 @@ pub const ThreadLocal = enum {...@@ -1785,20 +1818,28 @@ pub const ThreadLocal = enum {
17851818
1786 pub fn format(1819 pub fn format(
1787 self: ThreadLocal,1820 self: ThreadLocal,
1788 comptime _: []const u8,1821 comptime prefix: []const u8,
1789 _: std.fmt.FormatOptions,1822 _: std.fmt.FormatOptions,
1790 writer: anytype,1823 writer: anytype,
1791 ) @TypeOf(writer).Error!void {1824 ) @TypeOf(writer).Error!void {
1792 if (self == .default) return;1825 if (self == .default) return;
1793 try writer.writeAll(" thread_local");1826 try writer.print("{s}thread_local", .{prefix});
1794 if (self != .generaldynamic) {1827 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});
1795 try writer.writeByte('(');1828 }
1796 try writer.writeAll(@tagName(self));1829
1797 try writer.writeByte(')');1830 fn toLlvm(self: ThreadLocal) llvm.ThreadLocalMode {
1798 }1831 return switch (self) {
1832 .default => .NotThreadLocal,
1833 .generaldynamic => .GeneralDynamicTLSModel,
1834 .localdynamic => .LocalDynamicTLSModel,
1835 .initialexec => .InitialExecTLSModel,
1836 .localexec => .LocalExecTLSModel,
1837 };
1799 }1838 }
1800};1839};
18011840
1841pub const Mutability = enum { global, constant };
1842
1802pub const UnnamedAddr = enum {1843pub const UnnamedAddr = enum {
1803 default,1844 default,
1804 unnamed_addr,1845 unnamed_addr,
...@@ -2057,6 +2098,11 @@ pub const CallConv = enum(u10) {...@@ -2057,6 +2098,11 @@ pub const CallConv = enum(u10) {
2057 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),2098 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),
2058 }2099 }
2059 }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 }
2060};2106};
20612107
2062pub const Global = struct {2108pub const Global = struct {
...@@ -2093,10 +2139,6 @@ pub const Global = struct {...@@ -2093,10 +2139,6 @@ pub const Global = struct {
2093 return self.unwrap(builder) == other.unwrap(builder);2139 return self.unwrap(builder) == other.unwrap(builder);
2094 }2140 }
20952141
2096 pub fn name(self: Index, builder: *const Builder) String {
2097 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
2098 }
2099
2100 pub fn ptr(self: Index, builder: *Builder) *Global {2142 pub fn ptr(self: Index, builder: *Builder) *Global {
2101 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];2143 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
2102 }2144 }
...@@ -2105,6 +2147,10 @@ pub const Global = struct {...@@ -2105,6 +2147,10 @@ pub const Global = struct {
2105 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];2147 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
2106 }2148 }
21072149
2150 pub fn name(self: Index, builder: *const Builder) String {
2151 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
2152 }
2153
2108 pub fn typeOf(self: Index, builder: *const Builder) Type {2154 pub fn typeOf(self: Index, builder: *const Builder) Type {
2109 return self.ptrConst(builder).type;2155 return self.ptrConst(builder).type;
2110 }2156 }
...@@ -2113,6 +2159,30 @@ pub const Global = struct {...@@ -2113,6 +2159,30 @@ pub const Global = struct {
2113 return @enumFromInt(@intFromEnum(Constant.first_global) + @intFromEnum(self));2159 return @enumFromInt(@intFromEnum(Constant.first_global) + @intFromEnum(self));
2114 }2160 }
21152161
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
2116 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {2186 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
2117 assert(builder.useLibLlvm());2187 assert(builder.useLibLlvm());
2118 return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))];2188 return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))];
...@@ -2148,9 +2218,36 @@ pub const Global = struct {...@@ -2148,9 +2218,36 @@ pub const Global = struct {
21482218
2149 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 {
2150 try builder.ensureUnusedGlobalCapacity(.empty);2220 try builder.ensureUnusedGlobalCapacity(.empty);
2221 if (builder.useLibLlvm())
2222 try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1);
2151 self.replaceAssumeCapacity(other, builder);2223 self.replaceAssumeCapacity(other, builder);
2152 }2224 }
21532225
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
2154 fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void {2251 fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void {
2155 const old_name = self.name(builder);2252 const old_name = self.name(builder);
2156 if (new_name == old_name) return;2253 if (new_name == old_name) return;
...@@ -2187,13 +2284,8 @@ pub const Global = struct {...@@ -2187,13 +2284,8 @@ pub const Global = struct {
2187 if (builder.useLibLlvm()) {2284 if (builder.useLibLlvm()) {
2188 const self_llvm = self.toLlvm(builder);2285 const self_llvm = self.toLlvm(builder);
2189 self_llvm.replaceAllUsesWith(other.toLlvm(builder));2286 self_llvm.replaceAllUsesWith(other.toLlvm(builder));
2190 switch (self.ptr(builder).kind) {2287 self_llvm.removeGlobalValue();
2191 .alias,2288 builder.llvm.replacements.putAssumeCapacityNoClobber(self_llvm, other);
2192 .variable,
2193 => self_llvm.deleteGlobal(),
2194 .function => self_llvm.deleteFunction(),
2195 .replaced => unreachable,
2196 }
2197 }2289 }
2198 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };2290 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
2199 }2291 }
...@@ -2205,42 +2297,17 @@ pub const Global = struct {...@@ -2205,42 +2297,17 @@ pub const Global = struct {
2205 };2297 };
2206 }2298 }
2207 };2299 };
2208
2209 pub fn updateAttributes(self: *Global) void {
2210 switch (self.linkage) {
2211 .private, .internal => {
2212 self.visibility = .default;
2213 self.dll_storage_class = .default;
2214 self.preemption = .implicit_dso_local;
2215 },
2216 .extern_weak => if (self.preemption == .implicit_dso_local) {
2217 self.preemption = .dso_local;
2218 },
2219 else => switch (self.visibility) {
2220 .default => if (self.preemption == .implicit_dso_local) {
2221 self.preemption = .dso_local;
2222 },
2223 else => self.preemption = .implicit_dso_local,
2224 },
2225 }
2226 }
2227};2300};
22282301
2229pub const Alias = struct {2302pub const Alias = struct {
2230 global: Global.Index,2303 global: Global.Index,
2231 thread_local: ThreadLocal = .default,2304 thread_local: ThreadLocal = .default,
2232 init: Constant = .no_init,2305 aliasee: Constant = .no_init,
22332306
2234 pub const Index = enum(u32) {2307 pub const Index = enum(u32) {
2235 none = std.math.maxInt(u32),2308 none = std.math.maxInt(u32),
2236 _,2309 _,
22372310
2238 pub fn getAliasee(self: Index, builder: *const Builder) Global.Index {
2239 const aliasee = self.ptrConst(builder).init.getBase(builder);
2240 assert(aliasee != .none);
2241 return aliasee;
2242 }
2243
2244 pub fn ptr(self: Index, builder: *Builder) *Alias {2311 pub fn ptr(self: Index, builder: *Builder) *Alias {
2245 return &builder.aliases.items[@intFromEnum(self)];2312 return &builder.aliases.items[@intFromEnum(self)];
2246 }2313 }
...@@ -2249,6 +2316,10 @@ pub const Alias = struct {...@@ -2249,6 +2316,10 @@ pub const Alias = struct {
2249 return &builder.aliases.items[@intFromEnum(self)];2316 return &builder.aliases.items[@intFromEnum(self)];
2250 }2317 }
22512318
2319 pub fn name(self: Index, builder: *const Builder) String {
2320 return self.ptrConst(builder).global.name(builder);
2321 }
2322
2252 pub fn typeOf(self: Index, builder: *const Builder) Type {2323 pub fn typeOf(self: Index, builder: *const Builder) Type {
2253 return self.ptrConst(builder).global.typeOf(builder);2324 return self.ptrConst(builder).global.typeOf(builder);
2254 }2325 }
...@@ -2261,7 +2332,18 @@ pub const Alias = struct {...@@ -2261,7 +2332,18 @@ pub const Alias = struct {
2261 return self.toConst(builder).toValue();2332 return self.toConst(builder).toValue();
2262 }2333 }
22632334
2264 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {2335 pub fn getAliasee(self: Index, builder: *const Builder) Global.Index {
2336 const aliasee = self.ptrConst(builder).aliasee.getBase(builder);
2337 assert(aliasee != .none);
2338 return aliasee;
2339 }
2340
2341 pub fn setAliasee(self: Index, aliasee: Constant, builder: *Builder) void {
2342 if (builder.useLibLlvm()) self.toLlvm(builder).setAliasee(aliasee.toLlvm(builder));
2343 self.ptr(builder).aliasee = aliasee;
2344 }
2345
2346 fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
2265 return self.ptrConst(builder).global.toLlvm(builder);2347 return self.ptrConst(builder).global.toLlvm(builder);
2266 }2348 }
2267 };2349 };
...@@ -2270,7 +2352,7 @@ pub const Alias = struct {...@@ -2270,7 +2352,7 @@ pub const Alias = struct {
2270pub const Variable = struct {2352pub const Variable = struct {
2271 global: Global.Index,2353 global: Global.Index,
2272 thread_local: ThreadLocal = .default,2354 thread_local: ThreadLocal = .default,
2273 mutability: enum { global, constant } = .global,2355 mutability: Mutability = .global,
2274 init: Constant = .no_init,2356 init: Constant = .no_init,
2275 section: String = .none,2357 section: String = .none,
2276 alignment: Alignment = .default,2358 alignment: Alignment = .default,
...@@ -2287,6 +2369,10 @@ pub const Variable = struct {...@@ -2287,6 +2369,10 @@ pub const Variable = struct {
2287 return &builder.variables.items[@intFromEnum(self)];2369 return &builder.variables.items[@intFromEnum(self)];
2288 }2370 }
22892371
2372 pub fn name(self: Index, builder: *const Builder) String {
2373 return self.ptrConst(builder).global.name(builder);
2374 }
2375
2290 pub fn typeOf(self: Index, builder: *const Builder) Type {2376 pub fn typeOf(self: Index, builder: *const Builder) Type {
2291 return self.ptrConst(builder).global.typeOf(builder);2377 return self.ptrConst(builder).global.typeOf(builder);
2292 }2378 }
...@@ -2299,6 +2385,88 @@ pub const Variable = struct {...@@ -2299,6 +2385,88 @@ pub const Variable = struct {
2299 return self.toConst(builder).toValue();2385 return self.toConst(builder).toValue();
2300 }2386 }
23012387
2388 pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void {
2389 return self.ptrConst(builder).global.setLinkage(linkage, builder);
2390 }
2391
2392 pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void {
2393 return self.ptrConst(builder).global.setUnnamedAddr(unnamed_addr, builder);
2394 }
2395
2396 pub fn setThreadLocal(self: Index, thread_local: ThreadLocal, builder: *Builder) void {
2397 if (builder.useLibLlvm()) self.toLlvm(builder).setThreadLocalMode(thread_local.toLlvm());
2398 self.ptr(builder).thread_local = thread_local;
2399 }
2400
2401 pub fn setMutability(self: Index, mutability: Mutability, builder: *Builder) void {
2402 if (builder.useLibLlvm()) self.toLlvm(builder).setGlobalConstant(
2403 llvm.Bool.fromBool(mutability == .constant),
2404 );
2405 self.ptr(builder).mutability = mutability;
2406 }
2407
2408 pub fn setInitializer(
2409 self: Index,
2410 initializer: Constant,
2411 builder: *Builder,
2412 ) Allocator.Error!void {
2413 if (initializer != .no_init) {
2414 const variable = self.ptrConst(builder);
2415 const global = variable.global.ptr(builder);
2416 const initializer_type = initializer.typeOf(builder);
2417 if (builder.useLibLlvm() and global.type != initializer_type) {
2418 try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1);
2419 // LLVM does not allow us to change the type of globals. So we must
2420 // create a new global with the correct type, copy all its attributes,
2421 // and then update all references to point to the new global,
2422 // delete the original, and rename the new one to the old one's name.
2423 // This is necessary because LLVM does not support const bitcasting
2424 // a struct with padding bytes, which is needed to lower a const union value
2425 // to LLVM, when a field other than the most-aligned is active. Instead,
2426 // we must lower to an unnamed struct, and pointer cast at usage sites
2427 // of the global. Such an unnamed struct is the cause of the global type
2428 // mismatch, because we don't have the LLVM type until the *value* is created,
2429 // whereas the global needs to be created based on the type alone, because
2430 // lowering the value may reference the global as a pointer.
2431 // Related: https://github.com/ziglang/zig/issues/13265
2432 const old_global = &builder.llvm.globals.items[@intFromEnum(variable.global)];
2433 const new_global = builder.llvm.module.?.addGlobalInAddressSpace(
2434 initializer_type.toLlvm(builder),
2435 "",
2436 @intFromEnum(global.addr_space),
2437 );
2438 new_global.setLinkage(global.linkage.toLlvm());
2439 new_global.setUnnamedAddr(llvm.Bool.fromBool(global.unnamed_addr != .default));
2440 new_global.setAlignment(@intCast(variable.alignment.toByteUnits() orelse 0));
2441 if (variable.section != .none)
2442 new_global.setSection(variable.section.slice(builder).?);
2443 old_global.*.replaceAllUsesWith(new_global);
2444 builder.llvm.replacements.putAssumeCapacityNoClobber(old_global.*, variable.global);
2445 new_global.takeName(old_global.*);
2446 old_global.*.removeGlobalValue();
2447 old_global.* = new_global;
2448 self.ptr(builder).mutability = .global;
2449 }
2450 global.type = initializer_type;
2451 }
2452 if (builder.useLibLlvm()) self.toLlvm(builder).setInitializer(switch (initializer) {
2453 .no_init => null,
2454 else => initializer.toLlvm(builder),
2455 });
2456 self.ptr(builder).init = initializer;
2457 }
2458
2459 pub fn setSection(self: Index, section: String, builder: *Builder) void {
2460 if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?);
2461 self.ptr(builder).section = section;
2462 }
2463
2464 pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void {
2465 if (builder.useLibLlvm())
2466 self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0));
2467 self.ptr(builder).alignment = alignment;
2468 }
2469
2302 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {2470 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
2303 return self.ptrConst(builder).global.toLlvm(builder);2471 return self.ptrConst(builder).global.toLlvm(builder);
2304 }2472 }
...@@ -3640,6 +3808,10 @@ pub const Function = struct {...@@ -3640,6 +3808,10 @@ pub const Function = struct {
3640 return &builder.functions.items[@intFromEnum(self)];3808 return &builder.functions.items[@intFromEnum(self)];
3641 }3809 }
36423810
3811 pub fn name(self: Index, builder: *const Builder) String {
3812 return self.ptrConst(builder).global.name(builder);
3813 }
3814
3643 pub fn typeOf(self: Index, builder: *const Builder) Type {3815 pub fn typeOf(self: Index, builder: *const Builder) Type {
3644 return self.ptrConst(builder).global.typeOf(builder);3816 return self.ptrConst(builder).global.typeOf(builder);
3645 }3817 }
...@@ -3652,6 +3824,19 @@ pub const Function = struct {...@@ -3652,6 +3824,19 @@ pub const Function = struct {
3652 return self.toConst(builder).toValue();3824 return self.toConst(builder).toValue();
3653 }3825 }
36543826
3827 pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void {
3828 return self.ptrConst(builder).global.setLinkage(linkage, builder);
3829 }
3830
3831 pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void {
3832 return self.ptrConst(builder).global.setUnnamedAddr(unnamed_addr, builder);
3833 }
3834
3835 pub fn setCallConv(self: Index, call_conv: CallConv, builder: *Builder) void {
3836 if (builder.useLibLlvm()) self.toLlvm(builder).setFunctionCallConv(call_conv.toLlvm());
3837 self.ptr(builder).call_conv = call_conv;
3838 }
3839
3655 pub fn setAttributes(3840 pub fn setAttributes(
3656 self: Index,3841 self: Index,
3657 new_function_attributes: FunctionAttributes,3842 new_function_attributes: FunctionAttributes,
...@@ -3687,12 +3872,12 @@ pub const Function = struct {...@@ -3687,12 +3872,12 @@ pub const Function = struct {
3687 )) {3872 )) {
3688 .lt => {3873 .lt => {
3689 // Removed3874 // Removed
3690 if (old_attribute_kind.toString()) |name| {3875 if (old_attribute_kind.toString()) |attribute_name| {
3691 const slice = name.slice(builder).?;3876 const attribute_name_slice = attribute_name.slice(builder).?;
3692 llvm_function.removeStringAttributeAtIndex(3877 llvm_function.removeStringAttributeAtIndex(
3693 llvm_attribute_index,3878 llvm_attribute_index,
3694 slice.ptr,3879 attribute_name_slice.ptr,
3695 @intCast(slice.len),3880 @intCast(attribute_name_slice.len),
3696 );3881 );
3697 } else {3882 } else {
3698 const llvm_kind_id = old_attribute_kind.toLlvm(builder).*;3883 const llvm_kind_id = old_attribute_kind.toLlvm(builder).*;
...@@ -3732,6 +3917,17 @@ pub const Function = struct {...@@ -3732,6 +3917,17 @@ pub const Function = struct {
3732 self.ptr(builder).attributes = new_function_attributes;3917 self.ptr(builder).attributes = new_function_attributes;
3733 }3918 }
37343919
3920 pub fn setSection(self: Index, section: String, builder: *Builder) void {
3921 if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?);
3922 self.ptr(builder).section = section;
3923 }
3924
3925 pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void {
3926 if (builder.useLibLlvm())
3927 self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0));
3928 self.ptr(builder).alignment = alignment;
3929 }
3930
3735 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {3931 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
3736 return self.ptrConst(builder).global.toLlvm(builder);3932 return self.ptrConst(builder).global.toLlvm(builder);
3737 }3933 }
...@@ -4342,9 +4538,11 @@ pub const Function = struct {...@@ -4342,9 +4538,11 @@ pub const Function = struct {
4342 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };4538 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };
4343 }4539 }
43444540
4345 pub fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value {4541 fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value {
4346 assert(wip.builder.useLibLlvm());4542 assert(wip.builder.useLibLlvm());
4347 return wip.llvm.instructions.items[@intFromEnum(self)];4543 const llvm_value = wip.llvm.instructions.items[@intFromEnum(self)];
4544 const global = wip.builder.llvm.replacements.get(llvm_value) orelse return llvm_value;
4545 return global.toLlvm(wip.builder);
4348 }4546 }
43494547
4350 fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 {4548 fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 {
...@@ -4462,6 +4660,27 @@ pub const Function = struct {...@@ -4462,6 +4660,27 @@ pub const Function = struct {
4462 fmax,4660 fmax,
4463 fmin,4661 fmin,
4464 none = std.math.maxInt(u5),4662 none = std.math.maxInt(u5),
4663
4664 fn toLlvm(self: Operation) llvm.AtomicRMWBinOp {
4665 return switch (self) {
4666 .xchg => .Xchg,
4667 .add => .Add,
4668 .sub => .Sub,
4669 .@"and" => .And,
4670 .nand => .Nand,
4671 .@"or" => .Or,
4672 .xor => .Xor,
4673 .max => .Max,
4674 .min => .Min,
4675 .umax => .UMax,
4676 .umin => .UMin,
4677 .fadd => .FAdd,
4678 .fsub => .FSub,
4679 .fmax => .FMax,
4680 .fmin => .FMin,
4681 .none => unreachable,
4682 };
4683 }
4465 };4684 };
4466 };4685 };
44674686
...@@ -5245,7 +5464,7 @@ pub const WipFunction = struct {...@@ -5245,7 +5464,7 @@ pub const WipFunction = struct {
5245 instruction.llvmName(self),5464 instruction.llvmName(self),
5246 );5465 );
5247 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);5466 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5248 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));5467 if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm());
5249 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));5468 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5250 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);5469 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5251 }5470 }
...@@ -5295,7 +5514,7 @@ pub const WipFunction = struct {...@@ -5295,7 +5514,7 @@ pub const WipFunction = struct {
5295 if (self.builder.useLibLlvm()) {5514 if (self.builder.useLibLlvm()) {
5296 const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self));5515 const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self));
5297 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);5516 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
5298 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));5517 if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm());
5299 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));5518 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
5300 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);5519 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
5301 }5520 }
...@@ -5318,7 +5537,7 @@ pub const WipFunction = struct {...@@ -5318,7 +5537,7 @@ pub const WipFunction = struct {
5318 });5537 });
5319 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(5538 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
5320 self.llvm.builder.buildFence(5539 self.llvm.builder.buildFence(
5321 @enumFromInt(@intFromEnum(ordering)),5540 ordering.toLlvm(),
5322 llvm.Bool.fromBool(sync_scope == .singlethread),5541 llvm.Bool.fromBool(sync_scope == .singlethread),
5323 "",5542 "",
5324 ),5543 ),
...@@ -5370,8 +5589,8 @@ pub const WipFunction = struct {...@@ -5370,8 +5589,8 @@ pub const WipFunction = struct {
5370 ptr.toLlvm(self),5589 ptr.toLlvm(self),
5371 cmp.toLlvm(self),5590 cmp.toLlvm(self),
5372 new.toLlvm(self),5591 new.toLlvm(self),
5373 @enumFromInt(@intFromEnum(success_ordering)),5592 success_ordering.toLlvm(),
5374 @enumFromInt(@intFromEnum(failure_ordering)),5593 failure_ordering.toLlvm(),
5375 llvm.Bool.fromBool(sync_scope == .singlethread),5594 llvm.Bool.fromBool(sync_scope == .singlethread),
5376 );5595 );
5377 if (kind == .weak) llvm_instruction.setWeak(.True);5596 if (kind == .weak) llvm_instruction.setWeak(.True);
...@@ -5418,10 +5637,10 @@ pub const WipFunction = struct {...@@ -5418,10 +5637,10 @@ pub const WipFunction = struct {
5418 });5637 });
5419 if (self.builder.useLibLlvm()) {5638 if (self.builder.useLibLlvm()) {
5420 const llvm_instruction = self.llvm.builder.buildAtomicRmw(5639 const llvm_instruction = self.llvm.builder.buildAtomicRmw(
5421 @enumFromInt(@intFromEnum(operation)),5640 operation.toLlvm(),
5422 ptr.toLlvm(self),5641 ptr.toLlvm(self),
5423 val.toLlvm(self),5642 val.toLlvm(self),
5424 @enumFromInt(@intFromEnum(ordering)),5643 ordering.toLlvm(),
5425 llvm.Bool.fromBool(sync_scope == .singlethread),5644 llvm.Bool.fromBool(sync_scope == .singlethread),
5426 );5645 );
5427 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);5646 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
...@@ -5608,25 +5827,19 @@ pub const WipFunction = struct {...@@ -5608,25 +5827,19 @@ pub const WipFunction = struct {
56085827
5609 pub fn fcmp(5828 pub fn fcmp(
5610 self: *WipFunction,5829 self: *WipFunction,
5830 fast: FastMathKind,
5611 cond: FloatCondition,5831 cond: FloatCondition,
5612 lhs: Value,5832 lhs: Value,
5613 rhs: Value,5833 rhs: Value,
5614 name: []const u8,5834 name: []const u8,
5615 ) Allocator.Error!Value {5835 ) Allocator.Error!Value {
5616 return self.cmpTag(switch (cond) {5836 return self.cmpTag(switch (fast) {
5617 inline else => |tag| @field(Instruction.Tag, "fcmp " ++ @tagName(tag)),5837 inline else => |fast_tag| switch (cond) {
5618 }, @intFromEnum(cond), lhs, rhs, name);5838 inline else => |cond_tag| @field(Instruction.Tag, "fcmp " ++ switch (fast_tag) {
5619 }5839 .normal => "",
56205840 .fast => "fast ",
5621 pub fn fcmpFast(5841 } ++ @tagName(cond_tag)),
5622 self: *WipFunction,5842 },
5623 cond: FloatCondition,
5624 lhs: Value,
5625 rhs: Value,
5626 name: []const u8,
5627 ) Allocator.Error!Value {
5628 return self.cmpTag(switch (cond) {
5629 inline else => |tag| @field(Instruction.Tag, "fcmp fast " ++ @tagName(tag)),
5630 }, @intFromEnum(cond), lhs, rhs, name);5843 }, @intFromEnum(cond), lhs, rhs, name);
5631 }5844 }
56325845
...@@ -5684,22 +5897,16 @@ pub const WipFunction = struct {...@@ -5684,22 +5897,16 @@ pub const WipFunction = struct {
56845897
5685 pub fn select(5898 pub fn select(
5686 self: *WipFunction,5899 self: *WipFunction,
5900 fast: FastMathKind,
5687 cond: Value,5901 cond: Value,
5688 lhs: Value,5902 lhs: Value,
5689 rhs: Value,5903 rhs: Value,
5690 name: []const u8,5904 name: []const u8,
5691 ) Allocator.Error!Value {5905 ) Allocator.Error!Value {
5692 return self.selectTag(.select, cond, lhs, rhs, name);5906 return self.selectTag(switch (fast) {
5693 }5907 .normal => .select,
56945908 .fast => .@"select fast",
5695 pub fn selectFast(5909 }, cond, lhs, rhs, name);
5696 self: *WipFunction,
5697 cond: Value,
5698 lhs: Value,
5699 rhs: Value,
5700 name: []const u8,
5701 ) Allocator.Error!Value {
5702 return self.selectTag(.@"select fast", cond, lhs, rhs, name);
5703 }5910 }
57045911
5705 pub fn call(5912 pub fn call(
...@@ -5774,7 +5981,7 @@ pub const WipFunction = struct {...@@ -5774,7 +5981,7 @@ pub const WipFunction = struct {
5774 else => instruction.llvmName(self),5981 else => instruction.llvmName(self),
5775 },5982 },
5776 );5983 );
5777 llvm_instruction.setInstructionCallConv(@enumFromInt(@intFromEnum(call_conv)));5984 llvm_instruction.setInstructionCallConv(call_conv.toLlvm());
5778 llvm_instruction.setTailCallKind(switch (kind) {5985 llvm_instruction.setTailCallKind(switch (kind) {
5779 .normal, .fast => .None,5986 .normal, .fast => .None,
5780 .musttail, .musttail_fast => .MustTail,5987 .musttail, .musttail_fast => .MustTail,
...@@ -5808,6 +6015,7 @@ pub const WipFunction = struct {...@@ -5808,6 +6015,7 @@ pub const WipFunction = struct {
58086015
5809 pub fn callIntrinsic(6016 pub fn callIntrinsic(
5810 self: *WipFunction,6017 self: *WipFunction,
6018 fast: FastMathKind,
5811 function_attributes: FunctionAttributes,6019 function_attributes: FunctionAttributes,
5812 id: Intrinsic,6020 id: Intrinsic,
5813 overload: []const Type,6021 overload: []const Type,
...@@ -5816,7 +6024,7 @@ pub const WipFunction = struct {...@@ -5816,7 +6024,7 @@ pub const WipFunction = struct {
5816 ) Allocator.Error!Value {6024 ) Allocator.Error!Value {
5817 const intrinsic = try self.builder.getIntrinsic(id, overload);6025 const intrinsic = try self.builder.getIntrinsic(id, overload);
5818 return self.call(6026 return self.call(
5819 .normal,6027 fast.toCallKind(),
5820 CallConv.default,6028 CallConv.default,
5821 function_attributes,6029 function_attributes,
5822 intrinsic.typeOf(self.builder),6030 intrinsic.typeOf(self.builder),
...@@ -5838,6 +6046,7 @@ pub const WipFunction = struct {...@@ -5838,6 +6046,7 @@ pub const WipFunction = struct {
5838 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};6046 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
5839 var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })};6047 var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })};
5840 const value = try self.callIntrinsic(6048 const value = try self.callIntrinsic(
6049 .normal,
5841 try self.builder.fnAttrs(&.{6050 try self.builder.fnAttrs(&.{
5842 .none,6051 .none,
5843 .none,6052 .none,
...@@ -5865,6 +6074,7 @@ pub const WipFunction = struct {...@@ -5865,6 +6074,7 @@ pub const WipFunction = struct {
5865 ) Allocator.Error!Instruction.Index {6074 ) Allocator.Error!Instruction.Index {
5866 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};6075 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
5867 const value = try self.callIntrinsic(6076 const value = try self.callIntrinsic(
6077 .normal,
5868 try self.builder.fnAttrs(&.{ .none, .none, try self.builder.attrs(&dst_attrs) }),6078 try self.builder.fnAttrs(&.{ .none, .none, try self.builder.attrs(&dst_attrs) }),
5869 .memset,6079 .memset,
5870 &.{ dst.typeOfWip(self), len.typeOfWip(self) },6080 &.{ dst.typeOfWip(self), len.typeOfWip(self) },
...@@ -6740,6 +6950,24 @@ pub const FloatCondition = enum(u4) {...@@ -6740,6 +6950,24 @@ pub const FloatCondition = enum(u4) {
6740 ult = 12,6950 ult = 12,
6741 ule = 13,6951 ule = 13,
6742 une = 14,6952 une = 14,
6953
6954 fn toLlvm(self: FloatCondition) llvm.RealPredicate {
6955 return switch (self) {
6956 .oeq => .OEQ,
6957 .ogt => .OGT,
6958 .oge => .OGE,
6959 .olt => .OLT,
6960 .ole => .OLE,
6961 .one => .ONE,
6962 .ord => .ORD,
6963 .uno => .UNO,
6964 .ueq => .UEQ,
6965 .ugt => .UGT,
6966 .uge => .UGE,
6967 .ult => .ULT,
6968 .uno => .UNE,
6969 };
6970 }
6743};6971};
67446972
6745pub const IntegerCondition = enum(u6) {6973pub const IntegerCondition = enum(u6) {
...@@ -6753,6 +6981,20 @@ pub const IntegerCondition = enum(u6) {...@@ -6753,6 +6981,20 @@ pub const IntegerCondition = enum(u6) {
6753 sge = 39,6981 sge = 39,
6754 slt = 40,6982 slt = 40,
6755 sle = 41,6983 sle = 41,
6984
6985 fn toLlvm(self: IntegerCondition) llvm.IntPredicate {
6986 return switch (self) {
6987 .eq => .EQ,
6988 .ne => .NE,
6989 .ugt => .UGT,
6990 .uge => .UGE,
6991 .ult => .ULT,
6992 .sgt => .SGT,
6993 .sge => .SGE,
6994 .slt => .SLT,
6995 .sle => .SLE,
6996 };
6997 }
6756};6998};
67576999
6758pub const MemoryAccessKind = enum(u1) {7000pub const MemoryAccessKind = enum(u1) {
...@@ -6802,6 +7044,18 @@ pub const AtomicOrdering = enum(u3) {...@@ -6802,6 +7044,18 @@ pub const AtomicOrdering = enum(u3) {
6802 ) @TypeOf(writer).Error!void {7044 ) @TypeOf(writer).Error!void {
6803 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });7045 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
6804 }7046 }
7047
7048 fn toLlvm(self: AtomicOrdering) llvm.AtomicOrdering {
7049 return switch (self) {
7050 .none => .NotAtomic,
7051 .unordered => .Unordered,
7052 .monotonic => .Monotonic,
7053 .acquire => .Acquire,
7054 .release => .Release,
7055 .acq_rel => .AcquireRelease,
7056 .seq_cst => .SequentiallyConsistent,
7057 };
7058 }
6805};7059};
68067060
6807const MemoryAccessInfo = packed struct(u32) {7061const MemoryAccessInfo = packed struct(u32) {
...@@ -6834,6 +7088,18 @@ pub const FastMath = packed struct(u32) {...@@ -6834,6 +7088,18 @@ pub const FastMath = packed struct(u32) {
6834 };7088 };
6835};7089};
68367090
7091pub const FastMathKind = enum {
7092 normal,
7093 fast,
7094
7095 pub fn toCallKind(self: FastMathKind) Function.Instruction.Call.Kind {
7096 return switch (self) {
7097 .normal => .normal,
7098 .fast => .fast,
7099 };
7100 }
7101};
7102
6837pub const Constant = enum(u32) {7103pub const Constant = enum(u32) {
6838 false,7104 false,
6839 true,7105 true,
...@@ -7247,7 +7513,7 @@ pub const Constant = enum(u32) {...@@ -7247,7 +7513,7 @@ pub const Constant = enum(u32) {
7247 }7513 }
7248 },7514 },
7249 .global => |global| switch (global.ptrConst(builder).kind) {7515 .global => |global| switch (global.ptrConst(builder).kind) {
7250 .alias => |alias| cur = alias.ptrConst(builder).init,7516 .alias => |alias| cur = alias.ptrConst(builder).aliasee,
7251 .variable, .function => return global,7517 .variable, .function => return global,
7252 .replaced => unreachable,7518 .replaced => unreachable,
7253 },7519 },
...@@ -7586,10 +7852,12 @@ pub const Constant = enum(u32) {...@@ -7586,10 +7852,12 @@ pub const Constant = enum(u32) {
75867852
7587 pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value {7853 pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value {
7588 assert(builder.useLibLlvm());7854 assert(builder.useLibLlvm());
7589 return switch (self.unwrap()) {7855 const llvm_value = switch (self.unwrap()) {
7590 .constant => |constant| builder.llvm.constants.items[constant],7856 .constant => |constant| builder.llvm.constants.items[constant],
7591 .global => |global| global.toLlvm(builder),7857 .global => |global| return global.toLlvm(builder),
7592 };7858 };
7859 const global = builder.llvm.replacements.get(llvm_value) orelse return llvm_value;
7860 return global.toLlvm(builder);
7593 }7861 }
7594};7862};
75957863
...@@ -7726,6 +7994,7 @@ pub fn init(options: Options) InitError!Builder {...@@ -7726,6 +7994,7 @@ pub fn init(options: Options) InitError!Builder {
7726 .types = .{},7994 .types = .{},
7727 .globals = .{},7995 .globals = .{},
7728 .constants = .{},7996 .constants = .{},
7997 .replacements = .{},
7729 };7998 };
7730 errdefer self.deinit();7999 errdefer self.deinit();
77318000
...@@ -7805,6 +8074,20 @@ pub fn init(options: Options) InitError!Builder {...@@ -7805,6 +8074,20 @@ pub fn init(options: Options) InitError!Builder {
7805}8074}
78068075
7807pub fn deinit(self: *Builder) void {8076pub fn deinit(self: *Builder) void {
8077 if (self.useLibLlvm()) {
8078 var replacement_it = self.llvm.replacements.keyIterator();
8079 while (replacement_it.next()) |replacement| replacement.*.deleteGlobalValue();
8080 self.llvm.replacements.deinit(self.gpa);
8081 self.llvm.constants.deinit(self.gpa);
8082 self.llvm.globals.deinit(self.gpa);
8083 self.llvm.types.deinit(self.gpa);
8084 self.llvm.attributes.deinit(self.gpa);
8085 if (self.llvm.attribute_kind_ids) |attribute_kind_ids| self.gpa.destroy(attribute_kind_ids);
8086 if (self.llvm.di_builder) |di_builder| di_builder.dispose();
8087 if (self.llvm.module) |module| module.dispose();
8088 self.llvm.context.dispose();
8089 }
8090
7808 self.module_asm.deinit(self.gpa);8091 self.module_asm.deinit(self.gpa);
78098092
7810 self.string_map.deinit(self.gpa);8093 self.string_map.deinit(self.gpa);
...@@ -7834,16 +8117,6 @@ pub fn deinit(self: *Builder) void {...@@ -7834,16 +8117,6 @@ pub fn deinit(self: *Builder) void {
7834 self.constant_extra.deinit(self.gpa);8117 self.constant_extra.deinit(self.gpa);
7835 self.constant_limbs.deinit(self.gpa);8118 self.constant_limbs.deinit(self.gpa);
78368119
7837 if (self.useLibLlvm()) {
7838 self.llvm.constants.deinit(self.gpa);
7839 self.llvm.globals.deinit(self.gpa);
7840 self.llvm.types.deinit(self.gpa);
7841 self.llvm.attributes.deinit(self.gpa);
7842 if (self.llvm.attribute_kind_ids) |attribute_kind_ids| self.gpa.destroy(attribute_kind_ids);
7843 if (self.llvm.di_builder) |di_builder| di_builder.dispose();
7844 if (self.llvm.module) |module| module.dispose();
7845 self.llvm.context.dispose();
7846 }
7847 self.* = undefined;8120 self.* = undefined;
7848}8121}
78498122
...@@ -8300,10 +8573,10 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo...@@ -8300,10 +8573,10 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo
8300 const global_gop = self.globals.getOrPutAssumeCapacity(id);8573 const global_gop = self.globals.getOrPutAssumeCapacity(id);
8301 if (!global_gop.found_existing) {8574 if (!global_gop.found_existing) {
8302 global_gop.value_ptr.* = global;8575 global_gop.value_ptr.* = global;
8303 global_gop.value_ptr.updateAttributes();8576 const global_index: Global.Index = @enumFromInt(global_gop.index);
8304 const index: Global.Index = @enumFromInt(global_gop.index);8577 global_index.updateDsoLocal(self);
8305 index.updateName(self);8578 global_index.updateName(self);
8306 return index;8579 return global_index;
8307 }8580 }
83088581
8309 const unique_gop = self.next_unique_global_id.getOrPutAssumeCapacity(name);8582 const unique_gop = self.next_unique_global_id.getOrPutAssumeCapacity(name);
...@@ -8317,21 +8590,107 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index {...@@ -8317,21 +8590,107 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index {
8317 return @enumFromInt(self.globals.getIndex(name) orelse return null);8590 return @enumFromInt(self.globals.getIndex(name) orelse return null);
8318}8591}
83198592
8320pub fn addFunction(self: *Builder, ty: Type, name: String) Allocator.Error!Function.Index {8593pub fn addAlias(
8594 self: *Builder,
8595 name: String,
8596 ty: Type,
8597 addr_space: AddrSpace,
8598 aliasee: Constant,
8599) Allocator.Error!Alias.Index {
8600 assert(!name.isAnon());
8601 try self.ensureUnusedTypeCapacity(1, NoExtra, 0);
8602 try self.ensureUnusedGlobalCapacity(name);
8603 try self.aliases.ensureUnusedCapacity(self.gpa, 1);
8604 return self.addAliasAssumeCapacity(name, ty, addr_space, aliasee);
8605}
8606
8607pub fn addAliasAssumeCapacity(
8608 self: *Builder,
8609 name: String,
8610 ty: Type,
8611 addr_space: AddrSpace,
8612 aliasee: Constant,
8613) Alias.Index {
8614 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(self.llvm.module.?.addAlias(
8615 ty.toLlvm(self),
8616 @intFromEnum(addr_space),
8617 aliasee.toLlvm(self),
8618 name.slice(self).?,
8619 ));
8620 const alias_index: Alias.Index = @enumFromInt(self.aliases.items.len);
8621 self.aliases.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8622 .addr_space = addr_space,
8623 .type = ty,
8624 .kind = .{ .alias = alias_index },
8625 }), .aliasee = aliasee });
8626 return alias_index;
8627}
8628
8629pub fn addVariable(
8630 self: *Builder,
8631 name: String,
8632 ty: Type,
8633 addr_space: AddrSpace,
8634) Allocator.Error!Variable.Index {
8635 assert(!name.isAnon());
8636 try self.ensureUnusedTypeCapacity(1, NoExtra, 0);
8637 try self.ensureUnusedGlobalCapacity(name);
8638 try self.variables.ensureUnusedCapacity(self.gpa, 1);
8639 return self.addVariableAssumeCapacity(ty, name, addr_space);
8640}
8641
8642pub fn addVariableAssumeCapacity(
8643 self: *Builder,
8644 ty: Type,
8645 name: String,
8646 addr_space: AddrSpace,
8647) Variable.Index {
8648 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(
8649 self.llvm.module.?.addGlobalInAddressSpace(
8650 ty.toLlvm(self),
8651 name.slice(self).?,
8652 @intFromEnum(addr_space),
8653 ),
8654 );
8655 const variable_index: Variable.Index = @enumFromInt(self.variables.items.len);
8656 self.variables.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8657 .addr_space = addr_space,
8658 .type = ty,
8659 .kind = .{ .variable = variable_index },
8660 }) });
8661 return variable_index;
8662}
8663
8664pub fn addFunction(
8665 self: *Builder,
8666 ty: Type,
8667 name: String,
8668 addr_space: AddrSpace,
8669) Allocator.Error!Function.Index {
8321 assert(!name.isAnon());8670 assert(!name.isAnon());
8322 try self.ensureUnusedTypeCapacity(1, NoExtra, 0);8671 try self.ensureUnusedTypeCapacity(1, NoExtra, 0);
8323 try self.ensureUnusedGlobalCapacity(name);8672 try self.ensureUnusedGlobalCapacity(name);
8324 try self.functions.ensureUnusedCapacity(self.gpa, 1);8673 try self.functions.ensureUnusedCapacity(self.gpa, 1);
8325 return self.addFunctionAssumeCapacity(ty, name);8674 return self.addFunctionAssumeCapacity(ty, name, addr_space);
8326}8675}
83278676
8328pub fn addFunctionAssumeCapacity(self: *Builder, ty: Type, name: String) Function.Index {8677pub fn addFunctionAssumeCapacity(
8678 self: *Builder,
8679 ty: Type,
8680 name: String,
8681 addr_space: AddrSpace,
8682) Function.Index {
8329 assert(ty.isFunction(self));8683 assert(ty.isFunction(self));
8330 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(8684 if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(
8331 self.llvm.module.?.addFunction(name.slice(self).?, ty.toLlvm(self)),8685 self.llvm.module.?.addFunctionInAddressSpace(
8686 name.slice(self).?,
8687 ty.toLlvm(self),
8688 @intFromEnum(addr_space),
8689 ),
8332 );8690 );
8333 const function_index: Function.Index = @enumFromInt(self.functions.items.len);8691 const function_index: Function.Index = @enumFromInt(self.functions.items.len);
8334 self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{8692 self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8693 .addr_space = addr_space,
8335 .type = ty,8694 .type = ty,
8336 .kind = .{ .function = function_index },8695 .kind = .{ .function = function_index },
8337 }) });8696 }) });
...@@ -8423,12 +8782,11 @@ pub fn getIntrinsic(...@@ -8423,12 +8782,11 @@ pub fn getIntrinsic(
8423 };8782 };
8424 }8783 }
84258784
8426 const function_index =8785 const function_index = try self.addFunction(try self.fnType(switch (signature.ret_len) {
8427 try self.addFunction(try self.fnType(switch (signature.ret_len) {
8428 0 => .void,8786 0 => .void,
8429 1 => param_types[0],8787 1 => param_types[0],
8430 else => try self.structType(.normal, param_types[0..signature.ret_len]),8788 else => try self.structType(.normal, param_types[0..signature.ret_len]),
8431 }, param_types[signature.ret_len..], .normal), name);8789 }, param_types[signature.ret_len..], .normal), name, .default);
8432 function_index.ptr(self).attributes = try self.fnAttrs(function_attributes);8790 function_index.ptr(self).attributes = try self.fnAttrs(function_attributes);
8433 return function_index;8791 return function_index;
8434}8792}
...@@ -8889,6 +9247,40 @@ pub fn asmValue(...@@ -8889,6 +9247,40 @@ pub fn asmValue(
8889 return (try self.asmConst(ty, info, assembly, constraints)).toValue();9247 return (try self.asmConst(ty, info, assembly, constraints)).toValue();
8890}9248}
88919249
9250pub fn verify(self: *Builder) error{}!bool {
9251 if (self.useLibLlvm()) {
9252 var error_message: [*:0]const u8 = undefined;
9253 // verifyModule always allocs the error_message even if there is no error
9254 defer llvm.disposeMessage(error_message);
9255
9256 if (self.llvm.module.?.verify(.ReturnStatus, &error_message).toBool()) {
9257 log.err("failed verification of LLVM module:\n{s}\n", .{error_message});
9258 return false;
9259 }
9260 }
9261 return true;
9262}
9263
9264pub fn writeBitcodeToFile(self: *Builder, path: []const u8) Allocator.Error!bool {
9265 const path_z = try self.gpa.dupeZ(u8, path);
9266 defer self.gpa.free(path_z);
9267 return self.writeBitcodeToFileZ(path_z);
9268}
9269
9270pub fn writeBitcodeToFileZ(self: *Builder, path: [*:0]const u8) bool {
9271 if (self.useLibLlvm()) {
9272 const error_code = self.llvm.module.?.writeBitcodeToFile(path);
9273 if (error_code != 0) {
9274 log.err("failed dumping LLVM module to \"{s}\": {d}", .{ path, error_code });
9275 return false;
9276 }
9277 } else {
9278 log.err("writing bitcode without libllvm not implemented", .{});
9279 return false;
9280 }
9281 return true;
9282}
9283
8892pub fn dump(self: *Builder) void {9284pub fn dump(self: *Builder) void {
8893 if (self.useLibLlvm())9285 if (self.useLibLlvm())
8894 self.llvm.module.?.dump()9286 self.llvm.module.?.dump()
...@@ -8980,7 +9372,7 @@ pub fn printUnbuffered(...@@ -8980,7 +9372,7 @@ pub fn printUnbuffered(
8980 if (variable.global.getReplacement(self) != .none) continue;9372 if (variable.global.getReplacement(self) != .none) continue;
8981 const global = variable.global.ptrConst(self);9373 const global = variable.global.ptrConst(self);
8982 try writer.print(9374 try writer.print(
8983 \\{} ={}{}{}{}{}{}{ }{} {s} {%}{ }{, }9375 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }
8984 \\9376 \\
8985 , .{9377 , .{
8986 variable.global.fmt(self),9378 variable.global.fmt(self),
...@@ -10906,7 +11298,7 @@ fn icmpConstAssumeCapacity(...@@ -10906,7 +11298,7 @@ fn icmpConstAssumeCapacity(
10906 .data = self.addConstantExtraAssumeCapacity(data),11298 .data = self.addConstantExtraAssumeCapacity(data),
10907 });11299 });
10908 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(11300 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
10909 llvm.constICmp(@enumFromInt(@intFromEnum(cond)), lhs.toLlvm(self), rhs.toLlvm(self)),11301 llvm.constICmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)),
10910 );11302 );
10911 }11303 }
10912 return @enumFromInt(gop.index);11304 return @enumFromInt(gop.index);
...@@ -10943,7 +11335,7 @@ fn fcmpConstAssumeCapacity(...@@ -10943,7 +11335,7 @@ fn fcmpConstAssumeCapacity(
10943 .data = self.addConstantExtraAssumeCapacity(data),11335 .data = self.addConstantExtraAssumeCapacity(data),
10944 });11336 });
10945 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(11337 if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(
10946 llvm.constFCmp(@enumFromInt(@intFromEnum(cond)), lhs.toLlvm(self), rhs.toLlvm(self)),11338 llvm.constFCmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)),
10947 );11339 );
10948 }11340 }
10949 return @enumFromInt(gop.index);11341 return @enumFromInt(gop.index);
src/codegen/llvm/bindings.zig+10-35
...@@ -142,8 +142,14 @@ pub const Value = opaque {...@@ -142,8 +142,14 @@ pub const Value = opaque {
142 pub const setSection = LLVMSetSection;142 pub const setSection = LLVMSetSection;
143 extern fn LLVMSetSection(Global: *Value, Section: [*:0]const u8) void;143 extern fn LLVMSetSection(Global: *Value, Section: [*:0]const u8) void;
144144
145 pub const deleteGlobal = LLVMDeleteGlobal;145 pub const removeGlobalValue = ZigLLVMRemoveGlobalValue;
146 extern fn LLVMDeleteGlobal(GlobalVar: *Value) void;146 extern fn ZigLLVMRemoveGlobalValue(GlobalVal: *Value) void;
147
148 pub const eraseGlobalValue = ZigLLVMEraseGlobalValue;
149 extern fn ZigLLVMEraseGlobalValue(GlobalVal: *Value) void;
150
151 pub const deleteGlobalValue = ZigLLVMDeleteGlobalValue;
152 extern fn ZigLLVMDeleteGlobalValue(GlobalVal: *Value) void;
147153
148 pub const setAliasee = LLVMAliasSetAliasee;154 pub const setAliasee = LLVMAliasSetAliasee;
149 extern fn LLVMAliasSetAliasee(Alias: *Value, Aliasee: *Value) void;155 extern fn LLVMAliasSetAliasee(Alias: *Value, Aliasee: *Value) void;
...@@ -292,20 +298,14 @@ pub const Value = opaque {...@@ -292,20 +298,14 @@ pub const Value = opaque {
292 pub const setValueName = LLVMSetValueName2;298 pub const setValueName = LLVMSetValueName2;
293 extern fn LLVMSetValueName2(Val: *Value, Name: [*]const u8, NameLen: usize) void;299 extern fn LLVMSetValueName2(Val: *Value, Name: [*]const u8, NameLen: usize) void;
294300
295 pub const getValueName = LLVMGetValueName;
296 extern fn LLVMGetValueName(Val: *Value) [*:0]const u8;
297
298 pub const takeName = ZigLLVMTakeName;301 pub const takeName = ZigLLVMTakeName;
299 extern fn ZigLLVMTakeName(new_owner: *Value, victim: *Value) void;302 extern fn ZigLLVMTakeName(new_owner: *Value, victim: *Value) void;
300303
301 pub const deleteFunction = LLVMDeleteFunction;
302 extern fn LLVMDeleteFunction(Fn: *Value) void;
303
304 pub const getParam = LLVMGetParam;304 pub const getParam = LLVMGetParam;
305 extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;305 extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
306306
307 pub const setInitializer = LLVMSetInitializer;307 pub const setInitializer = ZigLLVMSetInitializer;
308 extern fn LLVMSetInitializer(GlobalVar: *Value, ConstantVal: *Value) void;308 extern fn ZigLLVMSetInitializer(GlobalVar: *Value, ConstantVal: ?*Value) void;
309309
310 pub const setDLLStorageClass = LLVMSetDLLStorageClass;310 pub const setDLLStorageClass = LLVMSetDLLStorageClass;
311 extern fn LLVMSetDLLStorageClass(Global: *Value, Class: DLLStorageClass) void;311 extern fn LLVMSetDLLStorageClass(Global: *Value, Class: DLLStorageClass) void;
...@@ -316,15 +316,6 @@ pub const Value = opaque {...@@ -316,15 +316,6 @@ pub const Value = opaque {
316 pub const replaceAllUsesWith = LLVMReplaceAllUsesWith;316 pub const replaceAllUsesWith = LLVMReplaceAllUsesWith;
317 extern fn LLVMReplaceAllUsesWith(OldVal: *Value, NewVal: *Value) void;317 extern fn LLVMReplaceAllUsesWith(OldVal: *Value, NewVal: *Value) void;
318318
319 pub const getLinkage = LLVMGetLinkage;
320 extern fn LLVMGetLinkage(Global: *Value) Linkage;
321
322 pub const getUnnamedAddress = LLVMGetUnnamedAddress;
323 extern fn LLVMGetUnnamedAddress(Global: *Value) Bool;
324
325 pub const getAlignment = LLVMGetAlignment;
326 extern fn LLVMGetAlignment(V: *Value) c_uint;
327
328 pub const attachMetaData = ZigLLVMAttachMetaData;319 pub const attachMetaData = ZigLLVMAttachMetaData;
329 extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void;320 extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void;
330321
...@@ -423,18 +414,12 @@ pub const Module = opaque {...@@ -423,18 +414,12 @@ pub const Module = opaque {
423 pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel;414 pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel;
424 extern fn ZigLLVMSetModuleCodeModel(module: *Module, code_model: CodeModel) void;415 extern fn ZigLLVMSetModuleCodeModel(module: *Module, code_model: CodeModel) void;
425416
426 pub const addFunction = LLVMAddFunction;
427 extern fn LLVMAddFunction(*Module, Name: [*:0]const u8, FunctionTy: *Type) *Value;
428
429 pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace;417 pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace;
430 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;
431419
432 pub const printToString = LLVMPrintModuleToString;420 pub const printToString = LLVMPrintModuleToString;
433 extern fn LLVMPrintModuleToString(*Module) [*:0]const u8;421 extern fn LLVMPrintModuleToString(*Module) [*:0]const u8;
434422
435 pub const addGlobal = LLVMAddGlobal;
436 extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*:0]const u8) *Value;
437
438 pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace;423 pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace;
439 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;
440425
...@@ -450,16 +435,6 @@ pub const Module = opaque {...@@ -450,16 +435,6 @@ pub const Module = opaque {
450 Name: [*:0]const u8,435 Name: [*:0]const u8,
451 ) *Value;436 ) *Value;
452437
453 pub const getNamedGlobalAlias = LLVMGetNamedGlobalAlias;
454 extern fn LLVMGetNamedGlobalAlias(
455 M: *Module,
456 /// Empirically, LLVM will call strlen() on `Name` and so it
457 /// must be both null terminated and also have `NameLen` set
458 /// to the size.
459 Name: [*:0]const u8,
460 NameLen: usize,
461 ) ?*Value;
462
463 pub const setTarget = LLVMSetTarget;438 pub const setTarget = LLVMSetTarget;
464 extern fn LLVMSetTarget(M: *Module, Triple: [*:0]const u8) void;439 extern fn LLVMSetTarget(M: *Module, Triple: [*:0]const u8) void;
465440
src/zig_llvm.cpp+16
...@@ -1122,6 +1122,22 @@ void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) {...@@ -1122,6 +1122,22 @@ void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) {
1122 unwrap(new_owner)->takeName(unwrap(victim));1122 unwrap(new_owner)->takeName(unwrap(victim));
1123}1123}
11241124
1125void ZigLLVMRemoveGlobalValue(LLVMValueRef GlobalVal) {
1126 unwrap<GlobalValue>(GlobalVal)->removeFromParent();
1127}
1128
1129void ZigLLVMEraseGlobalValue(LLVMValueRef GlobalVal) {
1130 unwrap<GlobalValue>(GlobalVal)->eraseFromParent();
1131}
1132
1133void ZigLLVMDeleteGlobalValue(LLVMValueRef GlobalVal) {
1134 delete unwrap<GlobalVariable>(GlobalVal);
1135}
1136
1137void ZigLLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal) {
1138 unwrap<GlobalVariable>(GlobalVar)->setInitializer(ConstantVal ? unwrap<Constant>(ConstantVal) : nullptr);
1139}
1140
1125ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {1141ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
1126 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());1142 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
1127}1143}
src/zig_llvm.h+4
...@@ -492,6 +492,10 @@ enum ZigLLVM_ObjectFormatType {...@@ -492,6 +492,10 @@ enum ZigLLVM_ObjectFormatType {
492};492};
493493
494ZIG_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);
495499
496#define ZigLLVM_DIFlags_Zero 0U500#define ZigLLVM_DIFlags_Zero 0U
497#define ZigLLVM_DIFlags_Private 1U501#define ZigLLVM_DIFlags_Private 1U