From 77c2ac3fcd27b114b0068d3b64b3d884aa71e4ef Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 21 Jul 2019 18:04:23 -0400 Subject: zig build: support DESTDIR environment variable closes #2929 --- std/build.zig | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/std/build.zig b/std/build.zig index fc0786094d..e6e7143f06 100644 --- a/std/build.zig +++ b/std/build.zig @@ -41,9 +41,10 @@ pub const Builder = struct { env_map: *BufMap, top_level_steps: ArrayList(*TopLevelStep), install_prefix: ?[]const u8, - search_prefixes: ArrayList([]const u8), + dest_dir: ?[]const u8, lib_dir: ?[]const u8, exe_dir: ?[]const u8, + search_prefixes: ArrayList([]const u8), installed_files: ArrayList(InstalledFile), build_root: []const u8, cache_root: []const u8, @@ -125,10 +126,11 @@ pub const Builder = struct { .top_level_steps = ArrayList(*TopLevelStep).init(allocator), .default_step = undefined, .env_map = env_map, - .install_prefix = null, .search_prefixes = ArrayList([]const u8).init(allocator), + .install_prefix = null, .lib_dir = null, .exe_dir = null, + .dest_dir = env_map.get("DESTDIR"), .installed_files = ArrayList(InstalledFile).init(allocator), .install_tls = TopLevelStep{ .step = Step.initNoOp("install", allocator), @@ -164,14 +166,14 @@ pub const Builder = struct { } fn resolveInstallPrefix(self: *Builder) void { - const prefix = if (self.install_prefix) |prefix| prefix else blk: { - const prefix = self.cache_root; - self.install_prefix = prefix; - break :blk prefix; + const dest_dir = self.dest_dir orelse blk: { + const dest_dir = self.install_prefix orelse self.cache_root; + self.dest_dir = dest_dir; + break :blk dest_dir; }; - - self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "lib" }) catch unreachable; - self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "bin" }) catch unreachable; + self.dest_dir = dest_dir; + self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ dest_dir, "lib" }) catch unreachable; + self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ dest_dir, "bin" }) catch unreachable; } pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { @@ -884,7 +886,7 @@ pub const Builder = struct { fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { const base_dir = switch (dir) { - .Prefix => self.install_prefix.?, + .Prefix => self.dest_dir.?, .Bin => self.exe_dir.?, .Lib => self.lib_dir.?, }; -- cgit v1.2.3 From d6d0bb054219da26a55f880f48f00902a4fbaf56 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 22 Jul 2019 10:45:59 -0400 Subject: zig build: adjust DESTDIR logic now if DESTDIR is provided then the default install prefix is /usr. otherwise the default install prefix is still zig-cache directly. DESTDIR is prepended to the prefix to match what make install does. --- std/build.zig | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/std/build.zig b/std/build.zig index e6e7143f06..3a0c34c8d1 100644 --- a/std/build.zig +++ b/std/build.zig @@ -44,6 +44,7 @@ pub const Builder = struct { dest_dir: ?[]const u8, lib_dir: ?[]const u8, exe_dir: ?[]const u8, + install_path: []const u8, search_prefixes: ArrayList([]const u8), installed_files: ArrayList(InstalledFile), build_root: []const u8, @@ -144,6 +145,7 @@ pub const Builder = struct { .is_release = false, .override_std_dir = null, .override_lib_dir = null, + .install_path = undefined, }; try self.top_level_steps.append(&self.install_tls); try self.top_level_steps.append(&self.uninstall_tls); @@ -166,14 +168,19 @@ pub const Builder = struct { } fn resolveInstallPrefix(self: *Builder) void { - const dest_dir = self.dest_dir orelse blk: { - const dest_dir = self.install_prefix orelse self.cache_root; - self.dest_dir = dest_dir; - break :blk dest_dir; - }; - self.dest_dir = dest_dir; - self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ dest_dir, "lib" }) catch unreachable; - self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ dest_dir, "bin" }) catch unreachable; + if (self.dest_dir) |dest_dir| { + const install_prefix = self.install_prefix orelse "/usr"; + self.install_path = fs.path.join(self.allocator, [_][]const u8{ dest_dir, install_prefix }) catch unreachable; + } else { + const install_prefix = self.install_prefix orelse blk: { + const p = self.cache_root; + self.install_prefix = p; + break :blk p; + }; + self.install_path = install_prefix; + } + self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ self.install_path, "lib" }) catch unreachable; + self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ self.install_path, "bin" }) catch unreachable; } pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { @@ -886,7 +893,7 @@ pub const Builder = struct { fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { const base_dir = switch (dir) { - .Prefix => self.dest_dir.?, + .Prefix => self.install_path, .Bin => self.exe_dir.?, .Lib => self.lib_dir.?, }; -- cgit v1.2.3 From a3327f0fbde0f7eebd6260bb5f47897599434bb4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 22 Jul 2019 12:33:24 -0400 Subject: fix usingnamespace analyzing the expression multiple times --- src/analyze.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index de4d64f5d6..0af1baec35 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3353,7 +3353,8 @@ static void resolve_use_decl(CodeGen *g, TldUsingNamespace *tld_using_namespace, static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, ScopeDecls *dest_decls_scope) { if (using_namespace->base.resolution == TldResolutionOk || - using_namespace->base.resolution == TldResolutionInvalid) + using_namespace->base.resolution == TldResolutionInvalid || + using_namespace->using_namespace_value != nullptr) { return; } -- cgit v1.2.3 From bc31c1280e012377c3a2b00356a5876919a72775 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 22 Jul 2019 12:15:16 -0400 Subject: disable segfault handler when panicking this prevents a segfault in stack trace printing to activate the segfault handler. --- src/codegen.cpp | 277 ++++++++++++++++++++++---------------------- src/codegen.hpp | 3 +- src/main.cpp | 7 +- std/debug.zig | 62 +++++++--- std/os/windows/kernel32.zig | 1 + std/special/start.zig | 14 +-- 6 files changed, 192 insertions(+), 172 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 188c5ccc8d..be694b19f9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -89,126 +89,6 @@ static const char *symbols_that_llvm_depends_on[] = { // TODO probably all of compiler-rt needs to go here }; -CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, - OutType out_type, BuildMode build_mode, Buf *override_lib_dir, Buf *override_std_dir, - ZigLibCInstallation *libc, Buf *cache_dir) -{ - CodeGen *g = allocate(1); - - codegen_add_time_event(g, "Initialize"); - - g->subsystem = TargetSubsystemAuto; - g->libc = libc; - g->zig_target = target; - g->cache_dir = cache_dir; - - if (override_lib_dir == nullptr) { - g->zig_lib_dir = get_zig_lib_dir(); - } else { - g->zig_lib_dir = override_lib_dir; - } - - if (override_std_dir == nullptr) { - g->zig_std_dir = buf_alloc(); - os_path_join(g->zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir); - } else { - g->zig_std_dir = override_std_dir; - } - - g->zig_c_headers_dir = buf_alloc(); - os_path_join(g->zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir); - - g->build_mode = build_mode; - g->out_type = out_type; - g->import_table.init(32); - g->builtin_fn_table.init(32); - g->primitive_type_table.init(32); - g->type_table.init(32); - g->fn_type_table.init(32); - g->error_table.init(16); - g->generic_table.init(16); - g->llvm_fn_table.init(16); - g->memoized_fn_eval_table.init(16); - g->exported_symbol_names.init(8); - g->external_prototypes.init(8); - g->string_literals_table.init(16); - g->type_info_cache.init(32); - g->is_test_build = false; - g->is_single_threaded = false; - buf_resize(&g->global_asm, 0); - - for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) { - g->external_prototypes.put(buf_create_from_str(symbols_that_llvm_depends_on[i]), nullptr); - } - - if (root_src_path) { - Buf *root_pkg_path; - Buf *rel_root_src_path; - if (main_pkg_path == nullptr) { - Buf *src_basename = buf_alloc(); - Buf *src_dir = buf_alloc(); - os_path_split(root_src_path, src_dir, src_basename); - - if (buf_len(src_basename) == 0) { - fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path)); - exit(1); - } - root_pkg_path = src_dir; - rel_root_src_path = src_basename; - } else { - Buf resolved_root_src_path = os_path_resolve(&root_src_path, 1); - Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1); - - if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) { - fprintf(stderr, "Root source path '%s' outside main package path '%s'", - buf_ptr(root_src_path), buf_ptr(main_pkg_path)); - exit(1); - } - root_pkg_path = main_pkg_path; - rel_root_src_path = buf_create_from_mem( - buf_ptr(&resolved_root_src_path) + buf_len(&resolved_main_pkg_path) + 1, - buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1); - } - - g->root_package = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), ""); - g->std_package = new_package(buf_ptr(g->zig_std_dir), "std.zig", "std"); - g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); - } else { - g->root_package = new_package(".", "", ""); - } - - g->root_package->package_table.put(buf_create_from_str("root"), g->root_package); - - g->zig_std_special_dir = buf_alloc(); - os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir); - - assert(target != nullptr); - if (!target->is_native) { - g->each_lib_rpath = false; - } else { - g->each_lib_rpath = true; - - if (target_os_is_darwin(g->zig_target->os)) { - init_darwin_native(g); - } - - } - - if (target_os_requires_libc(g->zig_target->os)) { - g->libc_link_lib = create_link_lib(buf_create_from_str("c")); - g->link_libs_list.append(g->libc_link_lib); - } - - target_triple_llvm(&g->llvm_triple_str, g->zig_target); - g->pointer_size_bytes = target_arch_pointer_bit_width(g->zig_target->arch) / 8; - - if (!target_has_debug_info(g->zig_target)) { - g->strip_debug_symbols = true; - } - - return g; -} - void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) { g->clang_argv = args; g->clang_argv_len = len; @@ -233,10 +113,6 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc g->version_patch = patch; } -void codegen_set_is_test(CodeGen *g, bool is_test_build) { - g->is_test_build = is_test_build; -} - void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) { g->emit_file_type = emit_file_type; } @@ -7994,6 +7870,14 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { return contents; } +static ZigPackage *create_test_runner_pkg(CodeGen *g) { + return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "test_runner.zig", "std.special"); +} + +static ZigPackage *create_panic_pkg(CodeGen *g) { + return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "panic.zig", "std.special"); +} + static Error define_builtin_compile_vars(CodeGen *g) { if (g->std_package == nullptr) return ErrorNone; @@ -8078,8 +7962,16 @@ static Error define_builtin_compile_vars(CodeGen *g) { g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); g->std_package->package_table.put(buf_create_from_str("std"), g->std_package); - g->std_package->package_table.put(buf_create_from_str("root"), - g->is_test_build ? g->test_runner_package : g->root_package); + ZigPackage *root_pkg; + if (g->is_test_build) { + if (g->test_runner_package == nullptr) { + g->test_runner_package = create_test_runner_pkg(g); + } + root_pkg = g->test_runner_package; + } else { + root_pkg = g->root_package; + } + g->std_package->package_table.put(buf_create_from_str("root"), root_pkg); g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents, SourceKindPkgMain); @@ -8571,14 +8463,6 @@ static ZigPackage *create_start_pkg(CodeGen *g, ZigPackage *pkg_with_main) { return package; } -static ZigPackage *create_test_runner_pkg(CodeGen *g) { - return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "test_runner.zig", "std.special"); -} - -static ZigPackage *create_panic_pkg(CodeGen *g) { - return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "panic.zig", "std.special"); -} - static void create_test_compile_var_and_add_test_runner(CodeGen *g) { Error err; @@ -8628,7 +8512,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); update_compile_var(g, buf_create_from_str("test_functions"), test_fn_slice); - g->test_runner_package = create_test_runner_pkg(g); + assert(g->test_runner_package != nullptr); g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig"); } @@ -9742,7 +9626,8 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o ZigLibCInstallation *libc) { CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type, - parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path()); + parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path(), + false); child_gen->disable_gen_h = true; child_gen->want_stack_check = WantStackCheckDisabled; child_gen->verbose_tokenize = parent_gen->verbose_tokenize; @@ -9769,3 +9654,123 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o return child_gen; } +CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, + OutType out_type, BuildMode build_mode, Buf *override_lib_dir, Buf *override_std_dir, + ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build) +{ + CodeGen *g = allocate(1); + + codegen_add_time_event(g, "Initialize"); + + g->subsystem = TargetSubsystemAuto; + g->libc = libc; + g->zig_target = target; + g->cache_dir = cache_dir; + + if (override_lib_dir == nullptr) { + g->zig_lib_dir = get_zig_lib_dir(); + } else { + g->zig_lib_dir = override_lib_dir; + } + + if (override_std_dir == nullptr) { + g->zig_std_dir = buf_alloc(); + os_path_join(g->zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir); + } else { + g->zig_std_dir = override_std_dir; + } + + g->zig_c_headers_dir = buf_alloc(); + os_path_join(g->zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir); + + g->build_mode = build_mode; + g->out_type = out_type; + g->import_table.init(32); + g->builtin_fn_table.init(32); + g->primitive_type_table.init(32); + g->type_table.init(32); + g->fn_type_table.init(32); + g->error_table.init(16); + g->generic_table.init(16); + g->llvm_fn_table.init(16); + g->memoized_fn_eval_table.init(16); + g->exported_symbol_names.init(8); + g->external_prototypes.init(8); + g->string_literals_table.init(16); + g->type_info_cache.init(32); + g->is_test_build = is_test_build; + g->is_single_threaded = false; + buf_resize(&g->global_asm, 0); + + for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) { + g->external_prototypes.put(buf_create_from_str(symbols_that_llvm_depends_on[i]), nullptr); + } + + if (root_src_path) { + Buf *root_pkg_path; + Buf *rel_root_src_path; + if (main_pkg_path == nullptr) { + Buf *src_basename = buf_alloc(); + Buf *src_dir = buf_alloc(); + os_path_split(root_src_path, src_dir, src_basename); + + if (buf_len(src_basename) == 0) { + fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path)); + exit(1); + } + root_pkg_path = src_dir; + rel_root_src_path = src_basename; + } else { + Buf resolved_root_src_path = os_path_resolve(&root_src_path, 1); + Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1); + + if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) { + fprintf(stderr, "Root source path '%s' outside main package path '%s'", + buf_ptr(root_src_path), buf_ptr(main_pkg_path)); + exit(1); + } + root_pkg_path = main_pkg_path; + rel_root_src_path = buf_create_from_mem( + buf_ptr(&resolved_root_src_path) + buf_len(&resolved_main_pkg_path) + 1, + buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1); + } + + g->root_package = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), ""); + g->std_package = new_package(buf_ptr(g->zig_std_dir), "std.zig", "std"); + g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); + } else { + g->root_package = new_package(".", "", ""); + } + + g->root_package->package_table.put(buf_create_from_str("root"), g->root_package); + + g->zig_std_special_dir = buf_alloc(); + os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir); + + assert(target != nullptr); + if (!target->is_native) { + g->each_lib_rpath = false; + } else { + g->each_lib_rpath = true; + + if (target_os_is_darwin(g->zig_target->os)) { + init_darwin_native(g); + } + + } + + if (target_os_requires_libc(g->zig_target->os)) { + g->libc_link_lib = create_link_lib(buf_create_from_str("c")); + g->link_libs_list.append(g->libc_link_lib); + } + + target_triple_llvm(&g->llvm_triple_str, g->zig_target); + g->pointer_size_bytes = target_arch_pointer_bit_width(g->zig_target->arch) / 8; + + if (!target_has_debug_info(g->zig_target)) { + g->strip_debug_symbols = true; + } + + return g; +} + diff --git a/src/codegen.hpp b/src/codegen.hpp index 5de36c1aab..cdff61a26f 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -18,14 +18,13 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir, - ZigLibCInstallation *libc, Buf *cache_dir); + ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build); CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type, ZigLibCInstallation *libc); void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); -void codegen_set_is_test(CodeGen *codegen, bool is_test); void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type); diff --git a/src/main.cpp b/src/main.cpp index ce68e53d85..42d0850046 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -583,7 +583,7 @@ int main(int argc, char **argv) { } CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe, - BuildModeDebug, override_lib_dir, override_std_dir, nullptr, &full_cache_dir); + BuildModeDebug, override_lib_dir, override_std_dir, nullptr, &full_cache_dir, false); g->valgrind_support = valgrind_support; g->enable_time_report = timing_info; codegen_set_out_name(g, buf_create_from_str("build")); @@ -1011,7 +1011,7 @@ int main(int argc, char **argv) { } case CmdBuiltin: { CodeGen *g = codegen_create(main_pkg_path, nullptr, &target, - out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr); + out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr, false); codegen_set_strip(g, strip); for (size_t i = 0; i < link_libs.length; i += 1) { LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i))); @@ -1115,7 +1115,7 @@ int main(int argc, char **argv) { cache_dir_buf = buf_create_from_str(cache_dir); } CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode, - override_lib_dir, override_std_dir, libc, cache_dir_buf); + override_lib_dir, override_std_dir, libc, cache_dir_buf, cmd == CmdTest); if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); g->valgrind_support = valgrind_support; g->want_pic = want_pic; @@ -1125,7 +1125,6 @@ int main(int argc, char **argv) { g->enable_time_report = timing_info; codegen_set_out_name(g, buf_out_name); codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); - codegen_set_is_test(g, cmd == CmdTest); g->want_single_threaded = want_single_threaded; codegen_set_linker_script(g, linker_script); g->version_script_path = version_script; diff --git a/std/debug.zig b/std/debug.zig index d81e62901a..7d1fd6ce47 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -12,6 +12,7 @@ const coff = std.coff; const pdb = std.pdb; const ArrayList = std.ArrayList; const builtin = @import("builtin"); +const root = @import("root"); const maxInt = std.math.maxInt; const File = std.fs.File; const windows = std.os.windows; @@ -217,6 +218,12 @@ var panicking: u8 = 0; // TODO make this a bool pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn { @setCold(true); + if (enable_segfault_handler) { + // If a segfault happens while panicking, we want it to actually segfault, not trigger + // the handler. + resetSegfaultHandler(); + } + if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) { // Panicked during a panic. @@ -2312,39 +2319,58 @@ fn getDebugInfoAllocator() *mem.Allocator { /// Whether or not the current target can print useful debug information when a segfault occurs. pub const have_segfault_handling_support = (builtin.arch == builtin.Arch.x86_64 and builtin.os == .linux) or builtin.os == .windows; +pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler")) + root.enable_segfault_handler +else + runtime_safety and have_segfault_handling_support; + +pub fn maybeEnableSegfaultHandler() void { + if (enable_segfault_handler) { + std.debug.attachSegfaultHandler(); + } +} + +var windows_segfault_handle: ?windows.HANDLE = null; /// Attaches a global SIGSEGV handler which calls @panic("segmentation fault"); pub fn attachSegfaultHandler() void { if (!have_segfault_handling_support) { @compileError("segfault handler not supported for this target"); } - switch (builtin.os) { - .linux => { - var act = os.Sigaction{ - .sigaction = handleSegfaultLinux, - .mask = os.empty_sigset, - .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND), - }; - - os.sigaction(os.SIGSEGV, &act, null); - }, - .windows => { - _ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); - }, - else => unreachable, + if (windows.is_the_target) { + windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); + return; } + var act = os.Sigaction{ + .sigaction = handleSegfaultLinux, + .mask = os.empty_sigset, + .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND), + }; + + os.sigaction(os.SIGSEGV, &act, null); } -extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn { - // Reset to the default handler so that if a segfault happens in this handler it will crash - // the process. Also when this handler returns, the original instruction will be repeated - // and the resulting segfault will crash the process rather than continually dump stack traces. +fn resetSegfaultHandler() void { + if (windows.is_the_target) { + if (windows_segfault_handle) |handle| { + assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0); + windows_segfault_handle = null; + } + return; + } var act = os.Sigaction{ .sigaction = os.SIG_DFL, .mask = os.empty_sigset, .flags = 0, }; os.sigaction(os.SIGSEGV, &act, null); +} + +extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn { + // Reset to the default handler so that if a segfault happens in this handler it will crash + // the process. Also when this handler returns, the original instruction will be repeated + // and the resulting segfault will crash the process rather than continually dump stack traces. + resetSegfaultHandler(); const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr)); const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]); diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig index e4edc349ab..2ae73ad45a 100644 --- a/std/os/windows/kernel32.zig +++ b/std/os/windows/kernel32.zig @@ -1,6 +1,7 @@ usingnamespace @import("bits.zig"); pub extern "kernel32" stdcallcc fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) ?*c_void; +pub extern "kernel32" stdcallcc fn RemoveVectoredExceptionHandler(Handle: HANDLE) c_ulong; pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL; diff --git a/std/special/start.zig b/std/special/start.zig index 30298669e3..f8a018e0ae 100644 --- a/std/special/start.zig +++ b/std/special/start.zig @@ -24,16 +24,6 @@ comptime { } } -fn enableSegfaultHandler() void { - const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler")) - root.enable_segfault_handler - else - std.debug.runtime_safety and std.debug.have_segfault_handling_support; - if (enable_segfault_handler) { - std.debug.attachSegfaultHandler(); - } -} - extern fn wasm_freestanding_start() void { _ = callMain(); } @@ -72,7 +62,7 @@ extern fn WinMainCRTStartup() noreturn { _ = @import("start_windows_tls.zig"); } - enableSegfaultHandler(); + std.debug.maybeEnableSegfaultHandler(); std.os.windows.kernel32.ExitProcess(callMain()); } @@ -113,7 +103,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 { std.os.argv = argv[0..argc]; std.os.environ = envp; - enableSegfaultHandler(); + std.debug.maybeEnableSegfaultHandler(); return callMain(); } -- cgit v1.2.3 From 16be70cbbf8e6dc658b9fcacd3366df8f83fffa8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 18 Jul 2019 13:54:22 -0400 Subject: compiler-rt: add __muldi3 --- build.zig | 9 ++++-- std/special/compiler_rt.zig | 3 ++ std/special/compiler_rt/divti3.zig | 1 - std/special/compiler_rt/muldi3.zig | 54 +++++++++++++++++++++++++++++++++ std/special/compiler_rt/muldi3_test.zig | 51 +++++++++++++++++++++++++++++++ test/tests.zig | 3 +- 6 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 std/special/compiler_rt/muldi3.zig create mode 100644 std/special/compiler_rt/muldi3_test.zig diff --git a/build.zig b/build.zig index 07041d026f..011f742d82 100644 --- a/build.zig +++ b/build.zig @@ -122,16 +122,19 @@ pub fn build(b: *Builder) !void { } const modes = chosen_modes[0..chosen_mode_index]; + const multi_and_single = [_]bool{ false, true }; + const just_multi = [_]bool{false}; + // run stage1 `zig fmt` on this build.zig file just to make sure it works test_step.dependOn(&fmt_build_zig.step); const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works"); fmt_step.dependOn(&fmt_build_zig.step); - test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes, skip_non_native)); + test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes, multi_and_single, skip_non_native)); - test_step.dependOn(tests.addPkgTests(b, test_filter, "std/std.zig", "std", "Run the standard library tests", modes, skip_non_native)); + test_step.dependOn(tests.addPkgTests(b, test_filter, "std/std.zig", "std", "Run the standard library tests", modes, multi_and_single, skip_non_native)); - test_step.dependOn(tests.addPkgTests(b, test_filter, "std/special/compiler_rt.zig", "compiler-rt", "Run the compiler_rt tests", modes, skip_non_native)); + test_step.dependOn(tests.addPkgTests(b, test_filter, "std/special/compiler_rt.zig", "compiler-rt", "Run the compiler_rt tests", modes, just_multi, skip_non_native)); test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); diff --git a/std/special/compiler_rt.zig b/std/special/compiler_rt.zig index 5064e9db29..a5bbefa1db 100644 --- a/std/special/compiler_rt.zig +++ b/std/special/compiler_rt.zig @@ -127,6 +127,7 @@ comptime { @export("__udivmoddi4", @import("compiler_rt/udivmoddi4.zig").__udivmoddi4, linkage); @export("__popcountdi2", @import("compiler_rt/popcountdi2.zig").__popcountdi2, linkage); + @export("__muldi3", @import("compiler_rt/muldi3.zig").__muldi3, linkage); @export("__divmoddi4", __divmoddi4, linkage); @export("__divsi3", __divsi3, linkage); @export("__divdi3", __divdi3, linkage); @@ -147,6 +148,8 @@ comptime { @export("__aeabi_unwind_cpp_pr1", __aeabi_unwind_cpp_pr1, linkage); @export("__aeabi_unwind_cpp_pr2", __aeabi_unwind_cpp_pr2, linkage); + @export("__aeabi_lmul", @import("compiler_rt/muldi3.zig").__muldi3, linkage); + @export("__aeabi_ldivmod", __aeabi_ldivmod, linkage); @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); diff --git a/std/special/compiler_rt/divti3.zig b/std/special/compiler_rt/divti3.zig index d5b2778a34..477ce2cb98 100644 --- a/std/special/compiler_rt/divti3.zig +++ b/std/special/compiler_rt/divti3.zig @@ -1,6 +1,5 @@ const udivmod = @import("udivmod.zig").udivmod; const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); pub extern fn __divti3(a: i128, b: i128) i128 { @setRuntimeSafety(builtin.is_test); diff --git a/std/special/compiler_rt/muldi3.zig b/std/special/compiler_rt/muldi3.zig new file mode 100644 index 0000000000..7a955120f5 --- /dev/null +++ b/std/special/compiler_rt/muldi3.zig @@ -0,0 +1,54 @@ +const builtin = @import("builtin"); + +// Ported from +// https://github.com/llvm/llvm-project/blob/552c2c09d354a3ad9c1c9647e0a3bb5099c31088/compiler-rt/lib/builtins/muldi3.c + +const dwords = extern union { + all: i64, + s: switch (builtin.endian) { + .Little => extern struct { + low: u32, + high: u32, + }, + .Big => extern struct { + high: u32, + low: u32, + }, + }, +}; + +fn __muldsi3(a: u32, b: u32) i64 { + @setRuntimeSafety(builtin.is_test); + + const bits_in_word_2 = @sizeOf(i32) * 8 / 2; + const lower_mask = (~u32(0)) >> bits_in_word_2; + + var r: dwords = undefined; + r.s.low = (a & lower_mask) *% (b & lower_mask); + var t: u32 = r.s.low >> bits_in_word_2; + r.s.low &= lower_mask; + t += (a >> bits_in_word_2) *% (b & lower_mask); + r.s.low +%= (t & lower_mask) << bits_in_word_2; + r.s.high = t >> bits_in_word_2; + t = r.s.low >> bits_in_word_2; + r.s.low &= lower_mask; + t +%= (b >> bits_in_word_2) *% (a & lower_mask); + r.s.low +%= (t & lower_mask) << bits_in_word_2; + r.s.high +%= t >> bits_in_word_2; + r.s.high +%= (a >> bits_in_word_2) *% (b >> bits_in_word_2); + return r.all; +} + +pub extern fn __muldi3(a: i64, b: i64) i64 { + @setRuntimeSafety(builtin.is_test); + + const x = dwords{ .all = a }; + const y = dwords{ .all = b }; + var r = dwords{ .all = __muldsi3(x.s.low, y.s.low) }; + r.s.high +%= x.s.high *% y.s.low +% x.s.low *% y.s.high; + return r.all; +} + +test "import muldi3" { + _ = @import("muldi3_test.zig"); +} diff --git a/std/special/compiler_rt/muldi3_test.zig b/std/special/compiler_rt/muldi3_test.zig new file mode 100644 index 0000000000..db4daf1e1e --- /dev/null +++ b/std/special/compiler_rt/muldi3_test.zig @@ -0,0 +1,51 @@ +const __muldi3 = @import("muldi3.zig").__muldi3; +const testing = @import("std").testing; + +fn test__muldi3(a: i64, b: i64, expected: i64) void { + const x = __muldi3(a, b); + testing.expect(x == expected); +} + +test "muldi3" { + test__muldi3(0, 0, 0); + test__muldi3(0, 1, 0); + test__muldi3(1, 0, 0); + test__muldi3(0, 10, 0); + test__muldi3(10, 0, 0); + test__muldi3(0, 81985529216486895, 0); + test__muldi3(81985529216486895, 0, 0); + + test__muldi3(0, -1, 0); + test__muldi3(-1, 0, 0); + test__muldi3(0, -10, 0); + test__muldi3(-10, 0, 0); + test__muldi3(0, -81985529216486895, 0); + test__muldi3(-81985529216486895, 0, 0); + + test__muldi3(1, 1, 1); + test__muldi3(1, 10, 10); + test__muldi3(10, 1, 10); + test__muldi3(1, 81985529216486895, 81985529216486895); + test__muldi3(81985529216486895, 1, 81985529216486895); + + test__muldi3(1, -1, -1); + test__muldi3(1, -10, -10); + test__muldi3(-10, 1, -10); + test__muldi3(1, -81985529216486895, -81985529216486895); + test__muldi3(-81985529216486895, 1, -81985529216486895); + + test__muldi3(3037000499, 3037000499, 9223372030926249001); + test__muldi3(-3037000499, 3037000499, -9223372030926249001); + test__muldi3(3037000499, -3037000499, -9223372030926249001); + test__muldi3(-3037000499, -3037000499, 9223372030926249001); + + test__muldi3(4398046511103, 2097152, 9223372036852678656); + test__muldi3(-4398046511103, 2097152, -9223372036852678656); + test__muldi3(4398046511103, -2097152, -9223372036852678656); + test__muldi3(-4398046511103, -2097152, 9223372036852678656); + + test__muldi3(2097152, 4398046511103, 9223372036852678656); + test__muldi3(-2097152, 4398046511103, -9223372036852678656); + test__muldi3(2097152, -4398046511103, -9223372036852678656); + test__muldi3(-2097152, -4398046511103, 9223372036852678656); +} diff --git a/test/tests.zig b/test/tests.zig index d94c012ac1..c8aea33591 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -170,6 +170,7 @@ pub fn addPkgTests( name: []const u8, desc: []const u8, modes: []const Mode, + single_threaded_list: []const bool, skip_non_native: bool, ) *build.Step { const step = b.step(b.fmt("test-{}", name), desc); @@ -179,7 +180,7 @@ pub fn addPkgTests( continue; for (modes) |mode| { for ([_]bool{ false, true }) |link_libc| { - for ([_]bool{ false, true }) |single_threaded| { + for (single_threaded_list) |single_threaded| { if (link_libc and !is_native) { // don't assume we have a cross-compiling libc set up continue; -- cgit v1.2.3