| author | |
| committer | |
| log | a615425b513eb981cb2d5f0b780d720203c8defe |
| tree | 20cc2e7305456b4175b1e19040016edb8ad303d2 |
| parent | 4731a6e5d57d5fe6c17c42028aebd9fce3682ddb |
| parent | 247b638ccf8bfd5e0c4729935d230022726f97aa |
7 files changed, 70 insertions(+), 13 deletions(-)
lib/std/build.zig+2| ... | @@ -2659,6 +2659,8 @@ pub const LibExeObjStep = struct { | ... | @@ -2659,6 +2659,8 @@ pub const LibExeObjStep = struct { |
| 2659 | try zig_args.append(bin_name); | 2659 | try zig_args.append(bin_name); |
| 2660 | try zig_args.append("--test-cmd"); | 2660 | try zig_args.append("--test-cmd"); |
| 2661 | try zig_args.append("--dir=."); | 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 | try zig_args.append("--test-cmd-bin"); | 2664 | try zig_args.append("--test-cmd-bin"); |
| 2663 | } else { | 2665 | } else { |
| 2664 | try zig_args.append("--test-no-exec"); | 2666 | try zig_args.append("--test-no-exec"); |
src/Compilation.zig+9| ... | @@ -166,6 +166,10 @@ emit_docs: ?EmitLoc, | ... | @@ -166,6 +166,10 @@ emit_docs: ?EmitLoc, |
| 166 | work_queue_wait_group: WaitGroup, | 166 | work_queue_wait_group: WaitGroup, |
| 167 | astgen_wait_group: WaitGroup, | 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 | pub const SemaError = Module.SemaError; | 173 | pub const SemaError = Module.SemaError; |
| 170 | 174 | ||
| 171 | pub const CRTFile = struct { | 175 | pub const CRTFile = struct { |
| ... | @@ -1878,6 +1882,11 @@ pub fn destroy(self: *Compilation) void { | ... | @@ -1878,6 +1882,11 @@ pub fn destroy(self: *Compilation) void { |
| 1878 | self.work_queue_wait_group.deinit(); | 1882 | self.work_queue_wait_group.deinit(); |
| 1879 | self.astgen_wait_group.deinit(); | 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 | // This destroys `self`. | 1890 | // This destroys `self`. |
| 1882 | self.arena_state.promote(gpa).deinit(); | 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,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 | // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy | 1167 | // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy |
| 1168 | // here. TODO: think carefully about how we can avoid this redundant operation when doing | 1168 | // here. TODO: think carefully about how we can avoid this redundant operation when doing |
| 1169 | // build-obj. See also the corresponding TODO in linkAsArchive. | 1169 | // build-obj. See also the corresponding TODO in linkAsArchive. |
| ... | @@ -1233,14 +1233,45 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { | ... | @@ -1233,14 +1233,45 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1233 | try argv.append(arg); | 1233 | try argv.append(arg); |
| 1234 | } | 1234 | } |
| 1235 | 1235 | ||
| 1236 | var auto_export_symbols = true; | ||
| 1236 | // Users are allowed to specify which symbols they want to export to the wasm host. | 1237 | // Users are allowed to specify which symbols they want to export to the wasm host. |
| 1237 | for (self.base.options.export_symbol_names) |symbol_name| { | 1238 | for (self.base.options.export_symbol_names) |symbol_name| { |
| 1238 | const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}); | 1239 | const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}); |
| 1239 | try argv.append(arg); | 1240 | try argv.append(arg); |
| 1241 | auto_export_symbols = false; | ||
| 1240 | } | 1242 | } |
| 1241 | 1243 | ||
| 1242 | if (self.base.options.rdynamic) { | 1244 | if (self.base.options.rdynamic) { |
| 1243 | try argv.append("--export-dynamic"); | 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 | if (self.base.options.output_mode == .Exe) { | 1277 | if (self.base.options.output_mode == .Exe) { |
| ... | @@ -1258,12 +1289,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { | ... | @@ -1258,12 +1289,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1258 | if (self.base.options.wasi_exec_model == .reactor) { | 1289 | if (self.base.options.wasi_exec_model == .reactor) { |
| 1259 | // Reactor execution model does not have _start so lld doesn't look for it. | 1290 | // Reactor execution model does not have _start so lld doesn't look for it. |
| 1260 | try argv.append("--no-entry"); | 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 | } else { | 1293 | } else { |
| 1269 | if (self.base.options.stack_size_override) |stack_size| { | 1294 | if (self.base.options.stack_size_override) |stack_size| { |
| ... | @@ -1271,12 +1296,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { | ... | @@ -1271,12 +1296,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1271 | const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size}); | 1296 | const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size}); |
| 1272 | try argv.append(arg); | 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 | try argv.append("--no-entry"); // So lld doesn't look for _start. | 1299 | try argv.append("--no-entry"); // So lld doesn't look for _start. |
| 1281 | } | 1300 | } |
| 1282 | try argv.appendSlice(&[_][]const u8{ | 1301 | try argv.appendSlice(&[_][]const u8{ |
src/stage1.zig+7| ... | @@ -467,3 +467,10 @@ export fn stage2_fetch_file( | ... | @@ -467,3 +467,10 @@ export fn stage2_fetch_file( |
| 467 | if (contents.len == 0) return @intToPtr(?[*]const u8, 0x1); | 467 | if (contents.len == 0) return @intToPtr(?[*]const u8, 0x1); |
| 468 | return contents.ptr; | 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 | comp.export_symbol_names.append(comp.gpa, name_ptr[0..name_len]) catch return Error.OutOfMemory; | ||
| 475 | return Error.None; | ||
| 476 | } |
src/stage1/codegen.cpp+12| ... | @@ -9905,6 +9905,18 @@ void codegen_build_object(CodeGen *g) { | ... | @@ -9905,6 +9905,18 @@ void codegen_build_object(CodeGen *g) { |
| 9905 | 9905 | ||
| 9906 | codegen_add_time_event(g, "Done"); | 9906 | codegen_add_time_event(g, "Done"); |
| 9907 | codegen_switch_sub_prog_node(g, nullptr); | 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 | ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path, | 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,4 +182,7 @@ ZIG_EXTERN_C const char *stage2_add_link_lib(struct ZigStage1 *stage1, |
| 182 | const char *lib_name_ptr, size_t lib_name_len, | 182 | const char *lib_name_ptr, size_t lib_name_len, |
| 183 | const char *symbol_name_ptr, size_t symbol_name_len); | 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 | #endif | 188 | #endif |
src/stage1/zig0.cpp+5| ... | @@ -554,3 +554,8 @@ const char *stage2_version_string(void) { | ... | @@ -554,3 +554,8 @@ const char *stage2_version_string(void) { |
| 554 | struct Stage2SemVer stage2_version(void) { | 554 | struct Stage2SemVer stage2_version(void) { |
| 555 | return {ZIG_VERSION_MAJOR, ZIG_VERSION_MINOR, ZIG_VERSION_PATCH}; | 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 | } |