From 89763c9a0d9a838439bcc6cd996c0ff2d3d0daca Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 16 Apr 2019 16:47:47 -0400 Subject: [PATCH] stage1 is now a hybrid of C++ and Zig This modifies the build process of Zig to put all of the source files into libcompiler.a, except main.cpp and userland.cpp. Next, the build process links main.cpp, userland.cpp, and libcompiler.a into zig1. userland.cpp is a shim for functions that will later be replaced with self-hosted implementations. Next, the build process uses zig1 to build src-self-hosted/stage1.zig into libuserland.a, which does not depend on any of the things that are shimmed in userland.cpp, such as translate-c. Finally, the build process re-links main.cpp and libcompiler.a, except with libuserland.a instead of userland.cpp. Now the shims are replaced with .zig code. This provides all of the Zig standard library to the stage1 C++ compiler, and enables us to move certain things to userland, such as translate-c. As a proof of concept I have made the `zig zen` command use text defined in userland. I added `zig translate-c-2` which is a work-in-progress reimplementation of translate-c in userland, which currently calls `std.debug.panic("unimplemented")` and you can see the stack trace makes it all the way back into the C++ main() function (Thanks LemonBoy for improving that!). This could potentially let us move other things into userland, such as hashing algorithms, the entire cache system, .d file parsing, pretty much anything that libuserland.a itself doesn't need to depend on. This can also let us have `zig fmt` in stage1 without the overhead of child process execution, and without the initial compilation delay before it gets cached. See #1964 --- CMakeLists.txt | 61 +++++++++++++++---- build.zig | 19 ++++++ src-self-hosted/main.zig | 18 +----- src-self-hosted/stage1.zig | 27 +++++++++ src-self-hosted/translate_c.zig | 8 +++ src/codegen.cpp | 22 +++++-- src/codegen.hpp | 2 +- src/compiler.cpp | 8 +-- src/compiler.hpp | 4 +- src/main.cpp | 101 +++++++++++++++++++------------- src/userland.cpp | 10 ++++ src/userland.h | 23 ++++++++ std/build.zig | 17 ++++++ std/special/build_runner.zig | 30 +++++++--- 14 files changed, 261 insertions(+), 89 deletions(-) create mode 100644 src-self-hosted/stage1.zig create mode 100644 src-self-hosted/translate_c.zig create mode 100644 src/userland.cpp create mode 100644 src/userland.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 38bd9a2a7..1bc9d2f04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -407,6 +407,12 @@ set(SOFTFLOAT_LIBRARIES embedded_softfloat) find_package(Threads) +# CMake doesn't let us create an empty executable, so we hang on to this one separately. +set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp") + +# This is our shim which will be replaced by libuserland written in Zig. +set(ZIG1_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp") + set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/analyze.cpp" "${CMAKE_SOURCE_DIR}/src/ast_render.cpp" @@ -423,7 +429,6 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/ir_print.cpp" "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp" "${CMAKE_SOURCE_DIR}/src/link.cpp" - "${CMAKE_SOURCE_DIR}/src/main.cpp" "${CMAKE_SOURCE_DIR}/src/os.cpp" "${CMAKE_SOURCE_DIR}/src/parser.cpp" "${CMAKE_SOURCE_DIR}/src/range_set.cpp" @@ -6635,19 +6640,19 @@ add_library(zig_cpp STATIC ${ZIG_CPP_SOURCES}) set_target_properties(zig_cpp PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} ) +install(TARGETS zig_cpp DESTINATION "${ZIG_CPP_LIB_DIR}") add_library(opt_c_util STATIC ${OPTIMIZED_C_SOURCES}) set_target_properties(opt_c_util PROPERTIES COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}" ) -add_executable(zig ${ZIG_SOURCES}) -set_target_properties(zig PROPERTIES +add_library(compiler STATIC ${ZIG_SOURCES}) +set_target_properties(compiler PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} LINK_FLAGS ${EXE_LDFLAGS} ) - -target_link_libraries(zig LINK_PUBLIC +target_link_libraries(compiler LINK_PUBLIC zig_cpp opt_c_util ${SOFTFLOAT_LIBRARIES} @@ -6656,24 +6661,58 @@ target_link_libraries(zig LINK_PUBLIC ${LLVM_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) - if(NOT MSVC) - target_link_libraries(zig LINK_PUBLIC ${LIBXML2}) + target_link_libraries(compiler LINK_PUBLIC ${LIBXML2}) endif() if(MINGW) - target_link_libraries(zig LINK_PUBLIC ${Z3_LIBRARIES}) + target_link_libraries(compiler LINK_PUBLIC ${Z3_LIBRARIES}) endif() if(ZIG_DIA_GUIDS_LIB) - target_link_libraries(zig LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB}) + target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB}) endif() if(MSVC OR MINGW) - target_link_libraries(zig LINK_PUBLIC version) + target_link_libraries(compiler LINK_PUBLIC version) endif() + +add_executable(zig1 "${ZIG_MAIN_SRC}" "${ZIG1_SHIM_SRC}") +set_target_properties(zig1 PROPERTIES + COMPILE_FLAGS ${EXE_CFLAGS} + LINK_FLAGS ${EXE_LDFLAGS} +) +target_link_libraries(zig1 compiler) + +if(WIN32) + set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib") +elseif(APPLE) + set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.o") +else() + set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a") +endif() +add_custom_command( + OUTPUT "${LIBUSERLAND}" + COMMAND zig1 ARGS build + --override-std-dir std + --override-lib-dir "${CMAKE_SOURCE_DIR}" + libuserland + "-Doutput-dir=${CMAKE_BINARY_DIR}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + DEPENDS + "${CMAKE_SOURCE_DIR}/src-self-hosted/stage1.zig" + "${CMAKE_SOURCE_DIR}/src-self-hosted/translate_c.zig" +) +add_custom_target(userland_target DEPENDS "${LIBUSERLAND}") +add_executable(zig "${ZIG_MAIN_SRC}") +set_target_properties(zig PROPERTIES + COMPILE_FLAGS ${EXE_CFLAGS} + LINK_FLAGS ${EXE_LDFLAGS} +) +target_link_libraries(zig compiler "${LIBUSERLAND}") +add_dependencies(zig userland_target) install(TARGETS zig DESTINATION bin) -install(TARGETS zig_cpp DESTINATION "${ZIG_CPP_LIB_DIR}") + foreach(file ${ZIG_C_HEADER_FILES}) get_filename_component(file_dir "${C_HEADERS_DEST}/${file}" DIRECTORY) diff --git a/build.zig b/build.zig index 2dc9c671e..a53743ca3 100644 --- a/build.zig +++ b/build.zig @@ -65,6 +65,8 @@ pub fn build(b: *Builder) !void { b.default_step.dependOn(&exe.step); + addLibUserlandStep(b); + const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false; const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release; const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release; @@ -380,3 +382,20 @@ const Context = struct { dia_guids_lib: []const u8, llvm: LibraryDep, }; + +fn addLibUserlandStep(b: *Builder) void { + const artifact = if (builtin.os == .macosx) + b.addObject("userland", "src-self-hosted/stage1.zig") + else + b.addStaticLibrary("userland", "src-self-hosted/stage1.zig"); + artifact.disable_gen_h = true; + const libuserland_step = b.step("libuserland", "Build the userland compiler library for use in stage1"); + libuserland_step.dependOn(&artifact.step); + + const output_dir = b.option( + []const u8, + "output-dir", + "For libuserland step, where to put the output", + ) orelse return; + artifact.setOutputDir(output_dir); +} diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 4c3edf6d5..361afc80e 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -858,23 +858,7 @@ fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { try stdout.write(usage); } -const info_zen = - \\ - \\ * Communicate intent precisely. - \\ * Edge cases matter. - \\ * Favor reading code over writing code. - \\ * Only one obvious way to do things. - \\ * Runtime crashes are better than bugs. - \\ * Compile errors are better than runtime crashes. - \\ * Incremental improvements. - \\ * Avoid local maximums. - \\ * Reduce the amount one must remember. - \\ * Minimize energy spent on coding style. - \\ * Together we serve end users. - \\ - \\ -; - +const info_zen = @import("stage1.zig").info_zen; fn cmdZen(allocator: *Allocator, args: []const []const u8) !void { try stdout.write(info_zen); } diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig new file mode 100644 index 000000000..bf400113e --- /dev/null +++ b/src-self-hosted/stage1.zig @@ -0,0 +1,27 @@ +// This is Zig code that is used by both stage1 and stage2. +// The prototypes in src/userland.h must match these definitions. +comptime { + _ = @import("translate_c.zig"); +} + +pub const info_zen = + \\ + \\ * Communicate intent precisely. + \\ * Edge cases matter. + \\ * Favor reading code over writing code. + \\ * Only one obvious way to do things. + \\ * Runtime crashes are better than bugs. + \\ * Compile errors are better than runtime crashes. + \\ * Incremental improvements. + \\ * Avoid local maximums. + \\ * Reduce the amount one must remember. + \\ * Minimize energy spent on coding style. + \\ * Together we serve end users. + \\ + \\ +; + +export fn stage2_zen(ptr: *[*]const u8, len: *usize) void { + ptr.* = &info_zen; + len.* = info_zen.len; +} diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig new file mode 100644 index 000000000..e182a5a99 --- /dev/null +++ b/src-self-hosted/translate_c.zig @@ -0,0 +1,8 @@ +// This is the userland implementation of translate-c which will be used by both stage1 +// and stage2. Currently it's not used by anything, as it's not feature complete. + +const std = @import("std"); + +export fn stage2_translate_c() void { + std.debug.panic("unimplemented"); +} diff --git a/src/codegen.cpp b/src/codegen.cpp index 8eea4e87f..33049abd6 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -19,6 +19,7 @@ #include "target.hpp" #include "util.hpp" #include "zig_llvm.h" +#include "userland.h" #include #include @@ -92,7 +93,7 @@ static const char *symbols_that_llvm_depends_on[] = { }; 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, + OutType out_type, BuildMode build_mode, Buf *override_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc, Buf *cache_dir) { CodeGen *g = allocate(1); @@ -100,19 +101,24 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget codegen_add_time_event(g, "Initialize"); g->libc = libc; - g->zig_lib_dir = zig_lib_dir; 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(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir); + 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(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir); + 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; @@ -8147,7 +8153,7 @@ static void detect_libc(CodeGen *g) { } } -AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) { +AstNode *codegen_translate_c(CodeGen *g, Buf *full_path, bool use_userland_implementation) { Buf *src_basename = buf_alloc(); Buf *src_dirname = buf_alloc(); os_path_split(full_path, src_dirname, src_basename); @@ -8159,6 +8165,12 @@ AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) { init(g); + if (use_userland_implementation) { + // TODO improve this + stage2_translate_c(); + zig_panic("TODO"); + } + ZigList errors = {0}; AstNode *root_node; Error err = parse_h_file(&root_node, &errors, buf_ptr(full_path), g, nullptr); diff --git a/src/codegen.hpp b/src/codegen.hpp index 3befca2de..d6149bf5d 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -50,7 +50,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c void codegen_add_assembly(CodeGen *g, Buf *path); void codegen_add_object(CodeGen *g, Buf *object_path); -AstNode *codegen_translate_c(CodeGen *g, Buf *path); +AstNode *codegen_translate_c(CodeGen *g, Buf *path, bool use_userland_implementation); Buf *codegen_generate_builtin_source(CodeGen *g); diff --git a/src/compiler.cpp b/src/compiler.cpp index af62173db..8bfe87bfc 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -179,24 +179,24 @@ Buf *get_zig_lib_dir(void) { return &saved_lib_dir; } -Buf *get_zig_std_dir() { +Buf *get_zig_std_dir(Buf *zig_lib_dir) { if (saved_std_dir.list.length != 0) { return &saved_std_dir; } buf_resize(&saved_std_dir, 0); - os_path_join(get_zig_lib_dir(), buf_create_from_str("std"), &saved_std_dir); + os_path_join(zig_lib_dir, buf_create_from_str("std"), &saved_std_dir); return &saved_std_dir; } -Buf *get_zig_special_dir() { +Buf *get_zig_special_dir(Buf *zig_lib_dir) { if (saved_special_dir.list.length != 0) { return &saved_special_dir; } buf_resize(&saved_special_dir, 0); - os_path_join(get_zig_std_dir(), buf_sprintf("special"), &saved_special_dir); + os_path_join(get_zig_std_dir(zig_lib_dir), buf_sprintf("special"), &saved_special_dir); return &saved_special_dir; } diff --git a/src/compiler.hpp b/src/compiler.hpp index f2788b999..4d682ba2f 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -16,7 +16,7 @@ Error get_compiler_id(Buf **result); Buf *get_self_dynamic_linker_path(void); Buf *get_zig_lib_dir(void); -Buf *get_zig_special_dir(void); -Buf *get_zig_std_dir(void); +Buf *get_zig_special_dir(Buf *zig_lib_dir); +Buf *get_zig_std_dir(Buf *zig_lib_dir); #endif diff --git a/src/main.cpp b/src/main.cpp index 5123512d1..03cf3aad6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,7 @@ #include "os.hpp" #include "target.hpp" #include "libc_installation.hpp" +#include "userland.h" #include @@ -40,6 +41,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " libc [paths_file] Display native libc paths file or validate one\n" " run [source] [-- [args]] create executable and run immediately\n" " translate-c [source] convert c code to zig code\n" + " translate-c-2 [source] experimental self-hosted translate-c\n" " targets list available compilation targets\n" " test [source] create and run a test build\n" " version print version number and exit\n" @@ -131,19 +133,6 @@ static int print_libc_usage(const char *arg0, FILE *file, int return_code) { return return_code; } -static const char *ZIG_ZEN = "\n" -" * Communicate intent precisely.\n" -" * Edge cases matter.\n" -" * Favor reading code over writing code.\n" -" * Only one obvious way to do things.\n" -" * Runtime crashes are better than bugs.\n" -" * Compile errors are better than runtime crashes.\n" -" * Incremental improvements.\n" -" * Avoid local maximums.\n" -" * Reduce the amount one must remember.\n" -" * Minimize energy spent on coding style.\n" -" * Together we serve end users.\n"; - static bool arch_available_in_llvm(ZigLLVM_ArchType arch) { LLVMTargetRef target_ref; char *err_msg = nullptr; @@ -211,6 +200,7 @@ enum Cmd { CmdTargets, CmdTest, CmdTranslateC, + CmdTranslateCUserland, CmdVersion, CmdZen, CmdLibC, @@ -324,7 +314,7 @@ int main(int argc, char **argv) { return print_error_usage(arg0); } Buf *cmd_template_path = buf_alloc(); - os_path_join(get_zig_special_dir(), buf_create_from_str(init_cmd), cmd_template_path); + os_path_join(get_zig_special_dir(get_zig_lib_dir()), buf_create_from_str(init_cmd), cmd_template_path); Buf *build_zig_path = buf_alloc(); os_path_join(cmd_template_path, buf_create_from_str("build.zig"), build_zig_path); Buf *src_dir_path = buf_alloc(); @@ -453,6 +443,7 @@ int main(int argc, char **argv) { bool want_single_threaded = false; bool disable_gen_h = false; Buf *override_std_dir = nullptr; + Buf *override_lib_dir = nullptr; Buf *main_pkg_path = nullptr; ValgrindSupport valgrind_support = ValgrindSupportAuto; WantPIC want_pic = WantPICAuto; @@ -486,13 +477,27 @@ int main(int argc, char **argv) { } else if (i + 1 < argc && strcmp(argv[i], "--cache-dir") == 0) { cache_dir = argv[i + 1]; i += 1; + } else if (i + 1 < argc && strcmp(argv[i], "--override-std-dir") == 0) { + override_std_dir = buf_create_from_str(argv[i + 1]); + i += 1; + + args.append("--override-std-dir"); + args.append(buf_ptr(override_std_dir)); + } else if (i + 1 < argc && strcmp(argv[i], "--override-lib-dir") == 0) { + override_lib_dir = buf_create_from_str(argv[i + 1]); + i += 1; + + args.append("--override-lib-dir"); + args.append(buf_ptr(override_lib_dir)); } else { args.append(argv[i]); } } + Buf *zig_lib_dir = (override_lib_dir == nullptr) ? get_zig_lib_dir() : override_lib_dir; + Buf *build_runner_path = buf_alloc(); - os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path); + os_path_join(get_zig_special_dir(zig_lib_dir), buf_create_from_str("build_runner.zig"), build_runner_path); ZigTarget target; get_native_target(&target); @@ -512,7 +517,7 @@ int main(int argc, char **argv) { } CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe, - BuildModeDebug, get_zig_lib_dir(), override_std_dir, nullptr, &full_cache_dir); + BuildModeDebug, override_lib_dir, override_std_dir, nullptr, &full_cache_dir); g->valgrind_support = valgrind_support; g->enable_time_report = timing_info; codegen_set_out_name(g, buf_create_from_str("build")); @@ -532,23 +537,25 @@ int main(int argc, char **argv) { "Usage: %s build [options]\n" "\n" "General Options:\n" - " --help Print this help and exit\n" - " --verbose Print commands before executing them\n" - " --prefix [path] Override default install prefix\n" - " --search-prefix [path] Add a path to look for binaries, libraries, headers\n" + " --help Print this help and exit\n" + " --verbose Print commands before executing them\n" + " --prefix [path] Override default install prefix\n" + " --search-prefix [path] Add a path to look for binaries, libraries, headers\n" "\n" "Project-specific options become available when the build file is found.\n" "\n" "Advanced Options:\n" - " --build-file [file] Override path to build.zig\n" - " --cache-dir [path] Override path to cache directory\n" - " --verbose-tokenize Enable compiler debug output for tokenization\n" - " --verbose-ast Enable compiler debug output for parsing into an AST\n" - " --verbose-link Enable compiler debug output for linking\n" - " --verbose-ir Enable compiler debug output for Zig IR\n" - " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n" - " --verbose-cimport Enable compiler debug output for C imports\n" - " --verbose-cc Enable compiler debug output for C compilation\n" + " --build-file [file] Override path to build.zig\n" + " --cache-dir [path] Override path to cache directory\n" + " --override-std-dir [arg] Override path to Zig standard library\n" + " --override-lib-dir [arg] Override path to Zig lib library\n" + " --verbose-tokenize Enable compiler debug output for tokenization\n" + " --verbose-ast Enable compiler debug output for parsing into an AST\n" + " --verbose-link Enable compiler debug output for linking\n" + " --verbose-ir Enable compiler debug output for Zig IR\n" + " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n" + " --verbose-cimport Enable compiler debug output for C imports\n" + " --verbose-cc Enable compiler debug output for C compilation\n" "\n" , zig_exe_path); return EXIT_SUCCESS; @@ -584,11 +591,12 @@ int main(int argc, char **argv) { init_all_targets(); ZigTarget target; get_native_target(&target); + Buf *zig_lib_dir = (override_lib_dir == nullptr) ? get_zig_lib_dir() : override_lib_dir; Buf *fmt_runner_path = buf_alloc(); - os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path); + os_path_join(get_zig_special_dir(zig_lib_dir), buf_create_from_str("fmt_runner.zig"), fmt_runner_path); Buf *cache_dir_buf = buf_create_from_str(cache_dir ? cache_dir : default_zig_cache_name); CodeGen *g = codegen_create(main_pkg_path, fmt_runner_path, &target, OutTypeExe, - BuildModeDebug, get_zig_lib_dir(), nullptr, nullptr, cache_dir_buf); + BuildModeDebug, zig_lib_dir, nullptr, nullptr, cache_dir_buf); g->valgrind_support = valgrind_support; g->want_single_threaded = true; codegen_set_out_name(g, buf_create_from_str("fmt")); @@ -757,6 +765,8 @@ int main(int argc, char **argv) { llvm_argv.append(argv[i]); } else if (strcmp(arg, "--override-std-dir") == 0) { override_std_dir = buf_create_from_str(argv[i]); + } else if (strcmp(arg, "--override-lib-dir") == 0) { + override_lib_dir = buf_create_from_str(argv[i]); } else if (strcmp(arg, "--main-pkg-path") == 0) { main_pkg_path = buf_create_from_str(argv[i]); } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) { @@ -867,6 +877,8 @@ int main(int argc, char **argv) { cmd = CmdLibC; } else if (strcmp(arg, "translate-c") == 0) { cmd = CmdTranslateC; + } else if (strcmp(arg, "translate-c-2") == 0) { + cmd = CmdTranslateCUserland; } else if (strcmp(arg, "test") == 0) { cmd = CmdTest; out_type = OutTypeExe; @@ -883,6 +895,7 @@ int main(int argc, char **argv) { case CmdBuild: case CmdRun: case CmdTranslateC: + case CmdTranslateCUserland: case CmdTest: case CmdLibC: if (!in_file) { @@ -959,7 +972,7 @@ int main(int argc, char **argv) { } case CmdBuiltin: { CodeGen *g = codegen_create(main_pkg_path, nullptr, &target, - out_type, build_mode, get_zig_lib_dir(), override_std_dir, nullptr, nullptr); + out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr); g->valgrind_support = valgrind_support; g->want_pic = want_pic; g->want_single_threaded = want_single_threaded; @@ -973,6 +986,7 @@ int main(int argc, char **argv) { case CmdRun: case CmdBuild: case CmdTranslateC: + case CmdTranslateCUserland: case CmdTest: { if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0 && @@ -985,14 +999,16 @@ int main(int argc, char **argv) { " * --assembly argument\n" " * --c-source argument\n"); return print_error_usage(arg0); - } else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) { + } else if ((cmd == CmdTranslateC || cmd == CmdTranslateCUserland || + cmd == CmdTest || cmd == CmdRun) && !in_file) + { fprintf(stderr, "Expected source file argument.\n"); return print_error_usage(arg0); } assert(cmd != CmdBuild || out_type != OutTypeUnknown); - bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC); + bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC || cmd == CmdTranslateCUserland); if (cmd == CmdRun) { out_name = "run"; @@ -1026,7 +1042,8 @@ int main(int argc, char **argv) { return print_error_usage(arg0); } - Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf; + Buf *zig_root_source_file = (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) ? + nullptr : in_file_buf; if (cmd == CmdRun && buf_out_name == nullptr) { buf_out_name = buf_create_from_str("run"); @@ -1050,7 +1067,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, - get_zig_lib_dir(), override_std_dir, libc, cache_dir_buf); + override_lib_dir, override_std_dir, libc, cache_dir_buf); 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; @@ -1170,8 +1187,8 @@ int main(int argc, char **argv) { } else { zig_unreachable(); } - } else if (cmd == CmdTranslateC) { - AstNode *root_node = codegen_translate_c(g, in_file_buf); + } else if (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) { + AstNode *root_node = codegen_translate_c(g, in_file_buf, cmd == CmdTranslateCUserland); ast_render(g, stdout, root_node, 4); if (timing_info) codegen_print_timing_report(g, stderr); @@ -1229,9 +1246,13 @@ int main(int argc, char **argv) { case CmdVersion: printf("%s\n", ZIG_VERSION_STRING); return EXIT_SUCCESS; - case CmdZen: - printf("%s\n", ZIG_ZEN); + case CmdZen: { + const char *ptr; + size_t len; + stage2_zen(&ptr, &len); + fwrite(ptr, len, 1, stdout); return EXIT_SUCCESS; + } case CmdTargets: return print_target_list(stdout); case CmdNone: diff --git a/src/userland.cpp b/src/userland.cpp new file mode 100644 index 000000000..25b149229 --- /dev/null +++ b/src/userland.cpp @@ -0,0 +1,10 @@ +// This file is a shim for zig1. The real implementations of these are in +// src-self-hosted/stage1.zig + +#include "userland.h" + +void stage2_translate_c(void) {} +void stage2_zen(const char **ptr, size_t *len) { + *ptr = nullptr; + *len = 0; +} diff --git a/src/userland.h b/src/userland.h new file mode 100644 index 000000000..92557ef99 --- /dev/null +++ b/src/userland.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_USERLAND_H +#define ZIG_USERLAND_H + +#include + +#ifdef __cplusplus +#define ZIG_USERLAND_EXTERN_C extern "C" +#else +#define ZIG_USERLAND_EXTERN_C +#endif + +ZIG_USERLAND_EXTERN_C void stage2_translate_c(void); + +ZIG_USERLAND_EXTERN_C void stage2_zen(const char **ptr, size_t *len); + +#endif diff --git a/std/build.zig b/std/build.zig index 2bd4a9b08..4d6c91543 100644 --- a/std/build.zig +++ b/std/build.zig @@ -50,6 +50,8 @@ pub const Builder = struct { build_root: []const u8, cache_root: []const u8, release_mode: ?builtin.Mode, + override_std_dir: ?[]const u8, + override_lib_dir: ?[]const u8, pub const CStd = enum { C89, @@ -133,6 +135,8 @@ pub const Builder = struct { }, .have_install_step = false, .release_mode = null, + .override_std_dir = null, + .override_lib_dir = null, }; self.detectNativeSystemPaths(); self.default_step = self.step("default", "Build the project"); @@ -939,6 +943,7 @@ pub const LibExeObjStep = struct { disable_gen_h: bool, c_std: Builder.CStd, override_std_dir: ?[]const u8, + override_lib_dir: ?[]const u8, main_pkg_path: ?[]const u8, exec_cmd_args: ?[]const ?[]const u8, name_prefix: []const u8, @@ -1039,6 +1044,7 @@ pub const LibExeObjStep = struct { .c_std = Builder.CStd.C99, .system_linker_hack = false, .override_std_dir = null, + .override_lib_dir = null, .main_pkg_path = null, .exec_cmd_args = null, .name_prefix = "", @@ -1528,6 +1534,17 @@ pub const LibExeObjStep = struct { if (self.override_std_dir) |dir| { try zig_args.append("--override-std-dir"); try zig_args.append(builder.pathFromRoot(dir)); + } else if (self.builder.override_std_dir) |dir| { + try zig_args.append("--override-std-dir"); + try zig_args.append(builder.pathFromRoot(dir)); + } + + if (self.override_lib_dir) |dir| { + try zig_args.append("--override-lib-dir"); + try zig_args.append(builder.pathFromRoot(dir)); + } else if (self.builder.override_lib_dir) |dir| { + try zig_args.append("--override-lib-dir"); + try zig_args.append(builder.pathFromRoot(dir)); } if (self.main_pkg_path) |dir| { diff --git a/std/special/build_runner.zig b/std/special/build_runner.zig index 56cfe3bcb..dfc383857 100644 --- a/std/special/build_runner.zig +++ b/std/special/build_runner.zig @@ -94,6 +94,16 @@ pub fn main() !void { return usageAndErr(&builder, false, try stderr_stream); }); builder.addSearchPrefix(search_prefix); + } else if (mem.eql(u8, arg, "--override-std-dir")) { + builder.override_std_dir = try unwrapArg(arg_it.next(allocator) orelse { + warn("Expected argument after --override-std-dir\n\n"); + return usageAndErr(&builder, false, try stderr_stream); + }); + } else if (mem.eql(u8, arg, "--override-lib-dir")) { + builder.override_lib_dir = try unwrapArg(arg_it.next(allocator) orelse { + warn("Expected argument after --override-lib-dir\n\n"); + return usageAndErr(&builder, false, try stderr_stream); + }); } else if (mem.eql(u8, arg, "--verbose-tokenize")) { builder.verbose_tokenize = true; } else if (mem.eql(u8, arg, "--verbose-ast")) { @@ -187,15 +197,17 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void { try out_stream.write( \\ \\Advanced Options: - \\ --build-file [file] Override path to build.zig - \\ --cache-dir [path] Override path to zig cache directory - \\ --verbose-tokenize Enable compiler debug output for tokenization - \\ --verbose-ast Enable compiler debug output for parsing into an AST - \\ --verbose-link Enable compiler debug output for linking - \\ --verbose-ir Enable compiler debug output for Zig IR - \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR - \\ --verbose-cimport Enable compiler debug output for C imports - \\ --verbose-cc Enable compiler debug output for C compilation + \\ --build-file [file] Override path to build.zig + \\ --cache-dir [path] Override path to zig cache directory + \\ --override-std-dir [arg] Override path to Zig standard library + \\ --override-lib-dir [arg] Override path to Zig lib directory + \\ --verbose-tokenize Enable compiler debug output for tokenization + \\ --verbose-ast Enable compiler debug output for parsing into an AST + \\ --verbose-link Enable compiler debug output for linking + \\ --verbose-ir Enable compiler debug output for Zig IR + \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR + \\ --verbose-cimport Enable compiler debug output for C imports + \\ --verbose-cc Enable compiler debug output for C compilation \\ ); }