authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-26 21:39:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:21-07:00
log57562c8d507667b6fefcb7fbc7a305fbd610b5dd
treef0e494bdace7302f7cce8ad8c9c7d3227bd81d64
parentc9fe43679f8d8f0db6250cc881b59cc68daaf128

compiler: push entry symbol name resolution into the linker

This is necessary because on COFF, the entry symbol name is not known until the linker has looked at the set of global symbol names to determine which of the four possible main entry points is present.

11 files changed, 124 insertions(+), 99 deletions(-)

src/Compilation.zig+6-3
......@@ -924,7 +924,7 @@ pub const LinkObject = struct {
924924 loption: bool = false,
925925};
926926
927pub const InitOptions = struct {
927pub const CreateOptions = struct {
928928 zig_lib_directory: Directory,
929929 local_cache_directory: Directory,
930930 global_cache_directory: Directory,
......@@ -1054,7 +1054,7 @@ pub const InitOptions = struct {
10541054 /// infinite recursion.
10551055 skip_linker_dependencies: bool = false,
10561056 hash_style: link.File.Elf.HashStyle = .both,
1057 entry: ?[]const u8 = null,
1057 entry: Entry = .default,
10581058 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{},
10591059 stack_size: ?u64 = null,
10601060 image_base: ?u64 = null,
......@@ -1089,6 +1089,8 @@ pub const InitOptions = struct {
10891089 /// (Windows) PDB output path
10901090 pdb_out_path: ?[]const u8 = null,
10911091 error_limit: ?Compilation.Module.ErrorInt = null,
1092
1093 pub const Entry = link.File.OpenOptions.Entry;
10921094};
10931095
10941096fn addModuleTableToCacheHash(
......@@ -1159,7 +1161,7 @@ fn addModuleTableToCacheHash(
11591161 }
11601162}
11611163
1162pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1164pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation {
11631165 const output_mode = options.config.output_mode;
11641166 const is_dyn_lib = switch (output_mode) {
11651167 .Obj, .Exe => false,
......@@ -1543,6 +1545,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15431545 .dynamicbase = options.linker_dynamicbase,
15441546 .major_subsystem_version = options.major_subsystem_version,
15451547 .minor_subsystem_version = options.minor_subsystem_version,
1548 .entry = options.entry,
15461549 .stack_size = options.stack_size,
15471550 .image_base = options.image_base,
15481551 .version_script = options.version_script,
src/Compilation/Config.zig-29
......@@ -55,7 +55,6 @@ export_memory: bool,
5555shared_memory: bool,
5656is_test: bool,
5757test_evented_io: bool,
58entry: ?[]const u8,
5958debug_format: DebugFormat,
6059root_strip: bool,
6160root_error_tracing: bool,
......@@ -100,12 +99,6 @@ pub const Options = struct {
10099 use_lld: ?bool = null,
101100 use_clang: ?bool = null,
102101 lto: ?bool = null,
103 entry: union(enum) {
104 default,
105 disabled,
106 enabled,
107 named: []const u8,
108 } = .default,
109102 /// WASI-only. Type of WASI execution model ("command" or "reactor").
110103 wasi_exec_model: ?std.builtin.WasiExecModel = null,
111104 import_memory: ?bool = null,
......@@ -123,8 +116,6 @@ pub const ResolveError = error{
123116 ObjectFilesCannotShareMemory,
124117 SharedMemoryRequiresAtomicsAndBulkMemory,
125118 ThreadsRequireSharedMemory,
126 UnknownTargetEntryPoint,
127 NonExecutableEntryPoint,
128119 EmittingLlvmModuleRequiresLlvmBackend,
129120 LlvmLacksTargetSupport,
130121 ZigLacksTargetSupport,
......@@ -352,25 +343,6 @@ pub fn resolve(options: Options) ResolveError!Config {
352343 break :b false;
353344 };
354345
355 const entry: ?[]const u8 = switch (options.entry) {
356 .disabled => null,
357 .default => b: {
358 if (options.output_mode != .Exe) break :b null;
359
360 // When producing C source code, the decision of entry point is made
361 // when compiling the C code, not when producing the C code.
362 if (target.ofmt == .c) break :b null;
363
364 break :b target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse
365 return error.UnknownTargetEntryPoint;
366 },
367 .enabled => target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse
368 return error.UnknownTargetEntryPoint,
369 .named => |name| name,
370 };
371 if (entry != null and options.output_mode != .Exe)
372 return error.NonExecutableEntryPoint;
373
374346 const any_unwind_tables = options.any_unwind_tables or
375347 link_libunwind or target_util.needUnwindTables(target);
376348
......@@ -519,7 +491,6 @@ pub fn resolve(options: Options) ResolveError!Config {
519491 .use_llvm = use_llvm,
520492 .use_lib_llvm = use_lib_llvm,
521493 .use_lld = use_lld,
522 .entry = entry,
523494 .wasi_exec_model = wasi_exec_model,
524495 .debug_format = debug_format,
525496 .root_strip = root_strip,
src/link.zig+9
......@@ -83,6 +83,8 @@ pub const File = struct {
8383 symbol_count_hint: u64 = 32,
8484 program_code_size_hint: u64 = 256 * 1024,
8585
86 /// This may depend on what symbols are found during the linking process.
87 entry: Entry,
8688 /// Virtual address of the entry point procedure relative to image base.
8789 entry_addr: ?u64,
8890 stack_size: ?u64,
......@@ -169,6 +171,13 @@ pub const File = struct {
169171 module_definition_file: ?[]const u8,
170172
171173 wasi_emulated_libs: []const wasi_libc.CRTFile,
174
175 pub const Entry = union(enum) {
176 default,
177 disabled,
178 enabled,
179 named: []const u8,
180 };
172181 };
173182
174183 /// Attempts incremental linking, if the file already exists. If
src/link/Coff.zig+20-1
......@@ -17,6 +17,7 @@ dynamicbase: bool,
1717major_subsystem_version: u16,
1818minor_subsystem_version: u16,
1919lib_dirs: []const []const u8,
20entry: link.File.OpenOptions.Entry,
2021entry_addr: ?u32,
2122module_definition_file: ?[]const u8,
2223pdb_out_path: ?[]const u8,
......@@ -303,7 +304,12 @@ pub fn createEmpty(
303304 .Obj => 0,
304305 },
305306
307 // Subsystem depends on the set of public symbol names from linked objects.
308 // See LinkerDriver::inferSubsystem from the LLD project for the flow chart.
306309 .subsystem = options.subsystem,
310
311 .entry = options.entry,
312
307313 .tsaware = options.tsaware,
308314 .nxcompat = options.nxcompat,
309315 .dynamicbase = options.dynamicbase,
......@@ -2498,7 +2504,20 @@ inline fn getSizeOfImage(self: Coff) u32 {
24982504/// Returns symbol location corresponding to the set entrypoint (if any).
24992505pub fn getEntryPoint(self: Coff) ?SymbolWithLoc {
25002506 const comp = self.base.comp;
2501 const entry_name = comp.config.entry orelse return null;
2507
2508 // TODO This is incomplete.
2509 // The entry symbol name depends on the subsystem as well as the set of
2510 // public symbol names from linked objects.
2511 // See LinkerDriver::findDefaultEntry from the LLD project for the flow chart.
2512 const entry_name = switch (self.entry) {
2513 .disabled => return null,
2514 .default => switch (comp.config.output_mode) {
2515 .Exe => "wWinMainCRTStartup",
2516 .Obj, .Lib => return null,
2517 },
2518 .enabled => "wWinMainCRTStartup",
2519 .named => |name| name,
2520 };
25022521 const global_index = self.resolver.get(entry_name) orelse return null;
25032522 return self.globals.items[global_index];
25042523}
src/link/Coff/lld.zig+11-4
......@@ -52,6 +52,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
5252 const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib;
5353 const target = comp.root_mod.resolved_target.result;
5454 const optimize_mode = comp.root_mod.optimize_mode;
55 const entry_name: ?[]const u8 = switch (self.entry) {
56 // This logic isn't quite right for disabled or enabled. No point in fixing it
57 // when the goal is to eliminate dependency on LLD anyway.
58 // https://github.com/ziglang/zig/issues/17751
59 .disabled, .default, .enabled => null,
60 .named => |name| name,
61 };
5562
5663 // See link/Elf.zig for comments on how this mechanism works.
5764 const id_symlink_basename = "lld.id";
......@@ -80,7 +87,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
8087 }
8188 }
8289 try man.addOptionalFile(module_obj_path);
83 man.hash.addOptionalBytes(comp.config.entry);
90 man.hash.addOptionalBytes(entry_name);
8491 man.hash.add(self.base.stack_size);
8592 man.hash.add(self.image_base);
8693 man.hash.addListOfBytes(self.lib_dirs);
......@@ -218,8 +225,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
218225 try argv.append("-DLL");
219226 }
220227
221 if (comp.config.entry) |entry| {
222 try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{entry}));
228 if (entry_name) |name| {
229 try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{name}));
223230 }
224231
225232 if (self.tsaware) {
......@@ -441,7 +448,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
441448 }
442449 } else {
443450 try argv.append("-NODEFAULTLIB");
444 if (!is_lib and comp.config.entry == null) {
451 if (!is_lib and entry_name == null) {
445452 if (comp.module) |module| {
446453 if (module.stage1_flags.have_winmain_crt_startup) {
447454 try argv.append("-ENTRY:WinMainCRTStartup");
src/link/Elf.zig+21-8
......@@ -25,6 +25,7 @@ linker_script: ?[]const u8,
2525version_script: ?[]const u8,
2626print_icf_sections: bool,
2727print_map: bool,
28entry_name: ?[]const u8,
2829
2930ptr_width: PtrWidth,
3031
......@@ -290,6 +291,13 @@ pub fn createEmpty(
290291 .page_size = page_size,
291292 .default_sym_version = default_sym_version,
292293
294 .entry_name = switch (options.entry) {
295 .disabled => null,
296 .default => if (output_mode != .Exe) null else defaultEntrySymbolName(target.cpu.arch),
297 .enabled => defaultEntrySymbolName(target.cpu.arch),
298 .named => |name| name,
299 },
300
293301 .image_base = b: {
294302 if (is_dyn_lib) break :b 0;
295303 if (output_mode == .Exe and comp.config.pie) break :b 0;
......@@ -1305,7 +1313,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
13051313
13061314 // Look for entry address in objects if not set by the incremental compiler.
13071315 if (self.entry_index == null) {
1308 if (comp.config.entry) |name| {
1316 if (self.entry_name) |name| {
13091317 self.entry_index = self.globalByName(name);
13101318 }
13111319 }
......@@ -1679,9 +1687,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
16791687 }
16801688 }
16811689
1682 if (comp.config.entry) |entry| {
1683 try argv.append("--entry");
1684 try argv.append(entry);
1690 if (self.entry_name) |name| {
1691 try argv.appendSlice(&.{ "--entry", name });
16851692 }
16861693
16871694 for (self.base.rpath_list) |rpath| {
......@@ -2427,7 +2434,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
24272434
24282435 // We can skip hashing libc and libc++ components that we are in charge of building from Zig
24292436 // installation sources because they are always a product of the compiler version + target information.
2430 man.hash.addOptionalBytes(comp.config.entry);
2437 man.hash.addOptionalBytes(self.entry_name);
24312438 man.hash.add(self.image_base);
24322439 man.hash.add(self.base.gc_sections);
24332440 man.hash.addOptional(self.sort_section);
......@@ -2563,9 +2570,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
25632570 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
25642571 }
25652572
2566 if (comp.config.entry) |entry| {
2567 try argv.append("--entry");
2568 try argv.append(entry);
2573 if (self.entry_name) |name| {
2574 try argv.appendSlice(&.{ "--entry", name });
25692575 }
25702576
25712577 for (self.base.force_undefined_symbols.keys()) |sym| {
......@@ -6512,6 +6518,13 @@ const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);
65126518pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1;
65136519pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2;
65146520
6521fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
6522 return switch (cpu_arch) {
6523 .mips, .mipsel, .mips64, .mips64el => "__start",
6524 else => "_start",
6525 };
6526}
6527
65156528const std = @import("std");
65166529const build_options = @import("build_options");
65176530const builtin = @import("builtin");
src/link/MachO.zig+13-4
......@@ -1,4 +1,5 @@
11base: File,
2entry_name: ?[]const u8,
23
34/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
45llvm_object: ?*LlvmObject = null,
......@@ -231,6 +232,12 @@ pub fn createEmpty(
231232 .install_name = options.install_name,
232233 .entitlements = options.entitlements,
233234 .compatibility_version = options.compatibility_version,
235 .entry_name = switch (options.entry) {
236 .disabled => null,
237 .default => if (output_mode != .Exe) null else default_entry_symbol_name,
238 .enabled => default_entry_symbol_name,
239 .named => |name| name,
240 },
234241 };
235242 if (use_llvm and comp.config.have_zcu) {
236243 self.llvm_object = try LlvmObject.create(arena, comp);
......@@ -1629,8 +1636,9 @@ pub fn resolveSymbols(self: *MachO) !void {
16291636 // we search for it in libraries should there be no object files specified
16301637 // on the linker line.
16311638 if (output_mode == .Exe) {
1632 const entry_name = comp.config.entry.?;
1633 _ = try self.addUndefined(entry_name, .{});
1639 if (self.entry_name) |entry_name| {
1640 _ = try self.addUndefined(entry_name, .{});
1641 }
16341642 }
16351643
16361644 // Force resolution of any symbols requested by the user.
......@@ -5085,8 +5093,7 @@ pub fn getStubsEntryAddress(self: *MachO, sym_with_loc: SymbolWithLoc) ?u64 {
50855093/// Returns symbol location corresponding to the set entrypoint if any.
50865094/// Asserts output mode is executable.
50875095pub fn getEntryPoint(self: MachO) ?SymbolWithLoc {
5088 const comp = self.base.comp;
5089 const entry_name = comp.config.entry orelse return null;
5096 const entry_name = self.entry_name orelse return null;
50905097 const global = self.getGlobal(entry_name) orelse return null;
50915098 return global;
50925099}
......@@ -5645,6 +5652,8 @@ pub fn logAtom(self: *MachO, atom_index: Atom.Index, logger: anytype) void {
56455652 }
56465653}
56475654
5655const default_entry_symbol_name = "_main";
5656
56485657pub const base_tag: File.Tag = File.Tag.macho;
56495658pub const N_DEAD: u16 = @as(u16, @bitCast(@as(i16, -1)));
56505659pub const N_BOUNDARY: u16 = @as(u16, @bitCast(@as(i16, -2)));
src/link/MachO/zld.zig+2-3
......@@ -276,9 +276,8 @@ pub fn linkWithZld(
276276 try argv.append("-dead_strip_dylibs");
277277 }
278278
279 if (comp.config.entry) |entry| {
280 try argv.append("-e");
281 try argv.append(entry);
279 if (macho_file.entry_name) |entry_name| {
280 try argv.appendSlice(&.{ "-e", entry_name });
282281 }
283282
284283 for (objects) |obj| {
src/link/Wasm.zig+33-18
......@@ -37,6 +37,7 @@ pub const Relocation = types.Relocation;
3737pub const base_tag: link.File.Tag = .wasm;
3838
3939base: link.File,
40entry_name: ?[]const u8,
4041import_symbols: bool,
4142export_symbol_names: []const []const u8,
4243global_base: ?u64,
......@@ -397,6 +398,7 @@ pub fn createEmpty(
397398 const use_llvm = comp.config.use_llvm;
398399 const output_mode = comp.config.output_mode;
399400 const shared_memory = comp.config.shared_memory;
401 const wasi_exec_model = comp.config.wasi_exec_model;
400402
401403 // If using LLD to link, this code should produce an object file so that it
402404 // can be passed to LLD.
......@@ -434,6 +436,13 @@ pub fn createEmpty(
434436 .initial_memory = options.initial_memory,
435437 .max_memory = options.max_memory,
436438 .wasi_emulated_libs = options.wasi_emulated_libs,
439
440 .entry_name = switch (options.entry) {
441 .disabled => null,
442 .default => if (output_mode != .Exe) null else defaultEntrySymbolName(wasi_exec_model),
443 .enabled => defaultEntrySymbolName(wasi_exec_model),
444 .named => |name| name,
445 },
437446 };
438447 if (use_llvm and comp.config.have_zcu) {
439448 wasm.llvm_object = try LlvmObject.create(arena, comp);
......@@ -3042,7 +3051,7 @@ fn setupExports(wasm: *Wasm) !void {
30423051fn setupStart(wasm: *Wasm) !void {
30433052 const comp = wasm.base.comp;
30443053 // do not export entry point if user set none or no default was set.
3045 const entry_name = comp.config.entry orelse return;
3054 const entry_name = wasm.entry_name orelse return;
30463055
30473056 const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse {
30483057 log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name});
......@@ -3475,8 +3484,8 @@ fn resetState(wasm: *Wasm) void {
34753484}
34763485
34773486pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
3478 const use_lld = build_options.have_llvm and wasm.base.comp.config.use_lld;
3479 const use_llvm = wasm.base.comp.config.use_llvm;
3487 const use_lld = build_options.have_llvm and comp.config.use_lld;
3488 const use_llvm = comp.config.use_llvm;
34803489
34813490 if (use_lld) {
34823491 return wasm.linkWithLLD(comp, prog_node);
......@@ -3492,7 +3501,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
34923501 const tracy = trace(@src());
34933502 defer tracy.end();
34943503
3495 const gpa = wasm.base.comp.gpa;
3504 const gpa = comp.gpa;
34963505 const shared_memory = comp.config.shared_memory;
34973506 const import_memory = comp.config.import_memory;
34983507
......@@ -3503,8 +3512,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
35033512
35043513 const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.
35053514 const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});
3506 const opt_zcu = wasm.base.comp.module;
3507 const use_llvm = wasm.base.comp.config.use_llvm;
3515 const opt_zcu = comp.module;
3516 const use_llvm = comp.config.use_llvm;
35083517
35093518 // If there is no Zig code to compile, then we should skip flushing the output file because it
35103519 // will not be part of the linker line anyway.
......@@ -3535,7 +3544,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
35353544 defer if (!wasm.base.disable_lld_caching) man.deinit();
35363545 var digest: [Cache.hex_digest_len]u8 = undefined;
35373546
3538 const objects = wasm.base.comp.objects;
3547 const objects = comp.objects;
35393548
35403549 // NOTE: The following section must be maintained to be equal
35413550 // as the section defined in `linkWithLLD`
......@@ -3556,7 +3565,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
35563565 }
35573566 try man.addOptionalFile(module_obj_path);
35583567 try man.addOptionalFile(compiler_rt_path);
3559 man.hash.addOptionalBytes(wasm.base.comp.config.entry);
3568 man.hash.addOptionalBytes(wasm.entry_name);
35603569 man.hash.add(wasm.base.stack_size);
35613570 man.hash.add(wasm.base.build_id);
35623571 man.hash.add(import_memory);
......@@ -3605,12 +3614,12 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
36053614 var positionals = std.ArrayList([]const u8).init(arena);
36063615 try positionals.ensureUnusedCapacity(objects.len);
36073616
3608 const target = wasm.base.comp.root_mod.resolved_target.result;
3609 const output_mode = wasm.base.comp.config.output_mode;
3610 const link_mode = wasm.base.comp.config.link_mode;
3611 const link_libc = wasm.base.comp.config.link_libc;
3612 const link_libcpp = wasm.base.comp.config.link_libcpp;
3613 const wasi_exec_model = wasm.base.comp.config.wasi_exec_model;
3617 const target = comp.root_mod.resolved_target.result;
3618 const output_mode = comp.config.output_mode;
3619 const link_mode = comp.config.link_mode;
3620 const link_libc = comp.config.link_libc;
3621 const link_libcpp = comp.config.link_libcpp;
3622 const wasi_exec_model = comp.config.wasi_exec_model;
36143623
36153624 // When the target os is WASI, we allow linking with WASI-LIBC
36163625 if (target.os.tag == .wasi) {
......@@ -4648,7 +4657,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
46484657 }
46494658 try man.addOptionalFile(module_obj_path);
46504659 try man.addOptionalFile(compiler_rt_path);
4651 man.hash.addOptionalBytes(wasm.base.comp.config.entry);
4660 man.hash.addOptionalBytes(wasm.entry_name);
46524661 man.hash.add(wasm.base.stack_size);
46534662 man.hash.add(wasm.base.build_id);
46544663 man.hash.add(import_memory);
......@@ -4799,9 +4808,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
47994808 try argv.append("--export-dynamic");
48004809 }
48014810
4802 if (comp.config.entry) |entry| {
4803 try argv.append("--entry");
4804 try argv.append(entry);
4811 if (wasm.entry_name) |entry_name| {
4812 try argv.appendSlice(&.{ "--entry", entry_name });
48054813 } else {
48064814 try argv.append("--no-entry");
48074815 }
......@@ -5347,3 +5355,10 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void {
53475355 try wasm.mark(target_loc.finalLoc(wasm));
53485356 }
53495357}
5358
5359fn defaultEntrySymbolName(wasi_exec_model: std.builtin.WasiExecModel) []const u8 {
5360 return switch (wasi_exec_model) {
5361 .reactor => "_initialize",
5362 .command => "_start",
5363 };
5364}
src/main.zig+9-9
......@@ -857,6 +857,7 @@ fn buildOutputType(
857857 var linker_optimization: ?[]const u8 = null;
858858 var linker_module_definition_file: ?[]const u8 = null;
859859 var test_no_exec = false;
860 var entry: Compilation.CreateOptions.Entry = .default;
860861 var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{};
861862 var stack_size: ?u64 = null;
862863 var image_base: ?u64 = null;
......@@ -1129,7 +1130,7 @@ fn buildOutputType(
11291130 } else if (mem.eql(u8, arg, "-O")) {
11301131 mod_opts.optimize_mode = parseOptimizeMode(args_iter.nextOrFatal());
11311132 } else if (mem.startsWith(u8, arg, "-fentry=")) {
1132 create_module.opts.entry = .{ .named = arg["-fentry=".len..] };
1133 entry = .{ .named = arg["-fentry=".len..] };
11331134 } else if (mem.eql(u8, arg, "--force_undefined")) {
11341135 try force_undefined_symbols.put(arena, args_iter.nextOrFatal(), {});
11351136 } else if (mem.eql(u8, arg, "--stack")) {
......@@ -1556,12 +1557,12 @@ fn buildOutputType(
15561557 } else if (mem.eql(u8, arg, "--import-memory")) {
15571558 create_module.opts.import_memory = true;
15581559 } else if (mem.eql(u8, arg, "-fentry")) {
1559 switch (create_module.opts.entry) {
1560 .default, .disabled => create_module.opts.entry = .enabled,
1560 switch (entry) {
1561 .default, .disabled => entry = .enabled,
15611562 .enabled, .named => {},
15621563 }
15631564 } else if (mem.eql(u8, arg, "-fno-entry")) {
1564 create_module.opts.entry = .disabled;
1565 entry = .disabled;
15651566 } else if (mem.eql(u8, arg, "--export-memory")) {
15661567 create_module.opts.export_memory = true;
15671568 } else if (mem.eql(u8, arg, "--import-symbols")) {
......@@ -2065,7 +2066,7 @@ fn buildOutputType(
20652066 create_module.sysroot = it.only_arg;
20662067 },
20672068 .entry => {
2068 create_module.opts.entry = .{ .named = it.only_arg };
2069 entry = .{ .named = it.only_arg };
20692070 },
20702071 .force_undefined_symbol => {
20712072 try force_undefined_symbols.put(arena, it.only_arg, {});
......@@ -2210,7 +2211,7 @@ fn buildOutputType(
22102211 } else if (mem.eql(u8, arg, "--export-table")) {
22112212 linker_export_table = true;
22122213 } else if (mem.eql(u8, arg, "--no-entry")) {
2213 create_module.opts.entry = .disabled;
2214 entry = .disabled;
22142215 } else if (mem.eql(u8, arg, "--initial-memory")) {
22152216 const next_arg = linker_args_it.nextOrFatal();
22162217 linker_initial_memory = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {
......@@ -2284,7 +2285,7 @@ fn buildOutputType(
22842285 };
22852286 have_version = true;
22862287 } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) {
2287 create_module.opts.entry = .{ .named = linker_args_it.nextOrFatal() };
2288 entry = .{ .named = linker_args_it.nextOrFatal() };
22882289 } else if (mem.eql(u8, arg, "-u")) {
22892290 try force_undefined_symbols.put(arena, linker_args_it.nextOrFatal(), {});
22902291 } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) {
......@@ -3200,6 +3201,7 @@ fn buildOutputType(
32003201 .minor_subsystem_version = minor_subsystem_version,
32013202 .link_eh_frame_hdr = link_eh_frame_hdr,
32023203 .link_emit_relocs = link_emit_relocs,
3204 .entry = entry,
32033205 .force_undefined_symbols = force_undefined_symbols,
32043206 .stack_size = stack_size,
32053207 .image_base = image_base,
......@@ -3845,8 +3847,6 @@ fn createModule(
38453847 error.ObjectFilesCannotShareMemory => fatal("object files cannot share memory", .{}),
38463848 error.SharedMemoryRequiresAtomicsAndBulkMemory => fatal("shared memory requires atomics and bulk_memory CPU features", .{}),
38473849 error.ThreadsRequireSharedMemory => fatal("threads require shared memory", .{}),
3848 error.UnknownTargetEntryPoint => fatal("unknown target entry point", .{}),
3849 error.NonExecutableEntryPoint => fatal("entry points only allowed for executables", .{}),
38503850 error.EmittingLlvmModuleRequiresLlvmBackend => fatal("emitting an LLVM module requires using the LLVM backend", .{}),
38513851 error.LlvmLacksTargetSupport => fatal("LLVM lacks support for the specified target", .{}),
38523852 error.ZigLacksTargetSupport => fatal("compiler backend unavailable for the specified target", .{}),
src/target.zig-20
......@@ -683,23 +683,3 @@ pub fn backendSupportsFeature(
683683 .safety_checked_instructions => use_llvm,
684684 };
685685}
686
687pub fn defaultEntrySymbolName(
688 target: std.Target,
689 /// May be `undefined` when `target` is not WASI.
690 wasi_exec_model: std.builtin.WasiExecModel,
691) ?[]const u8 {
692 return switch (target.ofmt) {
693 .coff => "wWinMainCRTStartup",
694 .macho => "_main",
695 .elf, .plan9 => switch (target.cpu.arch) {
696 .mips, .mipsel, .mips64, .mips64el => "__start",
697 else => "_start",
698 },
699 .wasm => switch (wasi_exec_model) {
700 .reactor => "_initialize",
701 .command => "_start",
702 },
703 else => null,
704 };
705}