| author | |
| committer | |
| log | 48731ccea9007529324e555ac9f24277d28c0d74 |
| tree | 5536d967bcad3a43d7def9171f0494cbe326703e |
| parent | 4731a6e5d57d5fe6c17c42028aebd9fce3682ddb |
| parent | 014e55e7610573e48a1a3722f4a5fdbb6ab347df |
7 files changed, 71 insertions(+), 13 deletions(-)
lib/std/build.zig+2| ... | ... | @@ -2659,6 +2659,8 @@ pub const LibExeObjStep = struct { |
| 2659 | 2659 | try zig_args.append(bin_name); |
| 2660 | 2660 | try zig_args.append("--test-cmd"); |
| 2661 | 2661 | try zig_args.append("--dir=."); |
| 2662 | try zig_args.append("--test-cmd"); | |
| 2663 | try zig_args.append("--allow-unknown-exports"); // TODO: Remove when stage2 is default compiler | |
| 2662 | 2664 | try zig_args.append("--test-cmd-bin"); |
| 2663 | 2665 | } else { |
| 2664 | 2666 | try zig_args.append("--test-no-exec"); |
src/Compilation.zig+9| ... | ... | @@ -166,6 +166,10 @@ emit_docs: ?EmitLoc, |
| 166 | 166 | work_queue_wait_group: WaitGroup, |
| 167 | 167 | astgen_wait_group: WaitGroup, |
| 168 | 168 | |
| 169 | /// Exported symbol names. This is only for when the target is wasm. | |
| 170 | /// TODO: Remove this when Stage2 becomes the default compiler as it will already have this information. | |
| 171 | export_symbol_names: std.ArrayListUnmanaged([]const u8) = .{}, | |
| 172 | ||
| 169 | 173 | pub const SemaError = Module.SemaError; |
| 170 | 174 | |
| 171 | 175 | pub const CRTFile = struct { |
| ... | ... | @@ -1878,6 +1882,11 @@ pub fn destroy(self: *Compilation) void { |
| 1878 | 1882 | self.work_queue_wait_group.deinit(); |
| 1879 | 1883 | self.astgen_wait_group.deinit(); |
| 1880 | 1884 | |
| 1885 | for (self.export_symbol_names.items) |symbol_name| { | |
| 1886 | gpa.free(symbol_name); | |
| 1887 | } | |
| 1888 | self.export_symbol_names.deinit(gpa); | |
| 1889 | ||
| 1881 | 1890 | // This destroys `self`. |
| 1882 | 1891 | self.arena_state.promote(gpa).deinit(); |
| 1883 | 1892 | } |
src/link/Wasm.zig+32-13| ... | ... | @@ -1163,7 +1163,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1163 | 1163 | }; |
| 1164 | 1164 | } |
| 1165 | 1165 | |
| 1166 | if (self.base.options.output_mode == .Obj) { | |
| 1166 | if (is_obj) { | |
| 1167 | 1167 | // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy |
| 1168 | 1168 | // here. TODO: think carefully about how we can avoid this redundant operation when doing |
| 1169 | 1169 | // build-obj. See also the corresponding TODO in linkAsArchive. |
| ... | ... | @@ -1233,14 +1233,45 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1233 | 1233 | try argv.append(arg); |
| 1234 | 1234 | } |
| 1235 | 1235 | |
| 1236 | var auto_export_symbols = true; | |
| 1236 | 1237 | // Users are allowed to specify which symbols they want to export to the wasm host. |
| 1237 | 1238 | for (self.base.options.export_symbol_names) |symbol_name| { |
| 1238 | 1239 | const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}); |
| 1239 | 1240 | try argv.append(arg); |
| 1241 | auto_export_symbols = false; | |
| 1240 | 1242 | } |
| 1241 | 1243 | |
| 1242 | 1244 | if (self.base.options.rdynamic) { |
| 1243 | 1245 | try argv.append("--export-dynamic"); |
| 1246 | auto_export_symbols = false; | |
| 1247 | } | |
| 1248 | ||
| 1249 | if (auto_export_symbols) { | |
| 1250 | if (self.base.options.module) |module| { | |
| 1251 | // when we use stage1, we use the exports that stage1 provided us. | |
| 1252 | // For stage2, we can directly retrieve them from the module. | |
| 1253 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; | |
| 1254 | if (use_stage1) { | |
| 1255 | for (comp.export_symbol_names.items) |symbol_name| { | |
| 1256 | try argv.append(try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name})); | |
| 1257 | } | |
| 1258 | } else { | |
| 1259 | const skip_export_non_fn = target.os.tag == .wasi and | |
| 1260 | self.base.options.wasi_exec_model == .command; | |
| 1261 | for (module.decl_exports.values()) |exports| { | |
| 1262 | for (exports) |exprt| { | |
| 1263 | if (skip_export_non_fn and exprt.exported_decl.ty.zigTypeTag() != .Fn) { | |
| 1264 | // skip exporting symbols when we're building a WASI command | |
| 1265 | // and the symbol is not a function | |
| 1266 | continue; | |
| 1267 | } | |
| 1268 | const symbol_name = exprt.exported_decl.name; | |
| 1269 | const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}); | |
| 1270 | try argv.append(arg); | |
| 1271 | } | |
| 1272 | } | |
| 1273 | } | |
| 1274 | } | |
| 1244 | 1275 | } |
| 1245 | 1276 | |
| 1246 | 1277 | if (self.base.options.output_mode == .Exe) { |
| ... | ... | @@ -1258,12 +1289,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1258 | 1289 | if (self.base.options.wasi_exec_model == .reactor) { |
| 1259 | 1290 | // Reactor execution model does not have _start so lld doesn't look for it. |
| 1260 | 1291 | try argv.append("--no-entry"); |
| 1261 | // Make sure "_initialize" and other used-defined functions are exported if this is WASI reactor. | |
| 1262 | // If rdynamic is true, it will already be appended, so only verify if the user did not specify | |
| 1263 | // the flag in which case, we ensure `--export-dynamic` is called. | |
| 1264 | if (!self.base.options.rdynamic) { | |
| 1265 | try argv.append("--export-dynamic"); | |
| 1266 | } | |
| 1267 | 1292 | } |
| 1268 | 1293 | } else { |
| 1269 | 1294 | if (self.base.options.stack_size_override) |stack_size| { |
| ... | ... | @@ -1271,12 +1296,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1271 | 1296 | const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size}); |
| 1272 | 1297 | try argv.append(arg); |
| 1273 | 1298 | } |
| 1274 | ||
| 1275 | // Only when the user has not specified how they want to export the symbols, do we want | |
| 1276 | // to export all symbols. | |
| 1277 | if (self.base.options.export_symbol_names.len == 0 and !self.base.options.rdynamic) { | |
| 1278 | try argv.append("--export-all"); | |
| 1279 | } | |
| 1280 | 1299 | try argv.append("--no-entry"); // So lld doesn't look for _start. |
| 1281 | 1300 | } |
| 1282 | 1301 | try argv.appendSlice(&[_][]const u8{ |
src/stage1.zig+8| ... | ... | @@ -467,3 +467,11 @@ export fn stage2_fetch_file( |
| 467 | 467 | if (contents.len == 0) return @intToPtr(?[*]const u8, 0x1); |
| 468 | 468 | return contents.ptr; |
| 469 | 469 | } |
| 470 | ||
| 471 | export fn stage2_append_symbol(stage1: *Module, name_ptr: [*c]const u8, name_len: usize) Error { | |
| 472 | if (name_len == 0) return Error.None; | |
| 473 | const comp = @intToPtr(*Compilation, stage1.userdata); | |
| 474 | const sym_name = comp.gpa.dupe(u8, name_ptr[0..name_len]) catch return Error.OutOfMemory; | |
| 475 | comp.export_symbol_names.append(comp.gpa, sym_name) catch return Error.OutOfMemory; | |
| 476 | return Error.None; | |
| 477 | } |
src/stage1/codegen.cpp+12| ... | ... | @@ -9905,6 +9905,18 @@ void codegen_build_object(CodeGen *g) { |
| 9905 | 9905 | |
| 9906 | 9906 | codegen_add_time_event(g, "Done"); |
| 9907 | 9907 | codegen_switch_sub_prog_node(g, nullptr); |
| 9908 | ||
| 9909 | // append all export symbols to stage2 so we can provide them to the linker | |
| 9910 | if (target_is_wasm(g->zig_target)){ | |
| 9911 | Error err; | |
| 9912 | auto export_it = g->exported_symbol_names.entry_iterator(); | |
| 9913 | decltype(g->exported_symbol_names)::Entry *curr_entry = nullptr; | |
| 9914 | while ((curr_entry = export_it.next()) != nullptr) { | |
| 9915 | if ((err = stage2_append_symbol(&g->stage1, buf_ptr(curr_entry->key), buf_len(curr_entry->key)))) { | |
| 9916 | fprintf(stderr, "Unable to export symbol '%s': %s\n", buf_ptr(curr_entry->key), err_str(err)); | |
| 9917 | } | |
| 9918 | } | |
| 9919 | } | |
| 9908 | 9920 | } |
| 9909 | 9921 | |
| 9910 | 9922 | ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path, |
src/stage1/stage2.h+3| ... | ... | @@ -182,4 +182,7 @@ ZIG_EXTERN_C const char *stage2_add_link_lib(struct ZigStage1 *stage1, |
| 182 | 182 | const char *lib_name_ptr, size_t lib_name_len, |
| 183 | 183 | const char *symbol_name_ptr, size_t symbol_name_len); |
| 184 | 184 | |
| 185 | // ABI warning | |
| 186 | ZIG_EXTERN_C enum Error stage2_append_symbol(struct ZigStage1 *stage1, const char *name_ptr, size_t name_len); | |
| 187 | ||
| 185 | 188 | #endif |
src/stage1/zig0.cpp+5| ... | ... | @@ -554,3 +554,8 @@ const char *stage2_version_string(void) { |
| 554 | 554 | struct Stage2SemVer stage2_version(void) { |
| 555 | 555 | return {ZIG_VERSION_MAJOR, ZIG_VERSION_MINOR, ZIG_VERSION_PATCH}; |
| 556 | 556 | } |
| 557 | ||
| 558 | Error stage2_append_symbol(struct ZigStage1 *stage1, const char *name_ptr, size_t name_len) | |
| 559 | { | |
| 560 | return ErrorNone; | |
| 561 | } |