authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-15 19:12:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:19-07:00
logb54ad9317591873159594e673953088a21d66e7b
tree3f460d89248d9764a2543a4ec0ae57edc99ff384
parent92b54e50c85488459df0c6579086494e31d9d52a

update codegen.llvm references to bin_file.options


8 files changed, 354 insertions(+), 304 deletions(-)

src/codegen/llvm.zig+246-248
......@@ -822,7 +822,7 @@ pub const Object = struct {
822822 type_map: TypeMap,
823823 di_type_map: DITypeMap,
824824 /// The LLVM global table which holds the names corresponding to Zig errors.
825 /// Note that the values are not added until flushModule, when all errors in
825 /// Note that the values are not added until `emit`, when all errors in
826826 /// the compilation are known.
827827 error_name_table: Builder.Variable.Index,
828828 /// This map is usually very close to empty. It tracks only the cases when a
......@@ -850,7 +850,7 @@ pub const Object = struct {
850850
851851 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);
852852
853 /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we
853 /// This is an ArrayHashMap as opposed to a HashMap because in `emit` we
854854 /// want to iterate over it while adding entries to it.
855855 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
856856
......@@ -1026,17 +1026,6 @@ pub const Object = struct {
10261026 self.* = undefined;
10271027 }
10281028
1029 fn locPath(
1030 arena: Allocator,
1031 opt_loc: ?Compilation.EmitLoc,
1032 cache_directory: Compilation.Directory,
1033 ) !?[*:0]u8 {
1034 const loc = opt_loc orelse return null;
1035 const directory = loc.directory orelse cache_directory;
1036 const slice = try directory.joinZ(arena, &[_][]const u8{loc.basename});
1037 return slice.ptr;
1038 }
1039
10401029 fn genErrorNameTable(o: *Object) Allocator.Error!void {
10411030 // If o.error_name_table is null, then it was not referenced by any instructions.
10421031 if (o.error_name_table == .none) return;
......@@ -1175,12 +1164,22 @@ pub const Object = struct {
11751164 }
11761165 }
11771166
1178 pub fn flushModule(self: *Object, comp: *Compilation, prog_node: *std.Progress.Node) !void {
1179 var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
1180 sub_prog_node.activate();
1181 sub_prog_node.context.refresh();
1182 defer sub_prog_node.end();
1167 pub const EmitOptions = struct {
1168 pre_ir_path: ?[]const u8,
1169 pre_bc_path: ?[]const u8,
1170 bin_path: ?[*:0]const u8,
1171 emit_asm: ?[*:0]const u8,
1172 post_ir_path: ?[*:0]const u8,
1173 post_bc_path: ?[*:0]const u8,
1174
1175 is_debug: bool,
1176 is_small: bool,
1177 time_report: bool,
1178 sanitize_thread: bool,
1179 lto: bool,
1180 };
11831181
1182 pub fn emit(self: *Object, options: EmitOptions) !void {
11841183 try self.resolveExportExternCollisions();
11851184 try self.genErrorNameTable();
11861185 try self.genCmpLtErrorsLenFunction();
......@@ -1206,7 +1205,7 @@ pub const Object = struct {
12061205 dib.finalize();
12071206 }
12081207
1209 if (comp.verbose_llvm_ir) |path| {
1208 if (options.pre_ir_path) |path| {
12101209 if (std.mem.eql(u8, path, "-")) {
12111210 self.builder.dump();
12121211 } else {
......@@ -1214,91 +1213,72 @@ pub const Object = struct {
12141213 }
12151214 }
12161215
1217 if (comp.verbose_llvm_bc) |path| _ = try self.builder.writeBitcodeToFile(path);
1218
1219 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
1220 defer arena_allocator.deinit();
1221 const arena = arena_allocator.allocator();
1222
1223 const mod = comp.module.?;
1224 const cache_dir = mod.zig_cache_artifact_directory;
1216 if (options.pre_bc_path) |path| _ = try self.builder.writeBitcodeToFile(path);
12251217
12261218 if (std.debug.runtime_safety and !try self.builder.verify()) {
1227 if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path|
1228 _ = self.builder.printToFileZ(emit_llvm_ir_path);
12291219 @panic("LLVM module verification failed");
12301220 }
12311221
1232 var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|
1233 try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?))
1234 else
1235 null;
1236
1237 const emit_asm_path = try locPath(arena, comp.emit_asm, cache_dir);
1238 var emit_llvm_ir_path = try locPath(arena, comp.emit_llvm_ir, cache_dir);
1239 const emit_llvm_bc_path = try locPath(arena, comp.emit_llvm_bc, cache_dir);
1240
1241 const emit_asm_msg = emit_asm_path orelse "(none)";
1242 const emit_bin_msg = emit_bin_path orelse "(none)";
1243 const emit_llvm_ir_msg = emit_llvm_ir_path orelse "(none)";
1244 const emit_llvm_bc_msg = emit_llvm_bc_path orelse "(none)";
1222 const emit_asm_msg = options.asm_path orelse "(none)";
1223 const emit_bin_msg = options.bin_path orelse "(none)";
1224 const post_llvm_ir_msg = options.post_ir_path orelse "(none)";
1225 const post_llvm_bc_msg = options.post_bc_path orelse "(none)";
12451226 log.debug("emit LLVM object asm={s} bin={s} ir={s} bc={s}", .{
1246 emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,
1227 emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg,
12471228 });
12481229
1249 if (emit_asm_path == null and emit_bin_path == null and
1250 emit_llvm_ir_path == null and emit_llvm_bc_path == null) return;
1230 if (options.asm_path == null and options.bin_path == null and
1231 options.post_ir_path == null and options.post_bc_path == null) return;
12511232
1252 if (!self.builder.useLibLlvm()) {
1253 log.err("emitting without libllvm not implemented", .{});
1254 return error.FailedToEmit;
1255 }
1233 if (!self.builder.useLibLlvm()) unreachable; // caught in Compilation.Config.resolve
12561234
12571235 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
12581236 // So we call the entire pipeline multiple times if this is requested.
12591237 var error_message: [*:0]const u8 = undefined;
1260 if (emit_asm_path != null and emit_bin_path != null) {
1238 var emit_bin_path = options.bin_path;
1239 var post_ir_path = options.post_ir_path;
1240 if (options.asm_path != null and options.bin_path != null) {
12611241 if (self.target_machine.emitToFile(
12621242 self.builder.llvm.module.?,
12631243 &error_message,
1264 comp.bin_file.options.optimize_mode == .Debug,
1265 comp.bin_file.options.optimize_mode == .ReleaseSmall,
1266 comp.time_report,
1267 comp.bin_file.options.tsan,
1268 comp.bin_file.options.lto,
1244 options.is_debug,
1245 options.is_small,
1246 options.time_report,
1247 options.sanitize_thread,
1248 options.lto,
12691249 null,
12701250 emit_bin_path,
1271 emit_llvm_ir_path,
1251 post_ir_path,
12721252 null,
12731253 )) {
12741254 defer llvm.disposeMessage(error_message);
12751255
12761256 log.err("LLVM failed to emit bin={s} ir={s}: {s}", .{
1277 emit_bin_msg, emit_llvm_ir_msg, error_message,
1257 emit_bin_msg, post_llvm_ir_msg, error_message,
12781258 });
12791259 return error.FailedToEmit;
12801260 }
12811261 emit_bin_path = null;
1282 emit_llvm_ir_path = null;
1262 post_ir_path = null;
12831263 }
12841264
12851265 if (self.target_machine.emitToFile(
12861266 self.builder.llvm.module.?,
12871267 &error_message,
1288 comp.bin_file.options.optimize_mode == .Debug,
1289 comp.bin_file.options.optimize_mode == .ReleaseSmall,
1290 comp.time_report,
1291 comp.bin_file.options.tsan,
1292 comp.bin_file.options.lto,
1293 emit_asm_path,
1268 options.is_debug,
1269 options.is_small,
1270 options.time_report,
1271 options.sanitize_thread,
1272 options.lto,
1273 options.asm_path,
12941274 emit_bin_path,
1295 emit_llvm_ir_path,
1296 emit_llvm_bc_path,
1275 post_ir_path,
1276 options.post_bc_path,
12971277 )) {
12981278 defer llvm.disposeMessage(error_message);
12991279
13001280 log.err("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{
1301 emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg,
1281 emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg,
13021282 error_message,
13031283 });
13041284 return error.FailedToEmit;
......@@ -1307,17 +1287,19 @@ pub const Object = struct {
13071287
13081288 pub fn updateFunc(
13091289 o: *Object,
1310 mod: *Module,
1290 zcu: *Module,
13111291 func_index: InternPool.Index,
13121292 air: Air,
13131293 liveness: Liveness,
13141294 ) !void {
1315 const func = mod.funcInfo(func_index);
1295 const func = zcu.funcInfo(func_index);
13161296 const decl_index = func.owner_decl;
1317 const decl = mod.declPtr(decl_index);
1318 const fn_info = mod.typeToFunc(decl.ty).?;
1319 const target = mod.getTarget();
1320 const ip = &mod.intern_pool;
1297 const decl = zcu.declPtr(decl_index);
1298 const namespace = zcu.namespacePtr(decl.src_namespace);
1299 const owner_mod = namespace.file_scope.mod;
1300 const fn_info = zcu.typeToFunc(decl.ty).?;
1301 const target = zcu.getTarget();
1302 const ip = &zcu.intern_pool;
13211303
13221304 var dg: DeclGen = .{
13231305 .object = o,
......@@ -1352,7 +1334,7 @@ pub const Object = struct {
13521334 }
13531335
13541336 // TODO: disable this if safety is off for the function scope
1355 const ssp_buf_size = mod.comp.bin_file.options.stack_protector;
1337 const ssp_buf_size = owner_mod.stack_protector;
13561338 if (ssp_buf_size != 0) {
13571339 try attributes.addFnAttr(.sspstrong, &o.builder);
13581340 try attributes.addFnAttr(.{ .string = .{
......@@ -1362,7 +1344,7 @@ pub const Object = struct {
13621344 }
13631345
13641346 // TODO: disable this if safety is off for the function scope
1365 if (mod.comp.bin_file.options.stack_check) {
1347 if (owner_mod.stack_check) {
13661348 try attributes.addFnAttr(.{ .string = .{
13671349 .kind = try o.builder.string("probe-stack"),
13681350 .value = try o.builder.string("__zig_probe_stack"),
......@@ -1385,20 +1367,22 @@ pub const Object = struct {
13851367 var llvm_arg_i: u32 = 0;
13861368
13871369 // This gets the LLVM values from the function and stores them in `dg.args`.
1388 const sret = firstParamSRet(fn_info, mod);
1370 const sret = firstParamSRet(fn_info, zcu);
13891371 const ret_ptr: Builder.Value = if (sret) param: {
13901372 const param = wip.arg(llvm_arg_i);
13911373 llvm_arg_i += 1;
13921374 break :param param;
13931375 } else .none;
13941376
1395 if (ccAbiPromoteInt(fn_info.cc, mod, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
1377 if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
13961378 .signed => try attributes.addRetAttr(.signext, &o.builder),
13971379 .unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
13981380 };
13991381
1400 const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and
1401 mod.comp.config.any_error_tracing;
1382 const comp = zcu.comp;
1383
1384 const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and
1385 comp.config.any_error_tracing;
14021386
14031387 const err_ret_trace: Builder.Value = if (err_return_tracing) param: {
14041388 const param = wip.arg(llvm_arg_i);
......@@ -1426,8 +1410,8 @@ pub const Object = struct {
14261410 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
14271411 const param = wip.arg(llvm_arg_i);
14281412
1429 if (isByRef(param_ty, mod)) {
1430 const alignment = param_ty.abiAlignment(mod).toLlvm();
1413 if (isByRef(param_ty, zcu)) {
1414 const alignment = param_ty.abiAlignment(zcu).toLlvm();
14311415 const param_llvm_ty = param.typeOfWip(&wip);
14321416 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
14331417 _ = try wip.store(.normal, param, arg_ptr, alignment);
......@@ -1443,12 +1427,12 @@ pub const Object = struct {
14431427 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
14441428 const param_llvm_ty = try o.lowerType(param_ty);
14451429 const param = wip.arg(llvm_arg_i);
1446 const alignment = param_ty.abiAlignment(mod).toLlvm();
1430 const alignment = param_ty.abiAlignment(zcu).toLlvm();
14471431
14481432 try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty);
14491433 llvm_arg_i += 1;
14501434
1451 if (isByRef(param_ty, mod)) {
1435 if (isByRef(param_ty, zcu)) {
14521436 args.appendAssumeCapacity(param);
14531437 } else {
14541438 args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, ""));
......@@ -1458,12 +1442,12 @@ pub const Object = struct {
14581442 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
14591443 const param_llvm_ty = try o.lowerType(param_ty);
14601444 const param = wip.arg(llvm_arg_i);
1461 const alignment = param_ty.abiAlignment(mod).toLlvm();
1445 const alignment = param_ty.abiAlignment(zcu).toLlvm();
14621446
14631447 try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);
14641448 llvm_arg_i += 1;
14651449
1466 if (isByRef(param_ty, mod)) {
1450 if (isByRef(param_ty, zcu)) {
14671451 args.appendAssumeCapacity(param);
14681452 } else {
14691453 args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, ""));
......@@ -1476,11 +1460,11 @@ pub const Object = struct {
14761460 llvm_arg_i += 1;
14771461
14781462 const param_llvm_ty = try o.lowerType(param_ty);
1479 const alignment = param_ty.abiAlignment(mod).toLlvm();
1463 const alignment = param_ty.abiAlignment(zcu).toLlvm();
14801464 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
14811465 _ = try wip.store(.normal, param, arg_ptr, alignment);
14821466
1483 args.appendAssumeCapacity(if (isByRef(param_ty, mod))
1467 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
14841468 arg_ptr
14851469 else
14861470 try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, ""));
......@@ -1488,14 +1472,14 @@ pub const Object = struct {
14881472 .slice => {
14891473 assert(!it.byval_attr);
14901474 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
1491 const ptr_info = param_ty.ptrInfo(mod);
1475 const ptr_info = param_ty.ptrInfo(zcu);
14921476
14931477 if (math.cast(u5, it.zig_index - 1)) |i| {
14941478 if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
14951479 try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder);
14961480 }
14971481 }
1498 if (param_ty.zigTypeTag(mod) != .Optional) {
1482 if (param_ty.zigTypeTag(zcu) != .Optional) {
14991483 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
15001484 }
15011485 if (ptr_info.flags.is_const) {
......@@ -1504,7 +1488,7 @@ pub const Object = struct {
15041488 const elem_align = (if (ptr_info.flags.alignment != .none)
15051489 @as(InternPool.Alignment, ptr_info.flags.alignment)
15061490 else
1507 Type.fromInterned(ptr_info.child).abiAlignment(mod).max(.@"1")).toLlvm();
1491 Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1")).toLlvm();
15081492 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder);
15091493 const ptr_param = wip.arg(llvm_arg_i);
15101494 llvm_arg_i += 1;
......@@ -1521,7 +1505,7 @@ pub const Object = struct {
15211505 const field_types = it.types_buffer[0..it.types_len];
15221506 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
15231507 const param_llvm_ty = try o.lowerType(param_ty);
1524 const param_alignment = param_ty.abiAlignment(mod).toLlvm();
1508 const param_alignment = param_ty.abiAlignment(zcu).toLlvm();
15251509 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, param_alignment, target);
15261510 const llvm_ty = try o.builder.structType(.normal, field_types);
15271511 for (0..field_types.len) |field_i| {
......@@ -1533,7 +1517,7 @@ pub const Object = struct {
15331517 _ = try wip.store(.normal, param, field_ptr, alignment);
15341518 }
15351519
1536 const is_by_ref = isByRef(param_ty, mod);
1520 const is_by_ref = isByRef(param_ty, zcu);
15371521 args.appendAssumeCapacity(if (is_by_ref)
15381522 arg_ptr
15391523 else
......@@ -1551,11 +1535,11 @@ pub const Object = struct {
15511535 const param = wip.arg(llvm_arg_i);
15521536 llvm_arg_i += 1;
15531537
1554 const alignment = param_ty.abiAlignment(mod).toLlvm();
1538 const alignment = param_ty.abiAlignment(zcu).toLlvm();
15551539 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
15561540 _ = try wip.store(.normal, param, arg_ptr, alignment);
15571541
1558 args.appendAssumeCapacity(if (isByRef(param_ty, mod))
1542 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
15591543 arg_ptr
15601544 else
15611545 try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, ""));
......@@ -1566,11 +1550,11 @@ pub const Object = struct {
15661550 const param = wip.arg(llvm_arg_i);
15671551 llvm_arg_i += 1;
15681552
1569 const alignment = param_ty.abiAlignment(mod).toLlvm();
1553 const alignment = param_ty.abiAlignment(zcu).toLlvm();
15701554 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
15711555 _ = try wip.store(.normal, param, arg_ptr, alignment);
15721556
1573 args.appendAssumeCapacity(if (isByRef(param_ty, mod))
1557 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
15741558 arg_ptr
15751559 else
15761560 try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, ""));
......@@ -1584,14 +1568,12 @@ pub const Object = struct {
15841568 var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null;
15851569 var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null;
15861570
1587 const namespace = mod.namespacePtr(decl.src_namespace);
1588
15891571 if (o.di_builder) |dib| {
15901572 di_file = try o.getDIFile(gpa, namespace.file_scope);
15911573
15921574 const line_number = decl.src_line + 1;
1593 const is_internal_linkage = decl.val.getExternFunc(mod) == null and
1594 !mod.decl_exports.contains(decl_index);
1575 const is_internal_linkage = decl.val.getExternFunc(zcu) == null and
1576 !zcu.decl_exports.contains(decl_index);
15951577 const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)
15961578 llvm.DIFlags.NoReturn
15971579 else
......@@ -1608,7 +1590,7 @@ pub const Object = struct {
16081590 true, // is definition
16091591 line_number + func.lbrace_line, // scope line
16101592 llvm.DIFlags.StaticMember | noret_bit,
1611 mod.comp.bin_file.options.optimize_mode != .Debug,
1593 owner_mod.optimize_mode != .Debug,
16121594 null, // decl_subprogram
16131595 );
16141596 try o.di_map.put(gpa, decl, subprogram.toNode());
......@@ -1618,8 +1600,6 @@ pub const Object = struct {
16181600 di_scope = subprogram.toScope();
16191601 }
16201602
1621 const single_threaded = namespace.file_scope.mod.single_threaded;
1622
16231603 var fg: FuncGen = .{
16241604 .gpa = gpa,
16251605 .air = air,
......@@ -1631,7 +1611,7 @@ pub const Object = struct {
16311611 .arg_index = 0,
16321612 .func_inst_table = .{},
16331613 .blocks = .{},
1634 .sync_scope = if (single_threaded) .singlethread else .system,
1614 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
16351615 .di_scope = di_scope,
16361616 .di_file = di_file,
16371617 .base_line = dg.decl.src_line,
......@@ -1645,7 +1625,7 @@ pub const Object = struct {
16451625 fg.genBody(air.getMainBody()) catch |err| switch (err) {
16461626 error.CodegenFail => {
16471627 decl.analysis = .codegen_failure;
1648 try mod.failed_decls.put(mod.gpa, decl_index, dg.err_msg.?);
1628 try zcu.failed_decls.put(zcu.gpa, decl_index, dg.err_msg.?);
16491629 dg.err_msg = null;
16501630 return;
16511631 },
......@@ -1654,7 +1634,7 @@ pub const Object = struct {
16541634
16551635 try fg.wip.finish();
16561636
1657 try o.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
1637 try o.updateExports(zcu, .{ .decl_index = decl_index }, zcu.getDeclExports(decl_index));
16581638 }
16591639
16601640 pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void {
......@@ -2933,22 +2913,24 @@ pub const Object = struct {
29332913 o: *Object,
29342914 decl_index: InternPool.DeclIndex,
29352915 ) Allocator.Error!Builder.Function.Index {
2936 const mod = o.module;
2937 const ip = &mod.intern_pool;
2916 const zcu = o.module;
2917 const ip = &zcu.intern_pool;
29382918 const gpa = o.gpa;
2939 const decl = mod.declPtr(decl_index);
2919 const decl = zcu.declPtr(decl_index);
2920 const namespace = zcu.namespacePtr(decl.src_namespace);
2921 const owner_mod = namespace.file_scope.mod;
29402922 const zig_fn_type = decl.ty;
29412923 const gop = try o.decl_map.getOrPut(gpa, decl_index);
29422924 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;
29432925
29442926 assert(decl.has_tv);
2945 const fn_info = mod.typeToFunc(zig_fn_type).?;
2946 const target = mod.getTarget();
2947 const sret = firstParamSRet(fn_info, mod);
2927 const fn_info = zcu.typeToFunc(zig_fn_type).?;
2928 const target = owner_mod.resolved_target.result;
2929 const sret = firstParamSRet(fn_info, zcu);
29482930
29492931 const function_index = try o.builder.addFunction(
29502932 try o.lowerType(zig_fn_type),
2951 try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))),
2933 try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(zcu))),
29522934 toLlvmAddressSpace(decl.@"addrspace", target),
29532935 );
29542936 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
......@@ -2956,7 +2938,7 @@ pub const Object = struct {
29562938 var attributes: Builder.FunctionAttributes.Wip = .{};
29572939 defer attributes.deinit(&o.builder);
29582940
2959 const is_extern = decl.isExtern(mod);
2941 const is_extern = decl.isExtern(zcu);
29602942 if (!is_extern) {
29612943 function_index.setLinkage(.internal, &o.builder);
29622944 function_index.setUnnamedAddr(.unnamed_addr, &o.builder);
......@@ -2966,7 +2948,7 @@ pub const Object = struct {
29662948 .kind = try o.builder.string("wasm-import-name"),
29672949 .value = try o.builder.string(ip.stringToSlice(decl.name)),
29682950 } }, &o.builder);
2969 if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
2951 if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(zcu).?.lib_name)) |lib_name| {
29702952 if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{
29712953 .kind = try o.builder.string("wasm-import-module"),
29722954 .value = try o.builder.string(lib_name),
......@@ -2987,8 +2969,8 @@ pub const Object = struct {
29872969 llvm_arg_i += 1;
29882970 }
29892971
2990 const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and
2991 mod.comp.config.any_error_tracing;
2972 const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and
2973 zcu.comp.config.any_error_tracing;
29922974
29932975 if (err_return_tracing) {
29942976 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
......@@ -3009,7 +2991,7 @@ pub const Object = struct {
30092991 function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder);
30102992
30112993 // Function attributes that are independent of analysis results of the function body.
3012 try o.addCommonFnAttributes(&attributes);
2994 try o.addCommonFnAttributes(&attributes, owner_mod);
30132995
30142996 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
30152997
......@@ -3022,14 +3004,14 @@ pub const Object = struct {
30223004 .byval => {
30233005 const param_index = it.zig_index - 1;
30243006 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
3025 if (!isByRef(param_ty, mod)) {
3007 if (!isByRef(param_ty, zcu)) {
30263008 try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
30273009 }
30283010 },
30293011 .byref => {
30303012 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
30313013 const param_llvm_ty = try o.lowerType(param_ty);
3032 const alignment = param_ty.abiAlignment(mod);
3014 const alignment = param_ty.abiAlignment(zcu);
30333015 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty);
30343016 },
30353017 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
......@@ -3055,13 +3037,14 @@ pub const Object = struct {
30553037 fn addCommonFnAttributes(
30563038 o: *Object,
30573039 attributes: *Builder.FunctionAttributes.Wip,
3040 owner_mod: *Package.Module,
30583041 ) Allocator.Error!void {
30593042 const comp = o.module.comp;
30603043
3061 if (!comp.bin_file.options.red_zone) {
3044 if (!owner_mod.red_zone) {
30623045 try attributes.addFnAttr(.noredzone, &o.builder);
30633046 }
3064 if (comp.bin_file.options.omit_frame_pointer) {
3047 if (owner_mod.omit_frame_pointer) {
30653048 try attributes.addFnAttr(.{ .string = .{
30663049 .kind = try o.builder.string("frame-pointer"),
30673050 .value = try o.builder.string("none"),
......@@ -3073,7 +3056,7 @@ pub const Object = struct {
30733056 } }, &o.builder);
30743057 }
30753058 try attributes.addFnAttr(.nounwind, &o.builder);
3076 if (comp.unwind_tables) {
3059 if (owner_mod.unwind_tables) {
30773060 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
30783061 }
30793062 if (comp.skip_linker_dependencies or comp.no_builtin) {
......@@ -3084,26 +3067,27 @@ pub const Object = struct {
30843067 // overflow instead of performing memcpy.
30853068 try attributes.addFnAttr(.nobuiltin, &o.builder);
30863069 }
3087 if (comp.bin_file.options.optimize_mode == .ReleaseSmall) {
3070 if (owner_mod.optimize_mode == .ReleaseSmall) {
30883071 try attributes.addFnAttr(.minsize, &o.builder);
30893072 try attributes.addFnAttr(.optsize, &o.builder);
30903073 }
3091 if (comp.bin_file.options.tsan) {
3074 if (owner_mod.sanitize_thread) {
30923075 try attributes.addFnAttr(.sanitize_thread, &o.builder);
30933076 }
3094 if (comp.getTarget().cpu.model.llvm_name) |s| {
3077 const target = owner_mod.resolved_target.result;
3078 if (target.cpu.model.llvm_name) |s| {
30953079 try attributes.addFnAttr(.{ .string = .{
30963080 .kind = try o.builder.string("target-cpu"),
30973081 .value = try o.builder.string(s),
30983082 } }, &o.builder);
30993083 }
3100 if (comp.bin_file.options.llvm_cpu_features) |s| {
3084 if (owner_mod.resolved_target.llvm_cpu_features) |s| {
31013085 try attributes.addFnAttr(.{ .string = .{
31023086 .kind = try o.builder.string("target-features"),
31033087 .value = try o.builder.string(std.mem.span(s)),
31043088 } }, &o.builder);
31053089 }
3106 if (comp.getTarget().cpu.arch.isBpf()) {
3090 if (target.cpu.arch.isBpf()) {
31073091 try attributes.addFnAttr(.{ .string = .{
31083092 .kind = try o.builder.string("no-builtins"),
31093093 .value = .empty,
......@@ -4646,6 +4630,100 @@ pub const Object = struct {
46464630 .field_index = @intCast(field_index),
46474631 });
46484632 }
4633
4634 fn getCmpLtErrorsLenFunction(o: *Object) !Builder.Function.Index {
4635 const name = try o.builder.string(lt_errors_fn_name);
4636 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
4637
4638 const zcu = o.module;
4639 const target = zcu.root_mod.resolved_target.result;
4640 const function_index = try o.builder.addFunction(
4641 try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal),
4642 name,
4643 toLlvmAddressSpace(.generic, target),
4644 );
4645
4646 var attributes: Builder.FunctionAttributes.Wip = .{};
4647 defer attributes.deinit(&o.builder);
4648 try o.addCommonFnAttributes(&attributes, zcu.root_mod);
4649
4650 function_index.setLinkage(.internal, &o.builder);
4651 function_index.setCallConv(.fastcc, &o.builder);
4652 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
4653 return function_index;
4654 }
4655
4656 fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index {
4657 const zcu = o.module;
4658 const ip = &zcu.intern_pool;
4659 const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type;
4660
4661 // TODO: detect when the type changes and re-emit this function.
4662 const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);
4663 if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function;
4664 errdefer assert(o.decl_map.remove(enum_type.decl));
4665
4666 const usize_ty = try o.lowerType(Type.usize);
4667 const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
4668 const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu);
4669 const target = zcu.root_mod.resolved_target.result;
4670 const function_index = try o.builder.addFunction(
4671 try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
4672 try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
4673 toLlvmAddressSpace(.generic, target),
4674 );
4675
4676 var attributes: Builder.FunctionAttributes.Wip = .{};
4677 defer attributes.deinit(&o.builder);
4678 try o.addCommonFnAttributes(&attributes, zcu.root_mod);
4679
4680 function_index.setLinkage(.internal, &o.builder);
4681 function_index.setCallConv(.fastcc, &o.builder);
4682 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
4683 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
4684
4685 var wip = try Builder.WipFunction.init(&o.builder, function_index);
4686 defer wip.deinit();
4687 wip.cursor = .{ .block = try wip.block(0, "Entry") };
4688
4689 const bad_value_block = try wip.block(1, "BadValue");
4690 const tag_int_value = wip.arg(0);
4691 var wip_switch =
4692 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
4693 defer wip_switch.finish(&wip);
4694
4695 for (0..enum_type.names.len) |field_index| {
4696 const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index]));
4697 const name_init = try o.builder.stringNullConst(name);
4698 const name_variable_index =
4699 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
4700 try name_variable_index.setInitializer(name_init, &o.builder);
4701 name_variable_index.setLinkage(.private, &o.builder);
4702 name_variable_index.setMutability(.constant, &o.builder);
4703 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
4704 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
4705
4706 const name_val = try o.builder.structValue(ret_ty, &.{
4707 name_variable_index.toConst(&o.builder),
4708 try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len),
4709 });
4710
4711 const return_block = try wip.block(1, "Name");
4712 const this_tag_int_value = try o.lowerValue(
4713 (try zcu.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
4714 );
4715 try wip_switch.addCase(this_tag_int_value, return_block, &wip);
4716
4717 wip.cursor = .{ .block = return_block };
4718 _ = try wip.ret(name_val);
4719 }
4720
4721 wip.cursor = .{ .block = bad_value_block };
4722 _ = try wip.@"unreachable"();
4723
4724 try wip.finish();
4725 return function_index;
4726 }
46494727};
46504728
46514729pub const DeclGen = struct {
......@@ -4654,6 +4732,13 @@ pub const DeclGen = struct {
46544732 decl_index: InternPool.DeclIndex,
46554733 err_msg: ?*Module.ErrorMsg,
46564734
4735 fn ownerModule(dg: DeclGen) *Package.Module {
4736 const o = dg.object;
4737 const zcu = o.module;
4738 const namespace = zcu.namespacePtr(dg.decl.src_namespace);
4739 return namespace.file_scope.mod;
4740 }
4741
46574742 fn todo(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
46584743 @setCold(true);
46594744 assert(dg.err_msg == null);
......@@ -5614,7 +5699,7 @@ pub const FuncGen = struct {
56145699 const o = self.dg.object;
56155700 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
56165701 const operand = try self.resolveInst(un_op);
5617 const llvm_fn = try self.getCmpLtErrorsLenFunction();
5702 const llvm_fn = try o.getCmpLtErrorsLenFunction();
56185703 return self.wip.call(
56195704 .normal,
56205705 .fastcc,
......@@ -6547,11 +6632,13 @@ pub const FuncGen = struct {
65476632 const dib = o.di_builder orelse return .none;
65486633 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
65496634
6550 const mod = o.module;
6551 const func = mod.funcInfo(ty_fn.func);
6635 const zcu = o.module;
6636 const func = zcu.funcInfo(ty_fn.func);
65526637 const decl_index = func.owner_decl;
6553 const decl = mod.declPtr(decl_index);
6554 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
6638 const decl = zcu.declPtr(decl_index);
6639 const namespace = zcu.namespacePtr(decl.src_namespace);
6640 const owner_mod = namespace.file_scope.mod;
6641 const di_file = try o.getDIFile(self.gpa, zcu.namespacePtr(decl.src_namespace).file_scope);
65556642 self.di_file = di_file;
65566643 const line_number = decl.src_line + 1;
65576644 const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2();
......@@ -6562,18 +6649,18 @@ pub const FuncGen = struct {
65626649 .base_line = self.base_line,
65636650 });
65646651
6565 const fqn = try decl.getFullyQualifiedName(mod);
6652 const fqn = try decl.getFullyQualifiedName(zcu);
65666653
6567 const is_internal_linkage = !mod.decl_exports.contains(decl_index);
6568 const fn_ty = try mod.funcType(.{
6654 const is_internal_linkage = !zcu.decl_exports.contains(decl_index);
6655 const fn_ty = try zcu.funcType(.{
65696656 .param_types = &.{},
65706657 .return_type = .void_type,
65716658 });
65726659 const fn_di_ty = try o.lowerDebugType(fn_ty, .full);
65736660 const subprogram = dib.createFunction(
65746661 di_file.toScope(),
6575 mod.intern_pool.stringToSlice(decl.name),
6576 mod.intern_pool.stringToSlice(fqn),
6662 zcu.intern_pool.stringToSlice(decl.name),
6663 zcu.intern_pool.stringToSlice(fqn),
65776664 di_file,
65786665 line_number,
65796666 fn_di_ty,
......@@ -6581,7 +6668,7 @@ pub const FuncGen = struct {
65816668 true, // is definition
65826669 line_number + func.lbrace_line, // scope line
65836670 llvm.DIFlags.StaticMember,
6584 mod.comp.bin_file.options.optimize_mode != .Debug,
6671 owner_mod.optimize_mode != .Debug,
65856672 null, // decl_subprogram
65866673 );
65876674
......@@ -6676,11 +6763,12 @@ pub const FuncGen = struct {
66766763 null;
66776764 const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);
66786765 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);
6679 const mod = o.module;
6680 if (isByRef(operand_ty, mod)) {
6766 const zcu = o.module;
6767 const owner_mod = self.dg.ownerModule();
6768 if (isByRef(operand_ty, zcu)) {
66816769 _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
6682 } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) {
6683 const alignment = operand_ty.abiAlignment(mod).toLlvm();
6770 } else if (owner_mod.optimize_mode == .Debug) {
6771 const alignment = operand_ty.abiAlignment(zcu).toLlvm();
66846772 const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);
66856773 _ = try self.wip.store(.normal, operand, alloca, alignment);
66866774 _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
......@@ -8729,9 +8817,10 @@ pub const FuncGen = struct {
87298817
87308818 const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null);
87318819 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);
8820 const owner_mod = self.dg.ownerModule();
87328821 if (isByRef(inst_ty, mod)) {
87338822 _ = dib.insertDeclareAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
8734 } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) {
8823 } else if (owner_mod.optimize_mode == .Debug) {
87358824 const alignment = inst_ty.abiAlignment(mod).toLlvm();
87368825 const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment);
87378826 _ = try self.wip.store(.normal, arg_val, alloca, alignment);
......@@ -8821,7 +8910,8 @@ pub const FuncGen = struct {
88218910 len,
88228911 if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal,
88238912 );
8824 if (safety and mod.comp.bin_file.options.valgrind) {
8913 const owner_mod = self.dg.ownerModule();
8914 if (safety and owner_mod.valgrind) {
88258915 try self.valgrindMarkUndef(dest_ptr, len);
88268916 }
88278917 return .none;
......@@ -9137,7 +9227,8 @@ pub const FuncGen = struct {
91379227 } else {
91389228 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
91399229 }
9140 if (safety and mod.comp.bin_file.options.valgrind) {
9230 const owner_mod = self.dg.ownerModule();
9231 if (safety and owner_mod.valgrind) {
91419232 try self.valgrindMarkUndef(dest_ptr, len);
91429233 }
91439234 return .none;
......@@ -9488,24 +9579,25 @@ pub const FuncGen = struct {
94889579
94899580 fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {
94909581 const o = self.dg.object;
9491 const mod = o.module;
9492 const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type;
9582 const zcu = o.module;
9583 const enum_type = zcu.intern_pool.indexToKey(enum_ty.toIntern()).enum_type;
94939584
94949585 // TODO: detect when the type changes and re-emit this function.
94959586 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl);
94969587 if (gop.found_existing) return gop.value_ptr.*;
94979588 errdefer assert(o.named_enum_map.remove(enum_type.decl));
94989589
9499 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
9590 const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu);
9591 const target = zcu.root_mod.resolved_target.result;
95009592 const function_index = try o.builder.addFunction(
95019593 try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
9502 try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}),
9503 toLlvmAddressSpace(.generic, mod.getTarget()),
9594 try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}),
9595 toLlvmAddressSpace(.generic, target),
95049596 );
95059597
95069598 var attributes: Builder.FunctionAttributes.Wip = .{};
95079599 defer attributes.deinit(&o.builder);
9508 try o.addCommonFnAttributes(&attributes);
9600 try o.addCommonFnAttributes(&attributes, zcu.root_mod);
95099601
95109602 function_index.setLinkage(.internal, &o.builder);
95119603 function_index.setCallConv(.fastcc, &o.builder);
......@@ -9524,7 +9616,7 @@ pub const FuncGen = struct {
95249616
95259617 for (0..enum_type.names.len) |field_index| {
95269618 const this_tag_int_value = try o.lowerValue(
9527 (try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
9619 (try zcu.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
95289620 );
95299621 try wip_switch.addCase(this_tag_int_value, named_block, &wip);
95309622 }
......@@ -9544,7 +9636,7 @@ pub const FuncGen = struct {
95449636 const operand = try self.resolveInst(un_op);
95459637 const enum_ty = self.typeOf(un_op);
95469638
9547 const llvm_fn = try self.getEnumTagNameFunction(enum_ty);
9639 const llvm_fn = try o.getEnumTagNameFunction(enum_ty);
95489640 return self.wip.call(
95499641 .normal,
95509642 .fastcc,
......@@ -9556,100 +9648,6 @@ pub const FuncGen = struct {
95569648 );
95579649 }
95589650
9559 fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {
9560 const o = self.dg.object;
9561 const mod = o.module;
9562 const ip = &mod.intern_pool;
9563 const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type;
9564
9565 // TODO: detect when the type changes and re-emit this function.
9566 const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);
9567 if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function;
9568 errdefer assert(o.decl_map.remove(enum_type.decl));
9569
9570 const usize_ty = try o.lowerType(Type.usize);
9571 const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
9572 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
9573 const function_index = try o.builder.addFunction(
9574 try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
9575 try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
9576 toLlvmAddressSpace(.generic, mod.getTarget()),
9577 );
9578
9579 var attributes: Builder.FunctionAttributes.Wip = .{};
9580 defer attributes.deinit(&o.builder);
9581 try o.addCommonFnAttributes(&attributes);
9582
9583 function_index.setLinkage(.internal, &o.builder);
9584 function_index.setCallConv(.fastcc, &o.builder);
9585 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9586 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
9587
9588 var wip = try Builder.WipFunction.init(&o.builder, function_index);
9589 defer wip.deinit();
9590 wip.cursor = .{ .block = try wip.block(0, "Entry") };
9591
9592 const bad_value_block = try wip.block(1, "BadValue");
9593 const tag_int_value = wip.arg(0);
9594 var wip_switch =
9595 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
9596 defer wip_switch.finish(&wip);
9597
9598 for (0..enum_type.names.len) |field_index| {
9599 const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index]));
9600 const name_init = try o.builder.stringNullConst(name);
9601 const name_variable_index =
9602 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
9603 try name_variable_index.setInitializer(name_init, &o.builder);
9604 name_variable_index.setLinkage(.private, &o.builder);
9605 name_variable_index.setMutability(.constant, &o.builder);
9606 name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
9607 name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder);
9608
9609 const name_val = try o.builder.structValue(ret_ty, &.{
9610 name_variable_index.toConst(&o.builder),
9611 try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len),
9612 });
9613
9614 const return_block = try wip.block(1, "Name");
9615 const this_tag_int_value = try o.lowerValue(
9616 (try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
9617 );
9618 try wip_switch.addCase(this_tag_int_value, return_block, &wip);
9619
9620 wip.cursor = .{ .block = return_block };
9621 _ = try wip.ret(name_val);
9622 }
9623
9624 wip.cursor = .{ .block = bad_value_block };
9625 _ = try wip.@"unreachable"();
9626
9627 try wip.finish();
9628 return function_index;
9629 }
9630
9631 fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index {
9632 const o = self.dg.object;
9633
9634 const name = try o.builder.string(lt_errors_fn_name);
9635 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
9636
9637 const function_index = try o.builder.addFunction(
9638 try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal),
9639 name,
9640 toLlvmAddressSpace(.generic, o.module.getTarget()),
9641 );
9642
9643 var attributes: Builder.FunctionAttributes.Wip = .{};
9644 defer attributes.deinit(&o.builder);
9645 try o.addCommonFnAttributes(&attributes);
9646
9647 function_index.setLinkage(.internal, &o.builder);
9648 function_index.setCallConv(.fastcc, &o.builder);
9649 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
9650 return function_index;
9651 }
9652
96539651 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
96549652 const o = self.dg.object;
96559653 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
src/link.zig+46
......@@ -18,6 +18,7 @@ const Module = @import("Module.zig");
1818const InternPool = @import("InternPool.zig");
1919const Type = @import("type.zig").Type;
2020const TypedValue = @import("TypedValue.zig");
21const LlvmObject = @import("codegen/llvm.zig").Object;
2122
2223/// When adding a new field, remember to update `hashAddSystemLibs`.
2324/// These are *always* dynamically linked. Static libraries will be
......@@ -1046,6 +1047,51 @@ pub const File = struct {
10461047 return output_mode == .Lib and !self.isStatic();
10471048 }
10481049
1050 pub fn resolveEmitLoc(
1051 base: File,
1052 arena: Allocator,
1053 opt_loc: ?Compilation.EmitLoc,
1054 ) Allocator.Error!?[*:0]u8 {
1055 const loc = opt_loc orelse return null;
1056 const slice = if (loc.directory) |directory|
1057 try directory.joinZ(arena, &.{loc.basename})
1058 else
1059 try base.emit.basenamePath(arena, loc.basename);
1060 return slice.ptr;
1061 }
1062
1063 pub fn emitLlvmObject(
1064 base: File,
1065 arena: Allocator,
1066 llvm_object: *LlvmObject,
1067 prog_node: *std.Progress.Node,
1068 ) !void {
1069 const comp = base.comp;
1070
1071 var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
1072 sub_prog_node.activate();
1073 sub_prog_node.context.refresh();
1074 defer sub_prog_node.end();
1075
1076 try llvm_object.emit(comp, .{
1077 .pre_ir_path = comp.verbose_llvm_ir,
1078 .pre_bc_path = comp.verbose_llvm_bc,
1079 .bin_path = try base.resolveEmitLoc(arena, .{
1080 .directory = null,
1081 .basename = base.intermediary_basename.?,
1082 }),
1083 .asm_path = try base.resolveEmitLoc(arena, comp.emit_asm),
1084 .post_llvm_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir),
1085 .post_llvm_bc_path = try base.resolveEmitLoc(arena, comp.emit_llvm_bc),
1086
1087 .is_debug = comp.root_mod.optimize_mode == .Debug,
1088 .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
1089 .time_report = comp.time_report,
1090 .sanitize_thread = comp.config.any_sanitize_thread,
1091 .lto = comp.config.lto,
1092 });
1093 }
1094
10491095 pub const C = @import("link/C.zig");
10501096 pub const Coff = @import("link/Coff.zig");
10511097 pub const Plan9 = @import("link/Plan9.zig");
src/link/Coff.zig+11-6
......@@ -3,7 +3,7 @@
33//! LLD for traditional linking (linking relocatable object files).
44//! LLD is also the default linker for LLVM.
55
6/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
6/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename.
77llvm_object: ?*LlvmObject = null,
88
99base: link.File,
......@@ -1711,17 +1711,22 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
17111711 const tracy = trace(@src());
17121712 defer tracy.end();
17131713
1714 const gpa = comp.gpa;
1715
17141716 if (self.llvm_object) |llvm_object| {
1715 return try llvm_object.flushModule(comp, prog_node);
1717 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
1718 defer arena_allocator.deinit();
1719 const arena = arena_allocator.allocator();
1720
1721 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
1722 return;
17161723 }
17171724
17181725 var sub_prog_node = prog_node.start("COFF Flush", 0);
17191726 sub_prog_node.activate();
17201727 defer sub_prog_node.end();
17211728
1722 const gpa = self.base.comp.gpa;
1723
1724 const module = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
1729 const module = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
17251730
17261731 if (self.lazy_syms.getPtr(.none)) |metadata| {
17271732 // Most lazy symbols can be updated on first use, but
......@@ -1822,7 +1827,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
18221827 try self.writeDataDirectoriesHeaders();
18231828 try self.writeSectionHeaders();
18241829
1825 if (self.entry_addr == null and self.base.comp.config.output_mode == .Exe) {
1830 if (self.entry_addr == null and comp.config.output_mode == .Exe) {
18261831 log.debug("flushing. no_entry_point_found = true\n", .{});
18271832 self.base.error_flags.no_entry_point_found = true;
18281833 } else {
src/link/Elf.zig+23-24
......@@ -27,7 +27,7 @@ version_script: ?[]const u8,
2727
2828ptr_width: PtrWidth,
2929
30/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
30/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename.
3131llvm_object: ?*LlvmObject = null,
3232
3333/// A list of all input files.
......@@ -1031,24 +1031,23 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10311031 const tracy = trace(@src());
10321032 defer tracy.end();
10331033
1034 if (self.llvm_object) |llvm_object| {
1035 try llvm_object.flushModule(comp, prog_node);
1034 const gpa = comp.gpa;
1035 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
1036 defer arena_allocator.deinit();
1037 const arena = arena_allocator.allocator();
10361038
1037 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
1039 if (self.llvm_object) |llvm_object| {
1040 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
1041 const use_lld = build_options.have_llvm and comp.config.use_lld;
10381042 if (use_lld) return;
10391043 }
10401044
1041 const gpa = self.base.comp.gpa;
10421045 var sub_prog_node = prog_node.start("ELF Flush", 0);
10431046 sub_prog_node.activate();
10441047 defer sub_prog_node.end();
10451048
1046 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
1047 defer arena_allocator.deinit();
1048 const arena = arena_allocator.allocator();
1049
1050 const target = self.base.comp.root_mod.resolved_target.result;
1051 const link_mode = self.base.comp.config.link_mode;
1049 const target = comp.root_mod.resolved_target.result;
1050 const link_mode = comp.config.link_mode;
10521051 const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
10531052 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
10541053 const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: {
......@@ -1060,7 +1059,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10601059 } else null;
10611060
10621061 // --verbose-link
1063 if (self.base.comp.verbose_link) try self.dumpArgv(comp);
1062 if (comp.verbose_link) try self.dumpArgv(comp);
10641063
10651064 const csu = try CsuObjects.init(arena, comp);
10661065 const compiler_rt_path: ?[]const u8 = blk: {
......@@ -1082,8 +1081,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10821081 if (csu.crti) |v| try positionals.append(.{ .path = v });
10831082 if (csu.crtbegin) |v| try positionals.append(.{ .path = v });
10841083
1085 try positionals.ensureUnusedCapacity(self.base.comp.objects.len);
1086 positionals.appendSliceAssumeCapacity(self.base.comp.objects);
1084 try positionals.ensureUnusedCapacity(comp.objects.len);
1085 positionals.appendSliceAssumeCapacity(comp.objects);
10871086
10881087 // This is a set of object files emitted by clang in a single `build-exe` invocation.
10891088 // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up
......@@ -1106,13 +1105,13 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11061105 var test_path = std.ArrayList(u8).init(gpa);
11071106 defer test_path.deinit();
11081107 for (self.lib_dirs) |lib_dir_path| {
1109 for (self.base.comp.system_libs.keys()) |link_lib| {
1108 for (comp.system_libs.keys()) |link_lib| {
11101109 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
11111110 continue;
11121111 _ = try rpath_table.put(lib_dir_path, {});
11131112 }
11141113 }
1115 for (self.base.comp.objects) |obj| {
1114 for (comp.objects) |obj| {
11161115 if (Compilation.classifyFileExt(obj.path) == .shared_library) {
11171116 const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue;
11181117 if (obj.loption) continue;
......@@ -1122,7 +1121,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11221121 }
11231122
11241123 // TSAN
1125 if (self.base.comp.config.any_sanitize_thread) {
1124 if (comp.config.any_sanitize_thread) {
11261125 try positionals.append(.{ .path = comp.tsan_static_lib.?.full_object_path });
11271126 }
11281127
......@@ -1146,27 +1145,27 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11461145
11471146 var system_libs = std.ArrayList(SystemLib).init(arena);
11481147
1149 try system_libs.ensureUnusedCapacity(self.base.comp.system_libs.values().len);
1150 for (self.base.comp.system_libs.values()) |lib_info| {
1148 try system_libs.ensureUnusedCapacity(comp.system_libs.values().len);
1149 for (comp.system_libs.values()) |lib_info| {
11511150 system_libs.appendAssumeCapacity(.{ .needed = lib_info.needed, .path = lib_info.path.? });
11521151 }
11531152
11541153 // libc++ dep
1155 if (self.base.comp.config.link_libcpp) {
1154 if (comp.config.link_libcpp) {
11561155 try system_libs.ensureUnusedCapacity(2);
11571156 system_libs.appendAssumeCapacity(.{ .path = comp.libcxxabi_static_lib.?.full_object_path });
11581157 system_libs.appendAssumeCapacity(.{ .path = comp.libcxx_static_lib.?.full_object_path });
11591158 }
11601159
11611160 // libunwind dep
1162 if (self.base.comp.config.link_libunwind) {
1161 if (comp.config.link_libunwind) {
11631162 try system_libs.append(.{ .path = comp.libunwind_static_lib.?.full_object_path });
11641163 }
11651164
11661165 // libc dep
11671166 self.base.error_flags.missing_libc = false;
1168 if (self.base.comp.config.link_libc) {
1169 if (self.base.comp.libc_installation) |lc| {
1167 if (comp.config.link_libc) {
1168 if (comp.libc_installation) |lc| {
11701169 const flags = target_util.libcFullLinkFlags(target);
11711170 try system_libs.ensureUnusedCapacity(flags.len);
11721171
......@@ -1305,7 +1304,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
13051304 // Look for entry address in objects if not set by the incremental compiler.
13061305 if (self.entry_index == null) {
13071306 const entry: ?[]const u8 = entry: {
1308 if (self.base.comp.config.entry) |entry| break :entry entry;
1307 if (comp.config.entry) |entry| break :entry entry;
13091308 if (!self.base.isDynLib()) break :entry "_start";
13101309 break :entry null;
13111310 };
src/link/Elf/Symbol.zig+3-3
......@@ -43,7 +43,7 @@ pub fn outputShndx(symbol: Symbol) ?u16 {
4343}
4444
4545pub fn isLocal(symbol: Symbol, elf_file: *Elf) bool {
46 if (elf_file.isRelocatable()) return symbol.elfSym(elf_file).st_bind() == elf.STB_LOCAL;
46 if (elf_file.base.isRelocatable()) return symbol.elfSym(elf_file).st_bind() == elf.STB_LOCAL;
4747 return !(symbol.flags.import or symbol.flags.@"export");
4848}
4949
......@@ -186,7 +186,7 @@ const GetOrCreateZigGotEntryResult = struct {
186186};
187187
188188pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult {
189 assert(!elf_file.isRelocatable());
189 assert(!elf_file.base.isRelocatable());
190190 assert(symbol.flags.needs_zig_got);
191191 if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).?.zig_got };
192192 const index = try elf_file.zig_got.addSymbol(symbol_index, elf_file);
......@@ -237,7 +237,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
237237 const st_shndx = blk: {
238238 if (symbol.flags.has_copy_rel) break :blk elf_file.copy_rel_section_index.?;
239239 if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;
240 if (elf_file.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;
240 if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;
241241 if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS;
242242 break :blk symbol.outputShndx() orelse elf.SHN_UNDEF;
243243 };
src/link/Elf/ZigObject.zig+3-3
......@@ -926,7 +926,7 @@ fn updateDeclCode(
926926 sym.value = atom_ptr.value;
927927 esym.st_value = atom_ptr.value;
928928
929 if (!elf_file.isRelocatable()) {
929 if (!elf_file.base.isRelocatable()) {
930930 log.debug(" (writing new offset table entry)", .{});
931931 assert(sym.flags.has_zig_got);
932932 const extra = sym.extra(elf_file).?;
......@@ -944,7 +944,7 @@ fn updateDeclCode(
944944 sym.flags.needs_zig_got = true;
945945 esym.st_value = atom_ptr.value;
946946
947 if (!elf_file.isRelocatable()) {
947 if (!elf_file.base.isRelocatable()) {
948948 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
949949 try elf_file.zig_got.writeOne(elf_file, gop.index);
950950 }
......@@ -1262,7 +1262,7 @@ fn updateLazySymbol(
12621262 local_sym.flags.needs_zig_got = true;
12631263 local_esym.st_value = atom_ptr.value;
12641264
1265 if (!elf_file.isRelocatable()) {
1265 if (!elf_file.base.isRelocatable()) {
12661266 const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);
12671267 try elf_file.zig_got.writeOne(elf_file, gop.index);
12681268 }
src/link/MachO.zig+11-10
......@@ -1,6 +1,6 @@
11base: File,
22
3/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
3/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename.
44llvm_object: ?*LlvmObject = null,
55
66/// Debug symbols bundle (or dSym).
......@@ -352,22 +352,23 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
352352 const tracy = trace(@src());
353353 defer tracy.end();
354354
355 if (self.llvm_object) |llvm_object| {
356 return try llvm_object.flushModule(comp, prog_node);
357 }
358
359 const gpa = self.base.comp.gpa;
355 const gpa = comp.gpa;
360356 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
361357 defer arena_allocator.deinit();
362358 const arena = arena_allocator.allocator();
363359
360 if (self.llvm_object) |llvm_object| {
361 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
362 return;
363 }
364
364365 var sub_prog_node = prog_node.start("MachO Flush", 0);
365366 sub_prog_node.activate();
366367 defer sub_prog_node.end();
367368
368 const output_mode = self.base.comp.config.output_mode;
369 const module = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
370 const target = self.base.comp.root_mod.resolved_target.result;
369 const output_mode = comp.config.output_mode;
370 const module = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
371 const target = comp.root_mod.resolved_target.result;
371372
372373 if (self.lazy_syms.getPtr(.none)) |metadata| {
373374 // Most lazy symbols can be updated on first use, but
......@@ -619,7 +620,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
619620 .stacksize = self.base.stack_size,
620621 });
621622 },
622 .Lib => if (self.base.comp.config.link_mode == .Dynamic) {
623 .Lib => if (comp.config.link_mode == .Dynamic) {
623624 try load_commands.writeDylibIdLC(self, lc_writer);
624625 },
625626 else => {},
src/link/Wasm.zig+11-10
......@@ -3700,8 +3700,15 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
37003700 const tracy = trace(@src());
37013701 defer tracy.end();
37023702
3703 const gpa = comp.gpa;
3704 // Used for all temporary memory allocated during flushin
3705 var arena_instance = std.heap.ArenaAllocator.init(gpa);
3706 defer arena_instance.deinit();
3707 const arena = arena_instance.allocator();
3708
37033709 if (wasm.llvm_object) |llvm_object| {
3704 return try llvm_object.flushModule(comp, prog_node);
3710 try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);
3711 return;
37053712 }
37063713
37073714 var sub_prog_node = prog_node.start("Wasm Flush", 0);
......@@ -3711,13 +3718,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
37113718 // ensure the error names table is populated when an error name is referenced
37123719 try wasm.populateErrorNameTable();
37133720
3714 // Used for all temporary memory allocated during flushin
3715 const gpa = wasm.base.comp.gpa;
3716 var arena_instance = std.heap.ArenaAllocator.init(gpa);
3717 defer arena_instance.deinit();
3718 const arena = arena_instance.allocator();
3719
3720 const objects = wasm.base.comp.objects;
3721 const objects = comp.objects;
37213722
37223723 // Positional arguments to the linker such as object files and static archives.
37233724 var positionals = std.ArrayList([]const u8).init(arena);
......@@ -3755,7 +3756,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
37553756 try wasm.markReferences();
37563757 try wasm.setupErrorsLen();
37573758 try wasm.setupImports();
3758 if (wasm.base.comp.module) |mod| {
3759 if (comp.module) |mod| {
37593760 var decl_it = wasm.decls.iterator();
37603761 while (decl_it.next()) |entry| {
37613762 const decl = mod.declPtr(entry.key_ptr.*);
......@@ -3810,7 +3811,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
38103811 }
38113812
38123813 if (wasm.dwarf) |*dwarf| {
3813 try dwarf.flushModule(wasm.base.comp.module.?);
3814 try dwarf.flushModule(comp.module.?);
38143815 }
38153816 }
38163817