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 {
764764 builder: Builder,
765765
766766 module: *Module,
767 llvm_module: *llvm.Module,
768767 di_builder: ?*llvm.DIBuilder,
769768 /// One of these mappings:
770769 /// - *Module.File => *DIFile
......@@ -945,9 +944,8 @@ pub const Object = struct {
945944 .gpa = gpa,
946945 .builder = builder,
947946 .module = options.module.?,
948 .llvm_module = builder.llvm.module.?,
949947 .di_map = .{},
950 .di_builder = builder.llvm.di_builder,
948 .di_builder = if (builder.useLibLlvm()) builder.llvm.di_builder else null, // TODO
951949 .di_compile_unit = builder.llvm.di_compile_unit,
952950 .target_machine = target_machine,
953951 .target_data = target_data,
......@@ -991,9 +989,8 @@ pub const Object = struct {
991989 }
992990
993991 fn genErrorNameTable(o: *Object) Allocator.Error!void {
994 // If o.error_name_table is null, there was no instruction that actually referenced the error table.
995 const error_name_table_ptr_global = o.error_name_table;
996 if (error_name_table_ptr_global == .none) return;
992 // If o.error_name_table is null, then it was not referenced by any instructions.
993 if (o.error_name_table == .none) return;
997994
998995 const mod = o.module;
999996
......@@ -1003,72 +1000,42 @@ pub const Object = struct {
10031000
10041001 // TODO: Address space
10051002 const slice_ty = Type.slice_const_u8_sentinel_0;
1006 const slice_alignment = slice_ty.abiAlignment(mod);
10071003 const llvm_usize_ty = try o.lowerType(Type.usize);
10081004 const llvm_slice_ty = try o.lowerType(slice_ty);
10091005 const llvm_table_ty = try o.builder.arrayType(error_name_list.len, llvm_slice_ty);
10101006
10111007 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
1012 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name_nts| {
1013 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_nts));
1014 const str_init = try o.builder.stringNullConst(name);
1015 const str_ty = str_init.typeOf(&o.builder);
1016 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");
1017 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));
1018 str_llvm_global.setLinkage(.Private);
1019 str_llvm_global.setGlobalConstant(.True);
1020 str_llvm_global.setUnnamedAddr(.True);
1021 str_llvm_global.setAlignment(1);
1022
1023 var str_global = Builder.Global{
1024 .linkage = .private,
1025 .unnamed_addr = .unnamed_addr,
1026 .type = str_ty,
1027 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
1028 };
1029 var str_variable = Builder.Variable{
1030 .global = @enumFromInt(o.builder.globals.count()),
1031 .mutability = .constant,
1032 .init = str_init,
1033 .alignment = comptime Builder.Alignment.fromByteUnits(1),
1034 };
1035 try o.builder.llvm.globals.append(o.gpa, str_llvm_global);
1036 const global_index = try o.builder.addGlobal(.empty, str_global);
1037 try o.builder.variables.append(o.gpa, str_variable);
1008 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {
1009 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
1010 const name_init = try o.builder.stringNullConst(name_string);
1011 const name_variable_index =
1012 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
1013 try name_variable_index.setInitializer(name_init, &o.builder);
1014 name_variable_index.setLinkage(.private, &o.builder);
1015 name_variable_index.setMutability(.constant, &o.builder);
1016 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
1017 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
10381018
10391019 llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
1040 global_index.toConst(),
1041 try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len),
1020 name_variable_index.toConst(&o.builder),
1021 try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len),
10421022 });
10431023 }
10441024
1045 const error_name_table_init = try o.builder.arrayConst(llvm_table_ty, llvm_errors);
1046 const error_name_table_global = o.llvm_module.addGlobal(llvm_table_ty.toLlvm(&o.builder), "");
1047 error_name_table_global.setInitializer(error_name_table_init.toLlvm(&o.builder));
1048 error_name_table_global.setLinkage(.Private);
1049 error_name_table_global.setGlobalConstant(.True);
1050 error_name_table_global.setUnnamedAddr(.True);
1051 error_name_table_global.setAlignment(slice_alignment); // TODO: Dont hardcode
1052
1053 var global = Builder.Global{
1054 .linkage = .private,
1055 .unnamed_addr = .unnamed_addr,
1056 .type = llvm_table_ty,
1057 .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) },
1058 };
1059 var variable = Builder.Variable{
1060 .global = @enumFromInt(o.builder.globals.count()),
1061 .mutability = .constant,
1062 .init = error_name_table_init,
1063 .alignment = Builder.Alignment.fromByteUnits(slice_alignment),
1064 };
1065 try o.builder.llvm.globals.append(o.gpa, error_name_table_global);
1066 _ = try o.builder.addGlobal(.empty, global);
1067 try o.builder.variables.append(o.gpa, variable);
1025 const table_variable_index = try o.builder.addVariable(.empty, llvm_table_ty, .default);
1026 try table_variable_index.setInitializer(
1027 try o.builder.arrayConst(llvm_table_ty, llvm_errors),
1028 &o.builder,
1029 );
1030 table_variable_index.setLinkage(.private, &o.builder);
1031 table_variable_index.setMutability(.constant, &o.builder);
1032 table_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
1033 table_variable_index.setAlignment(
1034 Builder.Alignment.fromByteUnits(slice_ty.abiAlignment(mod)),
1035 &o.builder,
1036 );
10681037
1069 const error_name_table_ptr = error_name_table_global;
1070 error_name_table_ptr_global.ptr(&o.builder).init = variable.global.toConst();
1071 error_name_table_ptr_global.toLlvm(&o.builder).setInitializer(error_name_table_ptr);
1038 try o.error_name_table.setInitializer(table_variable_index.toConst(&o.builder), &o.builder);
10721039 }
10731040
10741041 fn genCmpLtErrorsLenFunction(o: *Object) !void {
......@@ -1181,17 +1148,7 @@ pub const Object = struct {
11811148 }
11821149 }
11831150
1184 if (comp.verbose_llvm_bc) |path| {
1185 const path_z = try comp.gpa.dupeZ(u8, path);
1186 defer comp.gpa.free(path_z);
1187
1188 const error_code = self.llvm_module.writeBitcodeToFile(path_z);
1189 if (error_code != 0) {
1190 log.err("dump LLVM module failed bc={s}: {d}", .{
1191 path, error_code,
1192 });
1193 }
1194 }
1151 if (comp.verbose_llvm_bc) |path| _ = try self.builder.writeBitcodeToFile(path);
11951152
11961153 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
11971154 defer arena_allocator.deinit();
......@@ -1200,20 +1157,10 @@ pub const Object = struct {
12001157 const mod = comp.bin_file.options.module.?;
12011158 const cache_dir = mod.zig_cache_artifact_directory;
12021159
1203 if (std.debug.runtime_safety) {
1204 var error_message: [*:0]const u8 = undefined;
1205 // verifyModule always allocs the error_message even if there is no error
1206 defer llvm.disposeMessage(error_message);
1207
1208 if (self.llvm_module.verify(.ReturnStatus, &error_message).toBool()) {
1209 std.debug.print("\n{s}\n", .{error_message});
1210
1211 if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| {
1212 _ = self.llvm_module.printModuleToFile(emit_llvm_ir_path, &error_message);
1213 }
1214
1215 @panic("LLVM module verification failed");
1216 }
1160 if (std.debug.runtime_safety and !try self.builder.verify()) {
1161 if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path|
1162 _ = self.builder.printToFileZ(emit_llvm_ir_path);
1163 @panic("LLVM module verification failed");
12171164 }
12181165
12191166 var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|
......@@ -1233,12 +1180,17 @@ pub const Object = struct {
12331180 emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,
12341181 });
12351182
1183 if (!self.builder.useLibLlvm()) {
1184 log.err("emitting without libllvm not implemented", .{});
1185 return error.FailedToEmit;
1186 }
1187
12361188 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
12371189 // So we call the entire pipeline multiple times if this is requested.
12381190 var error_message: [*:0]const u8 = undefined;
12391191 if (emit_asm_path != null and emit_bin_path != null) {
12401192 if (self.target_machine.emitToFile(
1241 self.llvm_module,
1193 self.builder.llvm.module.?,
12421194 &error_message,
12431195 comp.bin_file.options.optimize_mode == .Debug,
12441196 comp.bin_file.options.optimize_mode == .ReleaseSmall,
......@@ -1262,7 +1214,7 @@ pub const Object = struct {
12621214 }
12631215
12641216 if (self.target_machine.emitToFile(
1265 self.llvm_module,
1217 self.builder.llvm.module.?,
12661218 &error_message,
12671219 comp.bin_file.options.optimize_mode == .Debug,
12681220 comp.bin_file.options.optimize_mode == .ReleaseSmall,
......@@ -1305,11 +1257,9 @@ pub const Object = struct {
13051257 .err_msg = null,
13061258 };
13071259
1308 const function = try o.resolveLlvmFunction(decl_index);
1309 const global = function.ptrConst(&o.builder).global;
1310 const llvm_func = global.toLlvm(&o.builder);
1260 const function_index = try o.resolveLlvmFunction(decl_index);
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);
13131263 defer attributes.deinit(&o.builder);
13141264
13151265 if (func.analysis(ip).is_noinline) {
......@@ -1354,17 +1304,14 @@ pub const Object = struct {
13541304 } }, &o.builder);
13551305 }
13561306
1357 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| {
1358 function.ptr(&o.builder).section = try o.builder.string(section);
1359 llvm_func.setSection(section);
1360 }
1307 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
1308 function_index.setSection(try o.builder.string(section), &o.builder);
13611309
13621310 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);
13641312 defer if (deinit_wip) wip.deinit();
13651313 wip.cursor = .{ .block = try wip.block(0, "Entry") };
13661314
1367 const builder = wip.llvm.builder;
13681315 var llvm_arg_i: u32 = 0;
13691316
13701317 // This gets the LLVM values from the function and stores them in `dg.args`.
......@@ -1566,7 +1513,7 @@ pub const Object = struct {
15661513 }
15671514 }
15681515
1569 function.setAttributes(try attributes.finish(&o.builder), &o.builder);
1516 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
15701517
15711518 var di_file: ?*llvm.DIFile = null;
15721519 var di_scope: ?*llvm.DIScope = null;
......@@ -1585,7 +1532,7 @@ pub const Object = struct {
15851532 const subprogram = dib.createFunction(
15861533 di_file.?.toScope(),
15871534 ip.stringToSlice(decl.name),
1588 llvm_func.getValueName(),
1535 function_index.name(&o.builder).slice(&o.builder).?,
15891536 di_file.?,
15901537 line_number,
15911538 decl_di_ty,
......@@ -1598,7 +1545,7 @@ pub const Object = struct {
15981545 );
15991546 try o.di_map.put(gpa, decl, subprogram.toNode());
16001547
1601 llvm_func.fnSetSubprogram(subprogram);
1548 function_index.toLlvm(&o.builder).fnSetSubprogram(subprogram);
16021549
16031550 di_scope = subprogram.toScope();
16041551 }
......@@ -1609,7 +1556,6 @@ pub const Object = struct {
16091556 .liveness = liveness,
16101557 .dg = &dg,
16111558 .wip = wip,
1612 .builder = builder,
16131559 .ret_ptr = ret_ptr,
16141560 .args = args.items,
16151561 .arg_index = 0,
......@@ -1670,8 +1616,7 @@ pub const Object = struct {
16701616 const gpa = mod.gpa;
16711617 // If the module does not already have the function, we ignore this function call
16721618 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
1673 const global = self.decl_map.get(decl_index) orelse return;
1674 const llvm_global = global.toLlvm(&self.builder);
1619 const global_index = self.decl_map.get(decl_index) orelse return;
16751620 const decl = mod.declPtr(decl_index);
16761621 if (decl.isExtern(mod)) {
16771622 const decl_name = decl_name: {
......@@ -1689,114 +1634,91 @@ pub const Object = struct {
16891634 };
16901635
16911636 if (self.builder.getGlobal(decl_name)) |other_global| {
1692 if (other_global.toLlvm(&self.builder) != llvm_global) {
1637 if (other_global != global_index) {
16931638 try self.extern_collisions.put(gpa, decl_index, {});
16941639 }
16951640 }
16961641
1697 try global.rename(decl_name, &self.builder);
1698 global.ptr(&self.builder).unnamed_addr = .default;
1699 llvm_global.setUnnamedAddr(.False);
1700 global.ptr(&self.builder).linkage = .external;
1701 llvm_global.setLinkage(.External);
1702 if (mod.wantDllExports()) {
1703 global.ptr(&self.builder).dll_storage_class = .default;
1704 llvm_global.setDLLStorageClass(.Default);
1705 }
1642 try global_index.rename(decl_name, &self.builder);
1643 global_index.setLinkage(.external, &self.builder);
1644 global_index.setUnnamedAddr(.default, &self.builder);
1645 if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder);
17061646 if (self.di_map.get(decl)) |di_node| {
17071647 const decl_name_slice = decl_name.slice(&self.builder).?;
17081648 if (try decl.isFunction(mod)) {
17091649 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 );
17111655 di_func.replaceLinkageName(linkage_name);
17121656 } else {
17131657 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 );
17151663 di_global.replaceLinkageName(linkage_name);
17161664 }
17171665 }
17181666 if (decl.val.getVariable(mod)) |decl_var| {
1719 if (decl_var.is_threadlocal) {
1720 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1721 .generaldynamic;
1722 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1723 } else {
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 }
1667 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1668 if (decl_var.is_threadlocal) .generaldynamic else .default,
1669 &self.builder,
1670 );
1671 if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder);
17321672 }
1733 global.ptr(&self.builder).updateAttributes();
17341673 } else if (exports.len != 0) {
1735 const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exports[0].opts.name));
1736 try global.rename(exp_name, &self.builder);
1737 global.ptr(&self.builder).unnamed_addr = .default;
1738 llvm_global.setUnnamedAddr(.False);
1739 if (mod.wantDllExports()) {
1740 global.ptr(&self.builder).dll_storage_class = .dllexport;
1741 llvm_global.setDLLStorageClass(.DLLExport);
1742 }
1674 const main_exp_name = try self.builder.string(
1675 mod.intern_pool.stringToSlice(exports[0].opts.name),
1676 );
1677 try global_index.rename(main_exp_name, &self.builder);
1678 global_index.setUnnamedAddr(.default, &self.builder);
1679 if (mod.wantDllExports()) global_index.setDllStorageClass(.dllexport, &self.builder);
17431680 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).?;
17451682 if (try decl.isFunction(mod)) {
17461683 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 );
17481689 di_func.replaceLinkageName(linkage_name);
17491690 } else {
17501691 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 );
17521697 di_global.replaceLinkageName(linkage_name);
17531698 }
17541699 }
1755 switch (exports[0].opts.linkage) {
1700 global_index.setLinkage(switch (exports[0].opts.linkage) {
17561701 .Internal => unreachable,
1757 .Strong => {
1758 global.ptr(&self.builder).linkage = .external;
1759 llvm_global.setLinkage(.External);
1760 },
1761 .Weak => {
1762 global.ptr(&self.builder).linkage = .weak_odr;
1763 llvm_global.setLinkage(.WeakODR);
1764 },
1765 .LinkOnce => {
1766 global.ptr(&self.builder).linkage = .linkonce_odr;
1767 llvm_global.setLinkage(.LinkOnceODR);
1768 },
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 =
1702 .Strong => .external,
1703 .Weak => .weak_odr,
1704 .LinkOnce => .linkonce_odr,
1705 }, &self.builder);
1706 global_index.setVisibility(switch (exports[0].opts.visibility) {
1707 .default => .default,
1708 .hidden => .hidden,
1709 .protected => .protected,
1710 }, &self.builder);
1711 if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section|
1712 switch (global_index.ptrConst(&self.builder).kind) {
1713 inline .variable, .function => |impl_index| impl_index.setSection(
17871714 try self.builder.string(section),
1715 &self.builder,
1716 ),
17881717 else => unreachable,
1789 }
1790 llvm_global.setSection(section);
1791 }
1792 if (decl.val.getVariable(mod)) |decl_var| {
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();
1718 };
1719 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
1720 global_index.ptrConst(&self.builder).kind
1721 .variable.setThreadLocal(.generaldynamic, &self.builder);
18001722
18011723 // If a Decl is exported more than one time (which is rare),
18021724 // we add aliases for all but the first export.
......@@ -1805,49 +1727,47 @@ pub const Object = struct {
18051727 // Until then we iterate over existing aliases and make them point
18061728 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.
18071729 for (exports[1..]) |exp| {
1808 const exp_name_z = mod.intern_pool.stringToSlice(exp.opts.name);
1809
1810 if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| {
1811 alias.setAliasee(llvm_global);
1812 } else {
1813 _ = self.llvm_module.addAlias(
1814 global.ptrConst(&self.builder).type.toLlvm(&self.builder),
1815 0,
1816 llvm_global,
1817 exp_name_z,
1818 );
1730 const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exp.opts.name));
1731 if (self.builder.getGlobal(exp_name)) |global| {
1732 switch (global.ptrConst(&self.builder).kind) {
1733 .alias => |alias| {
1734 alias.setAliasee(global_index.toConst(), &self.builder);
1735 continue;
1736 },
1737 .variable, .function => {},
1738 else => unreachable,
1739 }
18191740 }
1741 _ = try self.builder.addAlias(
1742 exp_name,
1743 global_index.typeOf(&self.builder),
1744 .default,
1745 global_index.toConst(),
1746 );
18201747 }
18211748 } else {
1822 const fqn = try self.builder.string(mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)));
1823 try global.rename(fqn, &self.builder);
1824 global.ptr(&self.builder).linkage = .internal;
1825 llvm_global.setLinkage(.Internal);
1826 if (mod.wantDllExports()) {
1827 global.ptr(&self.builder).dll_storage_class = .default;
1828 llvm_global.setDLLStorageClass(.Default);
1829 }
1830 global.ptr(&self.builder).unnamed_addr = .unnamed_addr;
1831 llvm_global.setUnnamedAddr(.True);
1749 const fqn = try self.builder.string(
1750 mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)),
1751 );
1752 try global_index.rename(fqn, &self.builder);
1753 global_index.setLinkage(.internal, &self.builder);
1754 if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder);
1755 global_index.setUnnamedAddr(.unnamed_addr, &self.builder);
18321756 if (decl.val.getVariable(mod)) |decl_var| {
1833 const single_threaded = mod.comp.bin_file.options.single_threaded;
1834 if (decl_var.is_threadlocal and !single_threaded) {
1835 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1836 .generaldynamic;
1837 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
1838 } else {
1839 global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local =
1840 .default;
1841 llvm_global.setThreadLocalMode(.NotThreadLocal);
1842 }
1757 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1758 if (decl_var.is_threadlocal and !mod.comp.bin_file.options.single_threaded)
1759 .generaldynamic
1760 else
1761 .default,
1762 &self.builder,
1763 );
18431764 }
1844 global.ptr(&self.builder).updateAttributes();
18451765 }
18461766 }
18471767
18481768 pub fn freeDecl(self: *Object, decl_index: Module.Decl.Index) void {
18491769 const global = self.decl_map.get(decl_index) orelse return;
1850 global.toLlvm(&self.builder).deleteGlobal();
1770 global.delete(&self.builder);
18511771 }
18521772
18531773 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {
......@@ -2883,8 +2803,12 @@ pub const Object = struct {
28832803 /// If the llvm function does not exist, create it.
28842804 /// Note that this can be called before the function's semantic analysis has
28852805 /// 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 {
28872810 const mod = o.module;
2811 const ip = &mod.intern_pool;
28882812 const gpa = o.gpa;
28892813 const decl = mod.declPtr(decl_index);
28902814 const zig_fn_type = decl.ty;
......@@ -2896,31 +2820,20 @@ pub const Object = struct {
28962820 const target = mod.getTarget();
28972821 const sret = firstParamSRet(fn_info, mod);
28982822
2899 const fn_type = try o.lowerType(zig_fn_type);
2900
2901 const ip = &mod.intern_pool;
2902 const fqn = try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod)));
2903
2904 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
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 };
2823 const function_index = try o.builder.addFunction(
2824 try o.lowerType(zig_fn_type),
2825 try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))),
2826 toLlvmAddressSpace(decl.@"addrspace", target),
2827 );
2828 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
29142829
29152830 var attributes: Builder.FunctionAttributes.Wip = .{};
29162831 defer attributes.deinit(&o.builder);
29172832
29182833 const is_extern = decl.isExtern(mod);
29192834 if (!is_extern) {
2920 global.linkage = .internal;
2921 llvm_fn.setLinkage(.Internal);
2922 global.unnamed_addr = .unnamed_addr;
2923 llvm_fn.setUnnamedAddr(.True);
2835 function_index.setLinkage(.internal, &o.builder);
2836 function_index.setUnnamedAddr(.unnamed_addr, &o.builder);
29242837 } else {
29252838 if (target.isWasm()) {
29262839 try attributes.addFnAttr(.{ .string = .{
......@@ -2957,35 +2870,22 @@ pub const Object = struct {
29572870 }
29582871
29592872 switch (fn_info.cc) {
2960 .Unspecified, .Inline => {
2961 function.call_conv = .fastcc;
2962 llvm_fn.setFunctionCallConv(.Fast);
2963 },
2964 .Naked => {
2965 try attributes.addFnAttr(.naked, &o.builder);
2966 },
2873 .Unspecified, .Inline => function_index.setCallConv(.fastcc, &o.builder),
2874 .Naked => try attributes.addFnAttr(.naked, &o.builder),
29672875 .Async => {
2968 function.call_conv = .fastcc;
2969 llvm_fn.setFunctionCallConv(.Fast);
2876 function_index.setCallConv(.fastcc, &o.builder);
29702877 @panic("TODO: LLVM backend lower async function");
29712878 },
2972 else => {
2973 function.call_conv = toLlvmCallConv(fn_info.cc, target);
2974 llvm_fn.setFunctionCallConv(@enumFromInt(@intFromEnum(function.call_conv)));
2975 },
2879 else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),
29762880 }
29772881
2978 if (fn_info.alignment.toByteUnitsOptional()) |a| {
2979 function.alignment = Builder.Alignment.fromByteUnits(a);
2980 llvm_fn.setAlignment(@intCast(a));
2981 }
2882 if (fn_info.alignment.toByteUnitsOptional()) |alignment|
2883 function_index.setAlignment(Builder.Alignment.fromByteUnits(alignment), &o.builder);
29822884
29832885 // Function attributes that are independent of analysis results of the function body.
29842886 try o.addCommonFnAttributes(&attributes);
29852887
2986 if (fn_info.return_type == .noreturn_type) {
2987 try attributes.addFnAttr(.noreturn, &o.builder);
2988 }
2888 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
29892889
29902890 // Add parameter attributes. We handle only the case of extern functions (no body)
29912891 // because functions with bodies are handled in `updateFunc`.
......@@ -3007,9 +2907,7 @@ pub const Object = struct {
30072907 Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod));
30082908 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
30092909 },
3010 .byref_mut => {
3011 try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder);
3012 },
2910 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
30132911 // No attributes needed for these.
30142912 .no_bits,
30152913 .abi_sized_int,
......@@ -3025,11 +2923,8 @@ pub const Object = struct {
30252923 };
30262924 }
30272925
3028 try o.builder.llvm.globals.append(o.gpa, llvm_fn);
3029 gop.value_ptr.* = try o.builder.addGlobal(fqn, global);
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;
2926 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
2927 return function_index;
30332928 }
30342929
30352930 fn addCommonFnAttributes(
......@@ -3093,76 +2988,50 @@ pub const Object = struct {
30932988 }
30942989 }
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 {
30972995 const gop = try o.decl_map.getOrPut(o.gpa, decl_index);
30982996 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;
30992997 errdefer assert(o.decl_map.remove(decl_index));
31002998
31012999 const mod = o.module;
31023000 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
31183001 const is_extern = decl.isExtern(mod);
3119 const name = if (is_extern)
3120 try o.builder.string(mod.intern_pool.stringToSlice(decl.name))
3121 else
3122 fqn;
3123 const llvm_global = o.llvm_module.addGlobalInAddressSpace(
3124 global.type.toLlvm(&o.builder),
3125 fqn.slice(&o.builder).?,
3126 @intFromEnum(global.addr_space),
3002
3003 const variable_index = try o.builder.addVariable(
3004 try o.builder.string(mod.intern_pool.stringToSlice(
3005 if (is_extern) decl.name else try decl.getFullyQualifiedName(mod),
3006 )),
3007 try o.lowerType(decl.ty),
3008 toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()),
31273009 );
3010 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
31283011
31293012 // This is needed for declarations created by `@extern`.
31303013 if (is_extern) {
3131 global.unnamed_addr = .default;
3132 llvm_global.setUnnamedAddr(.False);
3133 global.linkage = .external;
3134 llvm_global.setLinkage(.External);
3014 variable_index.setLinkage(.external, &o.builder);
3015 variable_index.setUnnamedAddr(.default, &o.builder);
31353016 if (decl.val.getVariable(mod)) |decl_var| {
31363017 const single_threaded = mod.comp.bin_file.options.single_threaded;
3137 if (decl_var.is_threadlocal and !single_threaded) {
3138 variable.thread_local = .generaldynamic;
3139 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
3140 } else {
3141 variable.thread_local = .default;
3142 llvm_global.setThreadLocalMode(.NotThreadLocal);
3143 }
3144 if (decl_var.is_weak_linkage) {
3145 global.linkage = .extern_weak;
3146 llvm_global.setLinkage(.ExternalWeak);
3147 }
3018 variable_index.setThreadLocal(
3019 if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default,
3020 &o.builder,
3021 );
3022 if (decl_var.is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder);
31483023 }
31493024 } else {
3150 global.linkage = .internal;
3151 llvm_global.setLinkage(.Internal);
3152 global.unnamed_addr = .unnamed_addr;
3153 llvm_global.setUnnamedAddr(.True);
3025 variable_index.setLinkage(.internal, &o.builder);
3026 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
31543027 }
3155
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;
3028 return variable_index;
31603029 }
31613030
31623031 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
31633032 const ty = try o.lowerTypeInner(t);
31643033 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: {
31663035 const llvm_ty = ty.toLlvm(&o.builder);
31673036 if (t.zigTypeTag(mod) == .Opaque) break :check;
31683037 if (!t.hasRuntimeBits(mod)) break :check;
......@@ -4533,65 +4402,22 @@ pub const DeclGen = struct {
45334402 if (decl.val.getExternFunc(mod)) |extern_func| {
45344403 _ = try o.resolveLlvmFunction(extern_func.decl);
45354404 } else {
4536 const target = mod.getTarget();
4537 const variable = try o.resolveGlobalDecl(decl_index);
4538 const global = variable.ptrConst(&o.builder).global;
4539 var llvm_global = global.toLlvm(&o.builder);
4540 variable.ptr(&o.builder).alignment = Builder.Alignment.fromByteUnits(decl.getAlignment(mod));
4541 llvm_global.setAlignment(decl.getAlignment(mod));
4542 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| {
4543 variable.ptr(&o.builder).section = try o.builder.string(section);
4544 llvm_global.setSection(section);
4545 }
4405 const variable_index = try o.resolveGlobalDecl(decl_index);
4406 variable_index.setAlignment(
4407 Builder.Alignment.fromByteUnits(decl.getAlignment(mod)),
4408 &o.builder,
4409 );
4410 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
4411 variable_index.setSection(try o.builder.string(section), &o.builder);
45464412 assert(decl.has_tv);
45474413 const init_val = if (decl.val.getVariable(mod)) |decl_var| decl_var.init else init_val: {
4548 variable.ptr(&o.builder).mutability = .constant;
4549 llvm_global.setGlobalConstant(.True);
4414 variable_index.setMutability(.constant, &o.builder);
45504415 break :init_val decl.val.toIntern();
45514416 };
4552 if (init_val != .none) {
4553 const llvm_init = try o.lowerValue(init_val);
4554 const llvm_init_ty = llvm_init.typeOf(&o.builder);
4555 if (global.ptrConst(&o.builder).type == llvm_init_ty) {
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 }
4417 try variable_index.setInitializer(switch (init_val) {
4418 .none => .no_init,
4419 else => try o.lowerValue(init_val),
4420 }, &o.builder);
45954421
45964422 if (o.di_builder) |dib| {
45974423 const di_file = try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
......@@ -4601,7 +4427,7 @@ pub const DeclGen = struct {
46014427 const di_global = dib.createGlobalVariableExpression(
46024428 di_file.toScope(),
46034429 mod.intern_pool.stringToSlice(decl.name),
4604 llvm_global.getValueName(),
4430 variable_index.name(&o.builder).slice(&o.builder).?,
46054431 di_file,
46064432 line_number,
46074433 try o.lowerDebugType(decl.ty, .full),
......@@ -4609,7 +4435,8 @@ pub const DeclGen = struct {
46094435 );
46104436
46114437 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);
46134440 }
46144441 }
46154442 }
......@@ -4621,7 +4448,6 @@ pub const FuncGen = struct {
46214448 air: Air,
46224449 liveness: Liveness,
46234450 wip: Builder.WipFunction,
4624 builder: *llvm.Builder,
46254451 di_scope: ?*llvm.DIScope,
46264452 di_file: ?*llvm.DIFile,
46274453 base_line: u32,
......@@ -4710,38 +4536,22 @@ pub const FuncGen = struct {
47104536 // We have an LLVM value but we need to create a global constant and
47114537 // set the value as its initializer, and then return a pointer to the global.
47124538 const target = mod.getTarget();
4713 const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target);
4714 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target);
4715 const llvm_ty = llvm_val.typeOf(&o.builder);
4716 const llvm_alignment = tv.ty.abiAlignment(mod);
4717 const llvm_global = o.llvm_module.addGlobalInAddressSpace(llvm_ty.toLlvm(&o.builder), "", @intFromEnum(llvm_actual_addrspace));
4718 llvm_global.setInitializer(llvm_val.toLlvm(&o.builder));
4719 llvm_global.setLinkage(.Private);
4720 llvm_global.setGlobalConstant(.True);
4721 llvm_global.setUnnamedAddr(.True);
4722 llvm_global.setAlignment(llvm_alignment);
4723
4724 var global = Builder.Global{
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
4539 const variable_index = try o.builder.addVariable(
4540 .empty,
4541 llvm_val.typeOf(&o.builder),
4542 toLlvmGlobalAddressSpace(.generic, target),
4543 );
4544 try variable_index.setInitializer(llvm_val, &o.builder);
4545 variable_index.setLinkage(.private, &o.builder);
4546 variable_index.setMutability(.constant, &o.builder);
4547 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4548 variable_index.setAlignment(Builder.Alignment.fromByteUnits(
4549 tv.ty.abiAlignment(mod),
4550 ), &o.builder);
47414551 return o.builder.convConst(
47424552 .unneeded,
4743 global_index.toConst(),
4744 try o.builder.ptrType(llvm_wanted_addrspace),
4553 variable_index.toConst(&o.builder),
4554 try o.builder.ptrType(toLlvmAddressSpace(.generic, target)),
47454555 );
47464556 }
47474557
......@@ -4768,18 +4578,18 @@ pub const FuncGen = struct {
47684578
47694579 const val: Builder.Value = switch (air_tags[inst]) {
47704580 // zig fmt: off
4771 .add => try self.airAdd(inst, false),
4772 .add_optimized => try self.airAdd(inst, true),
4581 .add => try self.airAdd(inst, .normal),
4582 .add_optimized => try self.airAdd(inst, .fast),
47734583 .add_wrap => try self.airAddWrap(inst),
47744584 .add_sat => try self.airAddSat(inst),
47754585
4776 .sub => try self.airSub(inst, false),
4777 .sub_optimized => try self.airSub(inst, true),
4586 .sub => try self.airSub(inst, .normal),
4587 .sub_optimized => try self.airSub(inst, .fast),
47784588 .sub_wrap => try self.airSubWrap(inst),
47794589 .sub_sat => try self.airSubSat(inst),
47804590
4781 .mul => try self.airMul(inst, false),
4782 .mul_optimized => try self.airMul(inst, true),
4591 .mul => try self.airMul(inst, .normal),
4592 .mul_optimized => try self.airMul(inst, .fast),
47834593 .mul_wrap => try self.airMulWrap(inst),
47844594 .mul_sat => try self.airMulSat(inst),
47854595
......@@ -4787,12 +4597,12 @@ pub const FuncGen = struct {
47874597 .sub_safe => try self.airSafeArithmetic(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
47884598 .mul_safe => try self.airSafeArithmetic(inst, .@"smul.with.overflow", .@"umul.with.overflow"),
47894599
4790 .div_float => try self.airDivFloat(inst, false),
4791 .div_trunc => try self.airDivTrunc(inst, false),
4792 .div_floor => try self.airDivFloor(inst, false),
4793 .div_exact => try self.airDivExact(inst, false),
4794 .rem => try self.airRem(inst, false),
4795 .mod => try self.airMod(inst, false),
4600 .div_float => try self.airDivFloat(inst, .normal),
4601 .div_trunc => try self.airDivTrunc(inst, .normal),
4602 .div_floor => try self.airDivFloor(inst, .normal),
4603 .div_exact => try self.airDivExact(inst, .normal),
4604 .rem => try self.airRem(inst, .normal),
4605 .mod => try self.airMod(inst, .normal),
47964606 .ptr_add => try self.airPtrAdd(inst),
47974607 .ptr_sub => try self.airPtrSub(inst),
47984608 .shl => try self.airShl(inst),
......@@ -4803,12 +4613,12 @@ pub const FuncGen = struct {
48034613 .slice => try self.airSlice(inst),
48044614 .mul_add => try self.airMulAdd(inst),
48054615
4806 .div_float_optimized => try self.airDivFloat(inst, true),
4807 .div_trunc_optimized => try self.airDivTrunc(inst, true),
4808 .div_floor_optimized => try self.airDivFloor(inst, true),
4809 .div_exact_optimized => try self.airDivExact(inst, true),
4810 .rem_optimized => try self.airRem(inst, true),
4811 .mod_optimized => try self.airMod(inst, true),
4616 .div_float_optimized => try self.airDivFloat(inst, .fast),
4617 .div_trunc_optimized => try self.airDivTrunc(inst, .fast),
4618 .div_floor_optimized => try self.airDivFloor(inst, .fast),
4619 .div_exact_optimized => try self.airDivExact(inst, .fast),
4620 .rem_optimized => try self.airRem(inst, .fast),
4621 .mod_optimized => try self.airMod(inst, .fast),
48124622
48134623 .add_with_overflow => try self.airOverflow(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"),
48144624 .sub_with_overflow => try self.airOverflow(inst, .@"ssub.with.overflow", .@"usub.with.overflow"),
......@@ -4836,25 +4646,25 @@ pub const FuncGen = struct {
48364646 .round => try self.airUnaryOp(inst, .round),
48374647 .trunc_float => try self.airUnaryOp(inst, .trunc),
48384648
4839 .neg => try self.airNeg(inst, false),
4840 .neg_optimized => try self.airNeg(inst, true),
4841
4842 .cmp_eq => try self.airCmp(inst, .eq, false),
4843 .cmp_gt => try self.airCmp(inst, .gt, false),
4844 .cmp_gte => try self.airCmp(inst, .gte, false),
4845 .cmp_lt => try self.airCmp(inst, .lt, false),
4846 .cmp_lte => try self.airCmp(inst, .lte, false),
4847 .cmp_neq => try self.airCmp(inst, .neq, false),
4848
4849 .cmp_eq_optimized => try self.airCmp(inst, .eq, true),
4850 .cmp_gt_optimized => try self.airCmp(inst, .gt, true),
4851 .cmp_gte_optimized => try self.airCmp(inst, .gte, true),
4852 .cmp_lt_optimized => try self.airCmp(inst, .lt, true),
4853 .cmp_lte_optimized => try self.airCmp(inst, .lte, true),
4854 .cmp_neq_optimized => try self.airCmp(inst, .neq, true),
4855
4856 .cmp_vector => try self.airCmpVector(inst, false),
4857 .cmp_vector_optimized => try self.airCmpVector(inst, true),
4649 .neg => try self.airNeg(inst, .normal),
4650 .neg_optimized => try self.airNeg(inst, .fast),
4651
4652 .cmp_eq => try self.airCmp(inst, .eq, .normal),
4653 .cmp_gt => try self.airCmp(inst, .gt, .normal),
4654 .cmp_gte => try self.airCmp(inst, .gte, .normal),
4655 .cmp_lt => try self.airCmp(inst, .lt, .normal),
4656 .cmp_lte => try self.airCmp(inst, .lte, .normal),
4657 .cmp_neq => try self.airCmp(inst, .neq, .normal),
4658
4659 .cmp_eq_optimized => try self.airCmp(inst, .eq, .fast),
4660 .cmp_gt_optimized => try self.airCmp(inst, .gt, .fast),
4661 .cmp_gte_optimized => try self.airCmp(inst, .gte, .fast),
4662 .cmp_lt_optimized => try self.airCmp(inst, .lt, .fast),
4663 .cmp_lte_optimized => try self.airCmp(inst, .lte, .fast),
4664 .cmp_neq_optimized => try self.airCmp(inst, .neq, .fast),
4665
4666 .cmp_vector => try self.airCmpVector(inst, .normal),
4667 .cmp_vector_optimized => try self.airCmpVector(inst, .fast),
48584668 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
48594669
48604670 .is_non_null => try self.airIsNonNull(inst, false, .ne),
......@@ -4906,8 +4716,8 @@ pub const FuncGen = struct {
49064716 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
49074717 .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),
49084718
4909 .int_from_float => try self.airIntFromFloat(inst, false),
4910 .int_from_float_optimized => try self.airIntFromFloat(inst, true),
4719 .int_from_float => try self.airIntFromFloat(inst, .normal),
4720 .int_from_float_optimized => try self.airIntFromFloat(inst, .fast),
49114721
49124722 .array_to_slice => try self.airArrayToSlice(inst),
49134723 .float_from_int => try self.airFloatFromInt(inst),
......@@ -4939,8 +4749,8 @@ pub const FuncGen = struct {
49394749 .is_named_enum_value => try self.airIsNamedEnumValue(inst),
49404750 .error_set_has_value => try self.airErrorSetHasValue(inst),
49414751
4942 .reduce => try self.airReduce(inst, false),
4943 .reduce_optimized => try self.airReduce(inst, true),
4752 .reduce => try self.airReduce(inst, .normal),
4753 .reduce_optimized => try self.airReduce(inst, .fast),
49444754
49454755 .atomic_store_unordered => try self.airAtomicStore(inst, .unordered),
49464756 .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),
......@@ -5466,7 +5276,7 @@ pub const FuncGen = struct {
54665276 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
54675277 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 }, "");
54705280 return if (isByRef(va_list_ty, mod))
54715281 dest_list
54725282 else
......@@ -5477,7 +5287,7 @@ pub const FuncGen = struct {
54775287 const un_op = self.air.instructions.items(.data)[inst].un_op;
54785288 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}, "");
54815291 return .none;
54825292 }
54835293
......@@ -5490,27 +5300,28 @@ pub const FuncGen = struct {
54905300 const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod));
54915301 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}, "");
54945304 return if (isByRef(va_list_ty, mod))
54955305 dest_list
54965306 else
54975307 try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, "");
54985308 }
54995309
5500 fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !Builder.Value {
5501 self.builder.setFastMath(want_fast_math);
5502
5310 fn airCmp(
5311 self: *FuncGen,
5312 inst: Air.Inst.Index,
5313 op: math.CompareOperator,
5314 fast: Builder.FastMathKind,
5315 ) !Builder.Value {
55035316 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
55045317 const lhs = try self.resolveInst(bin_op.lhs);
55055318 const rhs = try self.resolveInst(bin_op.rhs);
55065319 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);
55095322 }
55105323
5511 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
5512 self.builder.setFastMath(want_fast_math);
5513
5324 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
55145325 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
55155326 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
55165327
......@@ -5519,7 +5330,7 @@ pub const FuncGen = struct {
55195330 const vec_ty = self.typeOf(extra.lhs);
55205331 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);
55235334 }
55245335
55255336 fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -5540,10 +5351,11 @@ pub const FuncGen = struct {
55405351
55415352 fn cmp(
55425353 self: *FuncGen,
5354 fast: Builder.FastMathKind,
5355 op: math.CompareOperator,
5356 operand_ty: Type,
55435357 lhs: Builder.Value,
55445358 rhs: Builder.Value,
5545 operand_ty: Type,
5546 op: math.CompareOperator,
55475359 ) Allocator.Error!Builder.Value {
55485360 const o = self.dg.object;
55495361 const mod = o.module;
......@@ -5595,7 +5407,7 @@ pub const FuncGen = struct {
55955407 self.wip.cursor = .{ .block = both_pl_block };
55965408 const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty, true);
55975409 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);
55995411 _ = try self.wip.br(end_block);
56005412 const both_pl_block_end = self.wip.cursor.block;
56015413
......@@ -5624,7 +5436,7 @@ pub const FuncGen = struct {
56245436 );
56255437 return phi.toValue();
56265438 },
5627 .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }),
5439 .Float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }),
56285440 else => unreachable,
56295441 };
56305442 const is_signed = int_ty.isSignedInt(mod);
......@@ -5995,8 +5807,12 @@ pub const FuncGen = struct {
59955807 );
59965808 }
59975809
5998 fn airIntFromFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
5999 self.builder.setFastMath(want_fast_math);
5810 fn airIntFromFloat(
5811 self: *FuncGen,
5812 inst: Air.Inst.Index,
5813 fast: Builder.FastMathKind,
5814 ) !Builder.Value {
5815 _ = fast;
60005816
60015817 const o = self.dg.object;
60025818 const mod = o.module;
......@@ -6414,6 +6230,8 @@ pub const FuncGen = struct {
64146230 }
64156231
64166232 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6233 if (!self.dg.object.builder.useLibLlvm()) return .none;
6234
64176235 const di_scope = self.di_scope orelse return .none;
64186236 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
64196237 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);
......@@ -6422,12 +6240,19 @@ pub const FuncGen = struct {
64226240 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc
64236241 else
64246242 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 );
64266249 return .none;
64276250 }
64286251
64296252 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
64306253 const o = self.dg.object;
6254 if (!o.builder.useLibLlvm()) return .none;
6255
64316256 const dib = o.di_builder orelse return .none;
64326257 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
64336258
......@@ -6438,7 +6263,7 @@ pub const FuncGen = struct {
64386263 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
64396264 self.di_file = di_file;
64406265 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
64436268 try self.dbg_inlined.append(self.gpa, .{
64446269 .loc = @ptrCast(cur_debug_location),
......@@ -6486,6 +6311,8 @@ pub const FuncGen = struct {
64866311
64876312 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
64886313 const o = self.dg.object;
6314 if (!o.builder.useLibLlvm()) return .none;
6315
64896316 if (o.di_builder == null) return .none;
64906317 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
64916318
......@@ -6501,6 +6328,8 @@ pub const FuncGen = struct {
65016328
65026329 fn airDbgBlockBegin(self: *FuncGen) !Builder.Value {
65036330 const o = self.dg.object;
6331 if (!o.builder.useLibLlvm()) return .none;
6332
65046333 const dib = o.di_builder orelse return .none;
65056334 const old_scope = self.di_scope.?;
65066335 try self.dbg_block_stack.append(self.gpa, old_scope);
......@@ -6511,6 +6340,8 @@ pub const FuncGen = struct {
65116340
65126341 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {
65136342 const o = self.dg.object;
6343 if (!o.builder.useLibLlvm()) return .none;
6344
65146345 if (o.di_builder == null) return .none;
65156346 self.di_scope = self.dbg_block_stack.pop();
65166347 return .none;
......@@ -6518,6 +6349,8 @@ pub const FuncGen = struct {
65186349
65196350 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
65206351 const o = self.dg.object;
6352 if (!o.builder.useLibLlvm()) return .none;
6353
65216354 const mod = o.module;
65226355 const dib = o.di_builder orelse return .none;
65236356 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
......@@ -6546,6 +6379,8 @@ pub const FuncGen = struct {
65466379
65476380 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
65486381 const o = self.dg.object;
6382 if (!o.builder.useLibLlvm()) return .none;
6383
65496384 const dib = o.di_builder orelse return .none;
65506385 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
65516386 const operand = try self.resolveInst(pl_op.operand);
......@@ -7346,7 +7181,7 @@ pub const FuncGen = struct {
73467181 const o = self.dg.object;
73477182 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
73487183 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}, &.{
73507185 try o.builder.intValue(.i32, index),
73517186 }, "");
73527187 }
......@@ -7355,7 +7190,7 @@ pub const FuncGen = struct {
73557190 const o = self.dg.object;
73567191 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
73577192 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}, &.{
73597194 try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),
73607195 }, "");
73617196 }
......@@ -7391,8 +7226,9 @@ pub const FuncGen = struct {
73917226 const inst_ty = self.typeOfIndex(inst);
73927227 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 });
73957230 return self.wip.callIntrinsic(
7231 .normal,
73967232 .none,
73977233 if (scalar_ty.isSignedInt(mod)) .smin else .umin,
73987234 &.{try o.lowerType(inst_ty)},
......@@ -7410,8 +7246,9 @@ pub const FuncGen = struct {
74107246 const inst_ty = self.typeOfIndex(inst);
74117247 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 });
74147250 return self.wip.callIntrinsic(
7251 .normal,
74157252 .none,
74167253 if (scalar_ty.isSignedInt(mod)) .smax else .umax,
74177254 &.{try o.lowerType(inst_ty)},
......@@ -7430,9 +7267,7 @@ pub const FuncGen = struct {
74307267 return self.wip.buildAggregate(try o.lowerType(inst_ty), &.{ ptr, len }, "");
74317268 }
74327269
7433 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7434 self.builder.setFastMath(want_fast_math);
7435
7270 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
74367271 const o = self.dg.object;
74377272 const mod = o.module;
74387273 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7441,7 +7276,7 @@ pub const FuncGen = struct {
74417276 const inst_ty = self.typeOfIndex(inst);
74427277 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 });
74457280 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"add nsw" else .@"add nuw", lhs, rhs, "");
74467281 }
74477282
......@@ -7463,12 +7298,13 @@ pub const FuncGen = struct {
74637298 const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
74647299 const llvm_inst_ty = try o.lowerType(inst_ty);
74657300 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
74687303 const overflow_bits = try fg.wip.extractValue(results, &.{1}, "");
74697304 const overflow_bits_ty = overflow_bits.typeOfWip(&fg.wip);
74707305 const overflow_bit = if (overflow_bits_ty.isVector(&o.builder))
74717306 try fg.wip.callIntrinsic(
7307 .normal,
74727308 .none,
74737309 .@"vector.reduce.or",
74747310 &.{overflow_bits_ty},
......@@ -7508,6 +7344,7 @@ pub const FuncGen = struct {
75087344
75097345 if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});
75107346 return self.wip.callIntrinsic(
7347 .normal,
75117348 .none,
75127349 if (scalar_ty.isSignedInt(mod)) .@"sadd.sat" else .@"uadd.sat",
75137350 &.{try o.lowerType(inst_ty)},
......@@ -7516,9 +7353,7 @@ pub const FuncGen = struct {
75167353 );
75177354 }
75187355
7519 fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7520 self.builder.setFastMath(want_fast_math);
7521
7356 fn airSub(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
75227357 const o = self.dg.object;
75237358 const mod = o.module;
75247359 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7527,7 +7362,7 @@ pub const FuncGen = struct {
75277362 const inst_ty = self.typeOfIndex(inst);
75287363 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 });
75317366 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"sub nsw" else .@"sub nuw", lhs, rhs, "");
75327367 }
75337368
......@@ -7550,6 +7385,7 @@ pub const FuncGen = struct {
75507385
75517386 if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});
75527387 return self.wip.callIntrinsic(
7388 .normal,
75537389 .none,
75547390 if (scalar_ty.isSignedInt(mod)) .@"ssub.sat" else .@"usub.sat",
75557391 &.{try o.lowerType(inst_ty)},
......@@ -7558,9 +7394,7 @@ pub const FuncGen = struct {
75587394 );
75597395 }
75607396
7561 fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7562 self.builder.setFastMath(want_fast_math);
7563
7397 fn airMul(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
75647398 const o = self.dg.object;
75657399 const mod = o.module;
75667400 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7569,7 +7403,7 @@ pub const FuncGen = struct {
75697403 const inst_ty = self.typeOfIndex(inst);
75707404 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 });
75737407 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"mul nsw" else .@"mul nuw", lhs, rhs, "");
75747408 }
75757409
......@@ -7592,6 +7426,7 @@ pub const FuncGen = struct {
75927426
75937427 if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});
75947428 return self.wip.callIntrinsic(
7429 .normal,
75957430 .none,
75967431 if (scalar_ty.isSignedInt(mod)) .@"smul.fix.sat" else .@"umul.fix.sat",
75977432 &.{try o.lowerType(inst_ty)},
......@@ -7600,20 +7435,16 @@ pub const FuncGen = struct {
76007435 );
76017436 }
76027437
7603 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7604 self.builder.setFastMath(want_fast_math);
7605
7438 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
76067439 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
76077440 const lhs = try self.resolveInst(bin_op.lhs);
76087441 const rhs = try self.resolveInst(bin_op.rhs);
76097442 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 });
76127445 }
76137446
7614 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7615 self.builder.setFastMath(want_fast_math);
7616
7447 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
76177448 const o = self.dg.object;
76187449 const mod = o.module;
76197450 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7623,15 +7454,13 @@ pub const FuncGen = struct {
76237454 const scalar_ty = inst_ty.scalarType(mod);
76247455
76257456 if (scalar_ty.isRuntimeFloat()) {
7626 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7627 return self.buildFloatOp(.trunc, inst_ty, 1, .{result});
7457 const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7458 return self.buildFloatOp(.trunc, fast, inst_ty, 1, .{result});
76287459 }
76297460 return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .sdiv else .udiv, lhs, rhs, "");
76307461 }
76317462
7632 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7633 self.builder.setFastMath(want_fast_math);
7634
7463 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
76357464 const o = self.dg.object;
76367465 const mod = o.module;
76377466 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7641,8 +7470,8 @@ pub const FuncGen = struct {
76417470 const scalar_ty = inst_ty.scalarType(mod);
76427471
76437472 if (scalar_ty.isRuntimeFloat()) {
7644 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7645 return self.buildFloatOp(.floor, inst_ty, 1, .{result});
7473 const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7474 return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result});
76467475 }
76477476 if (scalar_ty.isSignedInt(mod)) {
76487477 const inst_llvm_ty = try o.lowerType(inst_ty);
......@@ -7657,15 +7486,13 @@ pub const FuncGen = struct {
76577486 const div_sign_mask = try self.wip.bin(.ashr, div_sign, bit_size_minus_one, "");
76587487 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
76597488 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, "");
76617490 return self.wip.bin(.@"add nsw", div, correction, "");
76627491 }
76637492 return self.wip.bin(.udiv, lhs, rhs, "");
76647493 }
76657494
7666 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7667 self.builder.setFastMath(want_fast_math);
7668
7495 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
76697496 const o = self.dg.object;
76707497 const mod = o.module;
76717498 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7674,16 +7501,16 @@ pub const FuncGen = struct {
76747501 const inst_ty = self.typeOfIndex(inst);
76757502 const scalar_ty = inst_ty.scalarType(mod);
76767503
7677 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7678 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
7679 .@"sdiv exact"
7680 else
7681 .@"udiv exact", lhs, rhs, "");
7504 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs });
7505 return self.wip.bin(
7506 if (scalar_ty.isSignedInt(mod)) .@"sdiv exact" else .@"udiv exact",
7507 lhs,
7508 rhs,
7509 "",
7510 );
76827511 }
76837512
7684 fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7685 self.builder.setFastMath(want_fast_math);
7686
7513 fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
76877514 const o = self.dg.object;
76887515 const mod = o.module;
76897516 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7692,16 +7519,15 @@ pub const FuncGen = struct {
76927519 const inst_ty = self.typeOfIndex(inst);
76937520 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 });
76967524 return self.wip.bin(if (scalar_ty.isSignedInt(mod))
76977525 .srem
76987526 else
76997527 .urem, lhs, rhs, "");
77007528 }
77017529
7702 fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
7703 self.builder.setFastMath(want_fast_math);
7704
7530 fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
77057531 const o = self.dg.object;
77067532 const mod = o.module;
77077533 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -7712,12 +7538,12 @@ pub const FuncGen = struct {
77127538 const scalar_ty = inst_ty.scalarType(mod);
77137539
77147540 if (scalar_ty.isRuntimeFloat()) {
7715 const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });
7716 const b = try self.buildFloatOp(.add, inst_ty, 2, .{ a, rhs });
7717 const c = try self.buildFloatOp(.fmod, inst_ty, 2, .{ b, rhs });
7541 const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs });
7542 const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs });
7543 const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs });
77187544 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
7719 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero });
7720 return self.wip.select(ltz, c, a, "");
7545 const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero });
7546 return self.wip.select(fast, ltz, c, a, "");
77217547 }
77227548 if (scalar_ty.isSignedInt(mod)) {
77237549 const bit_size_minus_one = try o.builder.splatValue(inst_llvm_ty, try o.builder.intConst(
......@@ -7731,7 +7557,7 @@ pub const FuncGen = struct {
77317557 const rhs_masked = try self.wip.bin(.@"and", rhs, div_sign_mask, "");
77327558 const zero = try o.builder.zeroInitValue(inst_llvm_ty);
77337559 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, "");
77357561 return self.wip.bin(.@"add nsw", rem, correction, "");
77367562 }
77377563 return self.wip.bin(.urem, lhs, rhs, "");
......@@ -7804,7 +7630,7 @@ pub const FuncGen = struct {
78047630 const llvm_inst_ty = try o.lowerType(inst_ty);
78057631 const llvm_lhs_ty = try o.lowerType(lhs_ty);
78067632 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
78097635 const result_val = try self.wip.extractValue(results, &.{0}, "");
78107636 const overflow_bit = try self.wip.extractValue(results, &.{1}, "");
......@@ -7879,13 +7705,18 @@ pub const FuncGen = struct {
78797705 .function => |function| function,
78807706 else => unreachable,
78817707 };
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 );
78837713 }
78847714
78857715 /// Creates a floating point comparison by lowering to the appropriate
78867716 /// hardware instruction or softfloat routine for the target
78877717 fn buildFloatCmp(
78887718 self: *FuncGen,
7719 fast: Builder.FastMathKind,
78897720 pred: math.CompareOperator,
78907721 ty: Type,
78917722 params: [2]Builder.Value,
......@@ -7905,7 +7736,7 @@ pub const FuncGen = struct {
79057736 .gt => .ogt,
79067737 .gte => .oge,
79077738 };
7908 return self.wip.fcmp(cond, params[0], params[1], "");
7739 return self.wip.fcmp(fast, cond, params[0], params[1], "");
79097740 }
79107741
79117742 const float_bits = scalar_ty.floatBits(target);
......@@ -7996,6 +7827,7 @@ pub const FuncGen = struct {
79967827 fn buildFloatOp(
79977828 self: *FuncGen,
79987829 comptime op: FloatOp,
7830 fast: Builder.FastMathKind,
79997831 ty: Type,
80007832 comptime params_len: usize,
80017833 params: [params_len]Builder.Value,
......@@ -8009,13 +7841,23 @@ pub const FuncGen = struct {
80097841 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
80107842 // Some operations are dedicated LLVM instructions, not available as intrinsics
80117843 .neg => return self.wip.un(.fneg, params[0], ""),
8012 .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (op) {
8013 .add => .fadd,
8014 .sub => .fsub,
8015 .mul => .fmul,
8016 .div => .fdiv,
8017 .fmod => .frem,
8018 else => unreachable,
7844 .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) {
7845 .normal => switch (op) {
7846 .add => .fadd,
7847 .sub => .fsub,
7848 .mul => .fmul,
7849 .div => .fdiv,
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 },
80197861 }, params[0], params[1], ""),
80207862 .fmax,
80217863 .fmin,
......@@ -8033,7 +7875,7 @@ pub const FuncGen = struct {
80337875 .sqrt,
80347876 .trunc,
80357877 .fma,
8036 => return self.wip.callIntrinsic(.none, switch (op) {
7878 => return self.wip.callIntrinsic(fast, .none, switch (op) {
80377879 .fmax => .maxnum,
80387880 .fmin => .minnum,
80397881 .ceil => .ceil,
......@@ -8108,7 +7950,7 @@ pub const FuncGen = struct {
81087950 }
81097951
81107952 return self.wip.call(
8111 .normal,
7953 fast.toCallKind(),
81127954 .ccc,
81137955 .none,
81147956 libc_fn.typeOf(&o.builder),
......@@ -8127,7 +7969,7 @@ pub const FuncGen = struct {
81277969 const addend = try self.resolveInst(pl_op.operand);
81287970
81297971 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 });
81317973 }
81327974
81337975 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -8248,6 +8090,7 @@ pub const FuncGen = struct {
82488090 const llvm_lhs_ty = try o.lowerType(lhs_ty);
82498091 const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder);
82508092 const result = try self.wip.callIntrinsic(
8093 .normal,
82518094 .none,
82528095 if (lhs_scalar_ty.isSignedInt(mod)) .@"sshl.sat" else .@"ushl.sat",
82538096 &.{llvm_lhs_ty},
......@@ -8269,7 +8112,7 @@ pub const FuncGen = struct {
82698112 try o.builder.intConst(llvm_lhs_scalar_ty, -1),
82708113 );
82718114 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, "");
82738116 }
82748117
82758118 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value {
......@@ -8682,14 +8525,14 @@ pub const FuncGen = struct {
86828525
86838526 fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
86848527 _ = inst;
8685 _ = try self.wip.callIntrinsic(.none, .trap, &.{}, &.{}, "");
8528 _ = try self.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, "");
86868529 _ = try self.wip.@"unreachable"();
86878530 return .none;
86888531 }
86898532
86908533 fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
86918534 _ = inst;
8692 _ = try self.wip.callIntrinsic(.none, .debugtrap, &.{}, &.{}, "");
8535 _ = try self.wip.callIntrinsic(.normal, .none, .debugtrap, &.{}, &.{}, "");
86938536 return .none;
86948537 }
86958538
......@@ -8701,7 +8544,7 @@ pub const FuncGen = struct {
87018544 // https://github.com/ziglang/zig/issues/11946
87028545 return o.builder.intValue(llvm_usize, 0);
87038546 }
8704 const result = try self.wip.callIntrinsic(.none, .returnaddress, &.{}, &.{
8547 const result = try self.wip.callIntrinsic(.normal, .none, .returnaddress, &.{}, &.{
87058548 try o.builder.intValue(.i32, 0),
87068549 }, "");
87078550 return self.wip.cast(.ptrtoint, result, llvm_usize, "");
......@@ -8710,7 +8553,7 @@ pub const FuncGen = struct {
87108553 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
87118554 _ = inst;
87128555 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}, &.{
87148557 try o.builder.intValue(.i32, 0),
87158558 }, "");
87168559 return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), "");
......@@ -8768,7 +8611,7 @@ pub const FuncGen = struct {
87688611
87698612 if (optional_ty.optionalReprIsPayload(mod)) {
87708613 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, "");
87728615 }
87738616
87748617 comptime assert(optional_layout_version == 3);
......@@ -9053,8 +8896,8 @@ pub const FuncGen = struct {
90538896 access_kind: Builder.MemoryAccessKind,
90548897 ) !void {
90558898 const o = self.dg.object;
9056 const llvm_usize_ty = try o.lowerType(Type.usize);
9057 const cond = try self.cmp(len, try o.builder.intValue(llvm_usize_ty, 0), Type.usize, .neq);
8899 const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0);
8900 const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero);
90588901 const memset_block = try self.wip.block(1, "MemsetTrapSkip");
90598902 const end_block = try self.wip.block(2, "MemsetTrapEnd");
90608903 _ = try self.wip.brCond(cond, memset_block, end_block);
......@@ -9087,8 +8930,8 @@ pub const FuncGen = struct {
90878930 std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and
90888931 dest_ptr_ty.isSlice(mod))
90898932 {
9090 const zero_usize = try o.builder.intValue(try o.lowerType(Type.usize), 0);
9091 const cond = try self.cmp(len, zero_usize, Type.usize, .neq);
8933 const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0);
8934 const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero);
90928935 const memcpy_block = try self.wip.block(1, "MemcpyTrapSkip");
90938936 const end_block = try self.wip.block(2, "MemcpyTrapEnd");
90948937 _ = try self.wip.brCond(cond, memcpy_block, end_block);
......@@ -9166,17 +9009,15 @@ pub const FuncGen = struct {
91669009 const operand = try self.resolveInst(un_op);
91679010 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});
91709013 }
91719014
9172 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
9173 self.builder.setFastMath(want_fast_math);
9174
9015 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
91759016 const un_op = self.air.instructions.items(.data)[inst].un_op;
91769017 const operand = try self.resolveInst(un_op);
91779018 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});
91809021 }
91819022
91829023 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value {
......@@ -9187,6 +9028,7 @@ pub const FuncGen = struct {
91879028 const operand = try self.resolveInst(ty_op.operand);
91889029
91899030 const result = try self.wip.callIntrinsic(
9031 .normal,
91909032 .none,
91919033 intrinsic,
91929034 &.{try o.lowerType(operand_ty)},
......@@ -9204,6 +9046,7 @@ pub const FuncGen = struct {
92049046 const operand = try self.resolveInst(ty_op.operand);
92059047
92069048 const result = try self.wip.callIntrinsic(
9049 .normal,
92079050 .none,
92089051 intrinsic,
92099052 &.{try o.lowerType(operand_ty)},
......@@ -9242,7 +9085,8 @@ pub const FuncGen = struct {
92429085 bits = bits + 8;
92439086 }
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}, "");
92469090 return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
92479091 }
92489092
......@@ -9309,20 +9153,18 @@ pub const FuncGen = struct {
93099153 const function_index = try o.builder.addFunction(
93109154 try o.builder.fnType(.i1, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
93119155 try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}),
9156 toLlvmAddressSpace(.generic, mod.getTarget()),
93129157 );
93139158
93149159 var attributes: Builder.FunctionAttributes.Wip = .{};
93159160 defer attributes.deinit(&o.builder);
93169161 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;
9320 function_index.ptr(&o.builder).call_conv = .fastcc;
9163 function_index.setLinkage(.internal, &o.builder);
9164 function_index.setCallConv(.fastcc, &o.builder);
9165 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
93219166 gop.value_ptr.* = function_index;
93229167
9323 function_index.toLlvm(&o.builder).setLinkage(.Internal);
9324 function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast);
9325
93269168 var wip = try Builder.WipFunction.init(&o.builder, function_index);
93279169 defer wip.deinit();
93289170 wip.cursor = .{ .block = try wip.block(0, "Entry") };
......@@ -9383,20 +9225,18 @@ pub const FuncGen = struct {
93839225 const function_index = try o.builder.addFunction(
93849226 try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
93859227 try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}),
9228 toLlvmAddressSpace(.generic, mod.getTarget()),
93869229 );
93879230
93889231 var attributes: Builder.FunctionAttributes.Wip = .{};
93899232 defer attributes.deinit(&o.builder);
93909233 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;
9394 function_index.ptr(&o.builder).call_conv = .fastcc;
9235 function_index.setLinkage(.internal, &o.builder);
9236 function_index.setCallConv(.fastcc, &o.builder);
9237 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
93959238 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
94009240 var wip = try Builder.WipFunction.init(&o.builder, function_index);
94019241 defer wip.deinit();
94029242 wip.cursor = .{ .block = try wip.block(0, "Entry") };
......@@ -9407,36 +9247,20 @@ pub const FuncGen = struct {
94079247 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
94089248 defer wip_switch.finish(&wip);
94099249
9410 for (enum_type.names, 0..) |name_ip, field_index| {
9411 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_ip));
9412 const str_init = try o.builder.stringNullConst(name);
9413 const str_ty = str_init.typeOf(&o.builder);
9414 const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), "");
9415 str_llvm_global.setInitializer(str_init.toLlvm(&o.builder));
9416 str_llvm_global.setLinkage(.Private);
9417 str_llvm_global.setGlobalConstant(.True);
9418 str_llvm_global.setUnnamedAddr(.True);
9419 str_llvm_global.setAlignment(1);
9420
9421 var str_global = Builder.Global{
9422 .linkage = .private,
9423 .unnamed_addr = .unnamed_addr,
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),
9250 for (enum_type.names, 0..) |name, field_index| {
9251 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
9252 const name_init = try o.builder.stringNullConst(name_string);
9253 const name_variable_index =
9254 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
9255 try name_variable_index.setInitializer(name_init, &o.builder);
9256 name_variable_index.setLinkage(.private, &o.builder);
9257 name_variable_index.setMutability(.constant, &o.builder);
9258 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
9259 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
9260
9261 const name_val = try o.builder.structValue(ret_ty, &.{
9262 name_variable_index.toConst(&o.builder),
9263 try o.builder.intConst(usize_ty, name_string.slice(&o.builder).?.len),
94409264 });
94419265
94429266 const return_block = try wip.block(1, "Name");
......@@ -9446,7 +9270,7 @@ pub const FuncGen = struct {
94469270 try wip_switch.addCase(this_tag_int_value, return_block, &wip);
94479271
94489272 wip.cursor = .{ .block = return_block };
9449 _ = try wip.ret(slice_val);
9273 _ = try wip.ret(name_val);
94509274 }
94519275
94529276 wip.cursor = .{ .block = bad_value_block };
......@@ -9465,19 +9289,16 @@ pub const FuncGen = struct {
94659289 const function_index = try o.builder.addFunction(
94669290 try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal),
94679291 name,
9292 toLlvmAddressSpace(.generic, o.module.getTarget()),
94689293 );
94699294
94709295 var attributes: Builder.FunctionAttributes.Wip = .{};
94719296 defer attributes.deinit(&o.builder);
94729297 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);
94819302 return function_index;
94829303 }
94839304
......@@ -9511,7 +9332,7 @@ pub const FuncGen = struct {
95119332 const a = try self.resolveInst(extra.lhs);
95129333 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, "");
95159336 }
95169337
95179338 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -9623,8 +9444,7 @@ pub const FuncGen = struct {
96239444 return self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, "");
96249445 }
96259446
9626 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value {
9627 self.builder.setFastMath(want_fast_math);
9447 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value {
96289448 const o = self.dg.object;
96299449 const mod = o.module;
96309450 const target = mod.getTarget();
......@@ -9637,14 +9457,14 @@ pub const FuncGen = struct {
96379457 const llvm_scalar_ty = try o.lowerType(scalar_ty);
96389458
96399459 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) {
96419461 .And => .@"vector.reduce.and",
96429462 .Or => .@"vector.reduce.or",
96439463 .Xor => .@"vector.reduce.xor",
96449464 else => unreachable,
96459465 }, &.{llvm_operand_ty}, &.{operand}, ""),
96469466 .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) {
96489468 .Min => if (scalar_ty.isSignedInt(mod))
96499469 .@"vector.reduce.smin"
96509470 else
......@@ -9656,7 +9476,7 @@ pub const FuncGen = struct {
96569476 else => unreachable,
96579477 }, &.{llvm_operand_ty}, &.{operand}, ""),
96589478 .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) {
96609480 .Min => .@"vector.reduce.fmin",
96619481 .Max => .@"vector.reduce.fmax",
96629482 else => unreachable,
......@@ -9664,13 +9484,13 @@ pub const FuncGen = struct {
96649484 else => unreachable,
96659485 },
96669486 .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) {
96689488 .Add => .@"vector.reduce.add",
96699489 .Mul => .@"vector.reduce.mul",
96709490 else => unreachable,
96719491 }, &.{llvm_operand_ty}, &.{operand}, ""),
96729492 .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) {
96749494 .Add => .@"vector.reduce.fadd",
96759495 .Mul => .@"vector.reduce.fmul",
96769496 else => unreachable,
......@@ -10021,7 +9841,7 @@ pub const FuncGen = struct {
100219841 .data => {},
100229842 }
100239843
10024 _ = try self.wip.callIntrinsic(.none, .prefetch, &.{.ptr}, &.{
9844 _ = try self.wip.callIntrinsic(.normal, .none, .prefetch, &.{.ptr}, &.{
100259845 try self.resolveInst(prefetch.ptr),
100269846 try o.builder.intValue(.i32, prefetch.rw),
100279847 try o.builder.intValue(.i32, prefetch.locality),
......@@ -10045,7 +9865,7 @@ pub const FuncGen = struct {
100459865 default: u32,
100469866 comptime basename: []const u8,
100479867 ) !Builder.Value {
10048 return self.wip.callIntrinsic(.none, switch (dimension) {
9868 return self.wip.callIntrinsic(.normal, .none, switch (dimension) {
100499869 0 => @field(Builder.Intrinsic, basename ++ ".x"),
100509870 1 => @field(Builder.Intrinsic, basename ++ ".y"),
100519871 2 => @field(Builder.Intrinsic, basename ++ ".z"),
......@@ -10074,7 +9894,8 @@ pub const FuncGen = struct {
100749894
100759895 // Fetch the dispatch pointer, which points to this structure:
100769896 // 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
100799900 // Load the work_group_* member from the struct as u16.
100809901 // Just treat the dispatch pointer as an array of u16 to keep things simple.
......@@ -10097,40 +9918,24 @@ pub const FuncGen = struct {
100979918
100989919 fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index {
100999920 const o = self.dg.object;
9921 const mod = o.module;
9922
101009923 const table = o.error_name_table;
101019924 if (table != .none) return table;
101029925
10103 const mod = o.module;
10104 const slice_ty = Type.slice_const_u8_sentinel_0;
10105 const slice_alignment = slice_ty.abiAlignment(mod);
10106 const undef_init = try o.builder.undefConst(.ptr); // TODO: Address space
10107
10108 const name = try o.builder.string("__zig_err_name_table");
10109 const error_name_table_global = o.llvm_module.addGlobal(Builder.Type.ptr.toLlvm(&o.builder), name.slice(&o.builder).?);
10110 error_name_table_global.setInitializer(undef_init.toLlvm(&o.builder));
10111 error_name_table_global.setLinkage(.Private);
10112 error_name_table_global.setGlobalConstant(.True);
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);
9926 // TODO: Address space
9927 const variable_index =
9928 try o.builder.addVariable(try o.builder.string("__zig_err_name_table"), .ptr, .default);
9929 variable_index.setLinkage(.private, &o.builder);
9930 variable_index.setMutability(.constant, &o.builder);
9931 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
9932 variable_index.setAlignment(
9933 Builder.Alignment.fromByteUnits(Type.slice_const_u8_sentinel_0.abiAlignment(mod)),
9934 &o.builder,
9935 );
101319936
10132 o.error_name_table = global.kind.variable;
10133 return global.kind.variable;
9937 o.error_name_table = variable_index;
9938 return variable_index;
101349939 }
101359940
101369941 /// Assumes the optional is not pointer-like and payload has bits.
......@@ -11547,15 +11352,19 @@ fn buildAllocaInner(
1154711352
1154811353 const alloca = blk: {
1154911354 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;
1155111359 defer {
1155211360 wip.cursor = prev_cursor;
1155311361 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);
1155511364 }
1155611365
1155711366 wip.cursor = .{ .block = .entry };
11558 wip.llvm.builder.clearCurrentDebugLocation();
11367 if (wip.builder.useLibLlvm()) wip.llvm.builder.clearCurrentDebugLocation();
1155911368 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");
1156011369 };
1156111370
src/codegen/llvm/Builder.zig+511-119
......@@ -13,6 +13,7 @@ llvm: if (build_options.have_llvm) struct {
1313 types: std.ArrayListUnmanaged(*llvm.Type),
1414 globals: std.ArrayListUnmanaged(*llvm.Value),
1515 constants: std.ArrayListUnmanaged(*llvm.Value),
16 replacements: std.AutoHashMapUnmanaged(*llvm.Value, Global.Index),
1617} else void,
1718
1819source_filename: String,
......@@ -1709,17 +1710,17 @@ pub const FunctionAttributes = enum(u32) {
17091710};
17101711
17111712pub const Linkage = enum {
1712 external,
17131713 private,
17141714 internal,
1715 available_externally,
1716 linkonce,
17171715 weak,
1718 common,
1716 weak_odr,
1717 linkonce,
1718 linkonce_odr,
1719 available_externally,
17191720 appending,
1721 common,
17201722 extern_weak,
1721 linkonce_odr,
1722 weak_odr,
1723 external,
17231724
17241725 pub fn format(
17251726 self: Linkage,
......@@ -1729,6 +1730,22 @@ pub const Linkage = enum {
17291730 ) @TypeOf(writer).Error!void {
17301731 if (self != .external) try writer.print(" {s}", .{@tagName(self)});
17311732 }
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 }
17321749};
17331750
17341751pub const Preemption = enum {
......@@ -1759,6 +1776,14 @@ pub const Visibility = enum {
17591776 ) @TypeOf(writer).Error!void {
17601777 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
17611778 }
1779
1780 fn toLlvm(self: Visibility) llvm.Visibility {
1781 return switch (self) {
1782 .default => .Default,
1783 .hidden => .Hidden,
1784 .protected => .Protected,
1785 };
1786 }
17621787};
17631788
17641789pub const DllStorageClass = enum {
......@@ -1774,6 +1799,14 @@ pub const DllStorageClass = enum {
17741799 ) @TypeOf(writer).Error!void {
17751800 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
17761801 }
1802
1803 fn toLlvm(self: DllStorageClass) llvm.DLLStorageClass {
1804 return switch (self) {
1805 .default => .Default,
1806 .dllimport => .DLLImport,
1807 .dllexport => .DLLExport,
1808 };
1809 }
17771810};
17781811
17791812pub const ThreadLocal = enum {
......@@ -1785,20 +1818,28 @@ pub const ThreadLocal = enum {
17851818
17861819 pub fn format(
17871820 self: ThreadLocal,
1788 comptime _: []const u8,
1821 comptime prefix: []const u8,
17891822 _: std.fmt.FormatOptions,
17901823 writer: anytype,
17911824 ) @TypeOf(writer).Error!void {
17921825 if (self == .default) return;
1793 try writer.writeAll(" thread_local");
1794 if (self != .generaldynamic) {
1795 try writer.writeByte('(');
1796 try writer.writeAll(@tagName(self));
1797 try writer.writeByte(')');
1798 }
1826 try writer.print("{s}thread_local", .{prefix});
1827 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});
1828 }
1829
1830 fn toLlvm(self: ThreadLocal) llvm.ThreadLocalMode {
1831 return switch (self) {
1832 .default => .NotThreadLocal,
1833 .generaldynamic => .GeneralDynamicTLSModel,
1834 .localdynamic => .LocalDynamicTLSModel,
1835 .initialexec => .InitialExecTLSModel,
1836 .localexec => .LocalExecTLSModel,
1837 };
17991838 }
18001839};
18011840
1841pub const Mutability = enum { global, constant };
1842
18021843pub const UnnamedAddr = enum {
18031844 default,
18041845 unnamed_addr,
......@@ -2057,6 +2098,11 @@ pub const CallConv = enum(u10) {
20572098 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),
20582099 }
20592100 }
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 }
20602106};
20612107
20622108pub const Global = struct {
......@@ -2093,10 +2139,6 @@ pub const Global = struct {
20932139 return self.unwrap(builder) == other.unwrap(builder);
20942140 }
20952141
2096 pub fn name(self: Index, builder: *const Builder) String {
2097 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
2098 }
2099
21002142 pub fn ptr(self: Index, builder: *Builder) *Global {
21012143 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
21022144 }
......@@ -2105,6 +2147,10 @@ pub const Global = struct {
21052147 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
21062148 }
21072149
2150 pub fn name(self: Index, builder: *const Builder) String {
2151 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
2152 }
2153
21082154 pub fn typeOf(self: Index, builder: *const Builder) Type {
21092155 return self.ptrConst(builder).type;
21102156 }
......@@ -2113,6 +2159,30 @@ pub const Global = struct {
21132159 return @enumFromInt(@intFromEnum(Constant.first_global) + @intFromEnum(self));
21142160 }
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
21162186 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
21172187 assert(builder.useLibLlvm());
21182188 return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))];
......@@ -2148,9 +2218,36 @@ pub const Global = struct {
21482218
21492219 pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
21502220 try builder.ensureUnusedGlobalCapacity(.empty);
2221 if (builder.useLibLlvm())
2222 try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1);
21512223 self.replaceAssumeCapacity(other, builder);
21522224 }
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
21542251 fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void {
21552252 const old_name = self.name(builder);
21562253 if (new_name == old_name) return;
......@@ -2187,13 +2284,8 @@ pub const Global = struct {
21872284 if (builder.useLibLlvm()) {
21882285 const self_llvm = self.toLlvm(builder);
21892286 self_llvm.replaceAllUsesWith(other.toLlvm(builder));
2190 switch (self.ptr(builder).kind) {
2191 .alias,
2192 .variable,
2193 => self_llvm.deleteGlobal(),
2194 .function => self_llvm.deleteFunction(),
2195 .replaced => unreachable,
2196 }
2287 self_llvm.removeGlobalValue();
2288 builder.llvm.replacements.putAssumeCapacityNoClobber(self_llvm, other);
21972289 }
21982290 self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
21992291 }
......@@ -2205,42 +2297,17 @@ pub const Global = struct {
22052297 };
22062298 }
22072299 };
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 }
22272300};
22282301
22292302pub const Alias = struct {
22302303 global: Global.Index,
22312304 thread_local: ThreadLocal = .default,
2232 init: Constant = .no_init,
2305 aliasee: Constant = .no_init,
22332306
22342307 pub const Index = enum(u32) {
22352308 none = std.math.maxInt(u32),
22362309 _,
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
22442311 pub fn ptr(self: Index, builder: *Builder) *Alias {
22452312 return &builder.aliases.items[@intFromEnum(self)];
22462313 }
......@@ -2249,6 +2316,10 @@ pub const Alias = struct {
22492316 return &builder.aliases.items[@intFromEnum(self)];
22502317 }
22512318
2319 pub fn name(self: Index, builder: *const Builder) String {
2320 return self.ptrConst(builder).global.name(builder);
2321 }
2322
22522323 pub fn typeOf(self: Index, builder: *const Builder) Type {
22532324 return self.ptrConst(builder).global.typeOf(builder);
22542325 }
......@@ -2261,7 +2332,18 @@ pub const Alias = struct {
22612332 return self.toConst(builder).toValue();
22622333 }
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 {
22652347 return self.ptrConst(builder).global.toLlvm(builder);
22662348 }
22672349 };
......@@ -2270,7 +2352,7 @@ pub const Alias = struct {
22702352pub const Variable = struct {
22712353 global: Global.Index,
22722354 thread_local: ThreadLocal = .default,
2273 mutability: enum { global, constant } = .global,
2355 mutability: Mutability = .global,
22742356 init: Constant = .no_init,
22752357 section: String = .none,
22762358 alignment: Alignment = .default,
......@@ -2287,6 +2369,10 @@ pub const Variable = struct {
22872369 return &builder.variables.items[@intFromEnum(self)];
22882370 }
22892371
2372 pub fn name(self: Index, builder: *const Builder) String {
2373 return self.ptrConst(builder).global.name(builder);
2374 }
2375
22902376 pub fn typeOf(self: Index, builder: *const Builder) Type {
22912377 return self.ptrConst(builder).global.typeOf(builder);
22922378 }
......@@ -2299,6 +2385,88 @@ pub const Variable = struct {
22992385 return self.toConst(builder).toValue();
23002386 }
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
23022470 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
23032471 return self.ptrConst(builder).global.toLlvm(builder);
23042472 }
......@@ -3640,6 +3808,10 @@ pub const Function = struct {
36403808 return &builder.functions.items[@intFromEnum(self)];
36413809 }
36423810
3811 pub fn name(self: Index, builder: *const Builder) String {
3812 return self.ptrConst(builder).global.name(builder);
3813 }
3814
36433815 pub fn typeOf(self: Index, builder: *const Builder) Type {
36443816 return self.ptrConst(builder).global.typeOf(builder);
36453817 }
......@@ -3652,6 +3824,19 @@ pub const Function = struct {
36523824 return self.toConst(builder).toValue();
36533825 }
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
36553840 pub fn setAttributes(
36563841 self: Index,
36573842 new_function_attributes: FunctionAttributes,
......@@ -3687,12 +3872,12 @@ pub const Function = struct {
36873872 )) {
36883873 .lt => {
36893874 // Removed
3690 if (old_attribute_kind.toString()) |name| {
3691 const slice = name.slice(builder).?;
3875 if (old_attribute_kind.toString()) |attribute_name| {
3876 const attribute_name_slice = attribute_name.slice(builder).?;
36923877 llvm_function.removeStringAttributeAtIndex(
36933878 llvm_attribute_index,
3694 slice.ptr,
3695 @intCast(slice.len),
3879 attribute_name_slice.ptr,
3880 @intCast(attribute_name_slice.len),
36963881 );
36973882 } else {
36983883 const llvm_kind_id = old_attribute_kind.toLlvm(builder).*;
......@@ -3732,6 +3917,17 @@ pub const Function = struct {
37323917 self.ptr(builder).attributes = new_function_attributes;
37333918 }
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
37353931 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
37363932 return self.ptrConst(builder).global.toLlvm(builder);
37373933 }
......@@ -4342,9 +4538,11 @@ pub const Function = struct {
43424538 return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };
43434539 }
43444540
4345 pub fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value {
4541 fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value {
43464542 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);
43484546 }
43494547
43504548 fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 {
......@@ -4462,6 +4660,27 @@ pub const Function = struct {
44624660 fmax,
44634661 fmin,
44644662 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 }
44654684 };
44664685 };
44674686
......@@ -5245,7 +5464,7 @@ pub const WipFunction = struct {
52455464 instruction.llvmName(self),
52465465 );
52475466 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());
52495468 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
52505469 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
52515470 }
......@@ -5295,7 +5514,7 @@ pub const WipFunction = struct {
52955514 if (self.builder.useLibLlvm()) {
52965515 const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self));
52975516 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());
52995518 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
53005519 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
53015520 }
......@@ -5318,7 +5537,7 @@ pub const WipFunction = struct {
53185537 });
53195538 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
53205539 self.llvm.builder.buildFence(
5321 @enumFromInt(@intFromEnum(ordering)),
5540 ordering.toLlvm(),
53225541 llvm.Bool.fromBool(sync_scope == .singlethread),
53235542 "",
53245543 ),
......@@ -5370,8 +5589,8 @@ pub const WipFunction = struct {
53705589 ptr.toLlvm(self),
53715590 cmp.toLlvm(self),
53725591 new.toLlvm(self),
5373 @enumFromInt(@intFromEnum(success_ordering)),
5374 @enumFromInt(@intFromEnum(failure_ordering)),
5592 success_ordering.toLlvm(),
5593 failure_ordering.toLlvm(),
53755594 llvm.Bool.fromBool(sync_scope == .singlethread),
53765595 );
53775596 if (kind == .weak) llvm_instruction.setWeak(.True);
......@@ -5418,10 +5637,10 @@ pub const WipFunction = struct {
54185637 });
54195638 if (self.builder.useLibLlvm()) {
54205639 const llvm_instruction = self.llvm.builder.buildAtomicRmw(
5421 @enumFromInt(@intFromEnum(operation)),
5640 operation.toLlvm(),
54225641 ptr.toLlvm(self),
54235642 val.toLlvm(self),
5424 @enumFromInt(@intFromEnum(ordering)),
5643 ordering.toLlvm(),
54255644 llvm.Bool.fromBool(sync_scope == .singlethread),
54265645 );
54275646 if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True);
......@@ -5608,25 +5827,19 @@ pub const WipFunction = struct {
56085827
56095828 pub fn fcmp(
56105829 self: *WipFunction,
5830 fast: FastMathKind,
56115831 cond: FloatCondition,
56125832 lhs: Value,
56135833 rhs: Value,
56145834 name: []const u8,
56155835 ) Allocator.Error!Value {
5616 return self.cmpTag(switch (cond) {
5617 inline else => |tag| @field(Instruction.Tag, "fcmp " ++ @tagName(tag)),
5618 }, @intFromEnum(cond), lhs, rhs, name);
5619 }
5620
5621 pub fn fcmpFast(
5622 self: *WipFunction,
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)),
5836 return self.cmpTag(switch (fast) {
5837 inline else => |fast_tag| switch (cond) {
5838 inline else => |cond_tag| @field(Instruction.Tag, "fcmp " ++ switch (fast_tag) {
5839 .normal => "",
5840 .fast => "fast ",
5841 } ++ @tagName(cond_tag)),
5842 },
56305843 }, @intFromEnum(cond), lhs, rhs, name);
56315844 }
56325845
......@@ -5684,22 +5897,16 @@ pub const WipFunction = struct {
56845897
56855898 pub fn select(
56865899 self: *WipFunction,
5900 fast: FastMathKind,
56875901 cond: Value,
56885902 lhs: Value,
56895903 rhs: Value,
56905904 name: []const u8,
56915905 ) Allocator.Error!Value {
5692 return self.selectTag(.select, cond, lhs, rhs, name);
5693 }
5694
5695 pub fn selectFast(
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);
5906 return self.selectTag(switch (fast) {
5907 .normal => .select,
5908 .fast => .@"select fast",
5909 }, cond, lhs, rhs, name);
57035910 }
57045911
57055912 pub fn call(
......@@ -5774,7 +5981,7 @@ pub const WipFunction = struct {
57745981 else => instruction.llvmName(self),
57755982 },
57765983 );
5777 llvm_instruction.setInstructionCallConv(@enumFromInt(@intFromEnum(call_conv)));
5984 llvm_instruction.setInstructionCallConv(call_conv.toLlvm());
57785985 llvm_instruction.setTailCallKind(switch (kind) {
57795986 .normal, .fast => .None,
57805987 .musttail, .musttail_fast => .MustTail,
......@@ -5808,6 +6015,7 @@ pub const WipFunction = struct {
58086015
58096016 pub fn callIntrinsic(
58106017 self: *WipFunction,
6018 fast: FastMathKind,
58116019 function_attributes: FunctionAttributes,
58126020 id: Intrinsic,
58136021 overload: []const Type,
......@@ -5816,7 +6024,7 @@ pub const WipFunction = struct {
58166024 ) Allocator.Error!Value {
58176025 const intrinsic = try self.builder.getIntrinsic(id, overload);
58186026 return self.call(
5819 .normal,
6027 fast.toCallKind(),
58206028 CallConv.default,
58216029 function_attributes,
58226030 intrinsic.typeOf(self.builder),
......@@ -5838,6 +6046,7 @@ pub const WipFunction = struct {
58386046 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
58396047 var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })};
58406048 const value = try self.callIntrinsic(
6049 .normal,
58416050 try self.builder.fnAttrs(&.{
58426051 .none,
58436052 .none,
......@@ -5865,6 +6074,7 @@ pub const WipFunction = struct {
58656074 ) Allocator.Error!Instruction.Index {
58666075 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
58676076 const value = try self.callIntrinsic(
6077 .normal,
58686078 try self.builder.fnAttrs(&.{ .none, .none, try self.builder.attrs(&dst_attrs) }),
58696079 .memset,
58706080 &.{ dst.typeOfWip(self), len.typeOfWip(self) },
......@@ -6740,6 +6950,24 @@ pub const FloatCondition = enum(u4) {
67406950 ult = 12,
67416951 ule = 13,
67426952 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 }
67436971};
67446972
67456973pub const IntegerCondition = enum(u6) {
......@@ -6753,6 +6981,20 @@ pub const IntegerCondition = enum(u6) {
67536981 sge = 39,
67546982 slt = 40,
67556983 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 }
67566998};
67576999
67587000pub const MemoryAccessKind = enum(u1) {
......@@ -6802,6 +7044,18 @@ pub const AtomicOrdering = enum(u3) {
68027044 ) @TypeOf(writer).Error!void {
68037045 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
68047046 }
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 }
68057059};
68067060
68077061const MemoryAccessInfo = packed struct(u32) {
......@@ -6834,6 +7088,18 @@ pub const FastMath = packed struct(u32) {
68347088 };
68357089};
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
68377103pub const Constant = enum(u32) {
68387104 false,
68397105 true,
......@@ -7247,7 +7513,7 @@ pub const Constant = enum(u32) {
72477513 }
72487514 },
72497515 .global => |global| switch (global.ptrConst(builder).kind) {
7250 .alias => |alias| cur = alias.ptrConst(builder).init,
7516 .alias => |alias| cur = alias.ptrConst(builder).aliasee,
72517517 .variable, .function => return global,
72527518 .replaced => unreachable,
72537519 },
......@@ -7586,10 +7852,12 @@ pub const Constant = enum(u32) {
75867852
75877853 pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value {
75887854 assert(builder.useLibLlvm());
7589 return switch (self.unwrap()) {
7855 const llvm_value = switch (self.unwrap()) {
75907856 .constant => |constant| builder.llvm.constants.items[constant],
7591 .global => |global| global.toLlvm(builder),
7857 .global => |global| return global.toLlvm(builder),
75927858 };
7859 const global = builder.llvm.replacements.get(llvm_value) orelse return llvm_value;
7860 return global.toLlvm(builder);
75937861 }
75947862};
75957863
......@@ -7726,6 +7994,7 @@ pub fn init(options: Options) InitError!Builder {
77267994 .types = .{},
77277995 .globals = .{},
77287996 .constants = .{},
7997 .replacements = .{},
77297998 };
77307999 errdefer self.deinit();
77318000
......@@ -7805,6 +8074,20 @@ pub fn init(options: Options) InitError!Builder {
78058074}
78068075
78078076pub 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
78088091 self.module_asm.deinit(self.gpa);
78098092
78108093 self.string_map.deinit(self.gpa);
......@@ -7834,16 +8117,6 @@ pub fn deinit(self: *Builder) void {
78348117 self.constant_extra.deinit(self.gpa);
78358118 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 }
78478120 self.* = undefined;
78488121}
78498122
......@@ -8300,10 +8573,10 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo
83008573 const global_gop = self.globals.getOrPutAssumeCapacity(id);
83018574 if (!global_gop.found_existing) {
83028575 global_gop.value_ptr.* = global;
8303 global_gop.value_ptr.updateAttributes();
8304 const index: Global.Index = @enumFromInt(global_gop.index);
8305 index.updateName(self);
8306 return index;
8576 const global_index: Global.Index = @enumFromInt(global_gop.index);
8577 global_index.updateDsoLocal(self);
8578 global_index.updateName(self);
8579 return global_index;
83078580 }
83088581
83098582 const unique_gop = self.next_unique_global_id.getOrPutAssumeCapacity(name);
......@@ -8317,21 +8590,107 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index {
83178590 return @enumFromInt(self.globals.getIndex(name) orelse return null);
83188591}
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 {
83218670 assert(!name.isAnon());
83228671 try self.ensureUnusedTypeCapacity(1, NoExtra, 0);
83238672 try self.ensureUnusedGlobalCapacity(name);
83248673 try self.functions.ensureUnusedCapacity(self.gpa, 1);
8325 return self.addFunctionAssumeCapacity(ty, name);
8674 return self.addFunctionAssumeCapacity(ty, name, addr_space);
83268675}
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 {
83298683 assert(ty.isFunction(self));
83308684 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 ),
83328690 );
83338691 const function_index: Function.Index = @enumFromInt(self.functions.items.len);
83348692 self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{
8693 .addr_space = addr_space,
83358694 .type = ty,
83368695 .kind = .{ .function = function_index },
83378696 }) });
......@@ -8423,12 +8782,11 @@ pub fn getIntrinsic(
84238782 };
84248783 }
84258784
8426 const function_index =
8427 try self.addFunction(try self.fnType(switch (signature.ret_len) {
8785 const function_index = try self.addFunction(try self.fnType(switch (signature.ret_len) {
84288786 0 => .void,
84298787 1 => param_types[0],
84308788 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);
84328790 function_index.ptr(self).attributes = try self.fnAttrs(function_attributes);
84338791 return function_index;
84348792}
......@@ -8889,6 +9247,40 @@ pub fn asmValue(
88899247 return (try self.asmConst(ty, info, assembly, constraints)).toValue();
88909248}
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
88929284pub fn dump(self: *Builder) void {
88939285 if (self.useLibLlvm())
88949286 self.llvm.module.?.dump()
......@@ -8980,7 +9372,7 @@ pub fn printUnbuffered(
89809372 if (variable.global.getReplacement(self) != .none) continue;
89819373 const global = variable.global.ptrConst(self);
89829374 try writer.print(
8983 \\{} ={}{}{}{}{}{}{ }{} {s} {%}{ }{, }
9375 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }
89849376 \\
89859377 , .{
89869378 variable.global.fmt(self),
......@@ -10906,7 +11298,7 @@ fn icmpConstAssumeCapacity(
1090611298 .data = self.addConstantExtraAssumeCapacity(data),
1090711299 });
1090811300 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)),
1091011302 );
1091111303 }
1091211304 return @enumFromInt(gop.index);
......@@ -10943,7 +11335,7 @@ fn fcmpConstAssumeCapacity(
1094311335 .data = self.addConstantExtraAssumeCapacity(data),
1094411336 });
1094511337 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)),
1094711339 );
1094811340 }
1094911341 return @enumFromInt(gop.index);
src/codegen/llvm/bindings.zig+10-35
......@@ -142,8 +142,14 @@ pub const Value = opaque {
142142 pub const setSection = LLVMSetSection;
143143 extern fn LLVMSetSection(Global: *Value, Section: [*:0]const u8) void;
144144
145 pub const deleteGlobal = LLVMDeleteGlobal;
146 extern fn LLVMDeleteGlobal(GlobalVar: *Value) void;
145 pub const removeGlobalValue = ZigLLVMRemoveGlobalValue;
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
148154 pub const setAliasee = LLVMAliasSetAliasee;
149155 extern fn LLVMAliasSetAliasee(Alias: *Value, Aliasee: *Value) void;
......@@ -292,20 +298,14 @@ pub const Value = opaque {
292298 pub const setValueName = LLVMSetValueName2;
293299 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
298301 pub const takeName = ZigLLVMTakeName;
299302 extern fn ZigLLVMTakeName(new_owner: *Value, victim: *Value) void;
300303
301 pub const deleteFunction = LLVMDeleteFunction;
302 extern fn LLVMDeleteFunction(Fn: *Value) void;
303
304304 pub const getParam = LLVMGetParam;
305305 extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
306306
307 pub const setInitializer = LLVMSetInitializer;
308 extern fn LLVMSetInitializer(GlobalVar: *Value, ConstantVal: *Value) void;
307 pub const setInitializer = ZigLLVMSetInitializer;
308 extern fn ZigLLVMSetInitializer(GlobalVar: *Value, ConstantVal: ?*Value) void;
309309
310310 pub const setDLLStorageClass = LLVMSetDLLStorageClass;
311311 extern fn LLVMSetDLLStorageClass(Global: *Value, Class: DLLStorageClass) void;
......@@ -316,15 +316,6 @@ pub const Value = opaque {
316316 pub const replaceAllUsesWith = LLVMReplaceAllUsesWith;
317317 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
328319 pub const attachMetaData = ZigLLVMAttachMetaData;
329320 extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void;
330321
......@@ -423,18 +414,12 @@ pub const Module = opaque {
423414 pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel;
424415 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
429417 pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace;
430418 extern fn ZigLLVMAddFunctionInAddressSpace(*Module, Name: [*:0]const u8, FunctionTy: *Type, AddressSpace: c_uint) *Value;
431419
432420 pub const printToString = LLVMPrintModuleToString;
433421 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
438423 pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace;
439424 extern fn LLVMAddGlobalInAddressSpace(M: *Module, Ty: *Type, Name: [*:0]const u8, AddressSpace: c_uint) *Value;
440425
......@@ -450,16 +435,6 @@ pub const Module = opaque {
450435 Name: [*:0]const u8,
451436 ) *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
463438 pub const setTarget = LLVMSetTarget;
464439 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) {
11221122 unwrap(new_owner)->takeName(unwrap(victim));
11231123}
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
11251141ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) {
11261142 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable());
11271143}
src/zig_llvm.h+4
......@@ -492,6 +492,10 @@ enum ZigLLVM_ObjectFormatType {
492492};
493493
494494ZIG_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
496500#define ZigLLVM_DIFlags_Zero 0U
497501#define ZigLLVM_DIFlags_Private 1U