From 97c9f61db47ddba43a0db562e13773514875fa6a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 5 Sep 2018 00:34:46 -0400 Subject: start creating a hash of input parameters See #1416 --- src/codegen.hpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/codegen.hpp') diff --git a/src/codegen.hpp b/src/codegen.hpp index 6297c4611b..55b38a0050 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -16,7 +16,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, Buf *zig_lib_dir); -void codegen_destroy(CodeGen *codegen); 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); -- cgit v1.2.3 From fbe5737c84c783cd31e6e2d595fc47eb782c5e3c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 10 Sep 2018 09:46:15 -0400 Subject: stage1: always optimize blake and softfloat even in debug mode --- CMakeLists.txt | 14 +++++++-- src/all_types.hpp | 4 +++ src/cache_hash.cpp | 4 +++ src/cache_hash.hpp | 3 +- src/codegen.cpp | 91 +++++++++++++++++++++++++++++++++--------------------- src/codegen.hpp | 2 +- src/link.cpp | 2 +- src/main.cpp | 21 ++++++++++--- 8 files changed, 94 insertions(+), 47 deletions(-) (limited to 'src/codegen.hpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index 615128159f..8339be71b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -390,7 +390,7 @@ if(MSVC) ) else() set_target_properties(embedded_softfloat PROPERTIES - COMPILE_FLAGS "-std=c99" + COMPILE_FLAGS "-std=c99 -O3" ) endif() target_include_directories(embedded_softfloat PUBLIC @@ -407,10 +407,9 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/ast_render.cpp" "${CMAKE_SOURCE_DIR}/src/bigfloat.cpp" "${CMAKE_SOURCE_DIR}/src/bigint.cpp" - "${CMAKE_SOURCE_DIR}/src/blake2b.cpp" "${CMAKE_SOURCE_DIR}/src/buffer.cpp" - "${CMAKE_SOURCE_DIR}/src/cache_hash.cpp" "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp" + "${CMAKE_SOURCE_DIR}/src/cache_hash.cpp" "${CMAKE_SOURCE_DIR}/src/codegen.cpp" "${CMAKE_SOURCE_DIR}/src/errmsg.cpp" "${CMAKE_SOURCE_DIR}/src/error.cpp" @@ -426,6 +425,9 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/util.cpp" "${CMAKE_SOURCE_DIR}/src/translate_c.cpp" ) +set(ZIG_SOURCES_O3 + "${CMAKE_SOURCE_DIR}/src/blake2b.cpp" +) set(ZIG_CPP_SOURCES "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp" @@ -813,6 +815,11 @@ set_target_properties(zig_cpp PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} ) +add_library(zig_O3 STATIC ${ZIG_SOURCES_O3}) +set_target_properties(zig_O3 PROPERTIES + COMPILE_FLAGS "${EXE_CFLAGS} -O3" +) + add_executable(zig ${ZIG_SOURCES}) set_target_properties(zig PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} @@ -821,6 +828,7 @@ set_target_properties(zig PROPERTIES target_link_libraries(zig LINK_PUBLIC zig_cpp + zig_O3 ${SOFTFLOAT_LIBRARIES} ${CLANG_LIBRARIES} ${LLD_LIBRARIES} diff --git a/src/all_types.hpp b/src/all_types.hpp index 0b0de58791..2dfbcaaa62 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -10,6 +10,7 @@ #include "list.hpp" #include "buffer.hpp" +#include "cache_hash.hpp" #include "zig_llvm.h" #include "hash_map.hpp" #include "errmsg.hpp" @@ -1613,7 +1614,10 @@ struct CodeGen { ZigType *entry_promise; } builtin_types; + CacheHash cache_hash; + //////////////////////////// Participates in Input Parameter Cache Hash + Buf *compiler_id; ZigList link_libs_list; // add -framework [name] args to linker ZigList darwin_frameworks; diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp index ff530ca65c..a0c43bc810 100644 --- a/src/cache_hash.cpp +++ b/src/cache_hash.cpp @@ -6,6 +6,7 @@ */ #include "cache_hash.hpp" +#include "all_types.hpp" #include "buffer.hpp" #include "os.hpp" @@ -219,6 +220,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { buf_append_str(ch->manifest_file_path, ".txt"); + if ((err = os_make_path(ch->manifest_dir))) + return err; + if ((err = os_file_open_lock_rw(ch->manifest_file_path, &ch->manifest_file))) return err; diff --git a/src/cache_hash.hpp b/src/cache_hash.hpp index 77b22a1e41..3c2d77abc0 100644 --- a/src/cache_hash.hpp +++ b/src/cache_hash.hpp @@ -8,10 +8,11 @@ #ifndef ZIG_CACHE_HASH_HPP #define ZIG_CACHE_HASH_HPP -#include "all_types.hpp" #include "blake2.h" #include "os.hpp" +struct LinkLib; + struct CacheHashFile { Buf *path; OsTimeStamp mtime; diff --git a/src/codegen.cpp b/src/codegen.cpp index 6c5648f626..a18b26bb18 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -88,12 +88,13 @@ static const char *symbols_that_llvm_depends_on[] = { }; CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, - Buf *zig_lib_dir) + Buf *zig_lib_dir, Buf *compiler_id) { CodeGen *g = allocate(1); codegen_add_time_event(g, "Initialize"); + g->compiler_id = compiler_id; g->zig_lib_dir = zig_lib_dir; g->zig_std_dir = buf_alloc(); @@ -7675,44 +7676,62 @@ void codegen_add_time_event(CodeGen *g, const char *name) { } -//// Called before init() -//static bool build_with_cache(CodeGen *g) { -// // TODO zig exe & dynamic libraries -// // should be in main.cpp I think. only needs to happen -// // once on startup. -// -// CacheHash comp; -// cache_init(&comp); -// -// add_cache_buf(&blake, g->root_out_name); -// add_cache_buf_opt(&blake, get_resolved_root_src_path(g)); // Root source file -// add_cache_list_of_link_lib(&blake, g->link_libs_list.items, g->link_libs_list.length); -// add_cache_list_of_buf(&blake, g->darwin_frameworks.items, g->darwin_frameworks.length); -// add_cache_list_of_buf(&blake, g->rpath_list.items, g->rpath_list.length); -// add_cache_int(&blake, g->emit_file_type); -// add_cache_int(&blake, g->build_mode); -// add_cache_int(&blake, g->out_type); -// // TODO the rest of the struct CodeGen fields -// -// uint8_t bin_digest[48]; -// rc = blake2b_final(&blake, bin_digest, 48); -// assert(rc == 0); -// -// Buf b64_digest = BUF_INIT; -// buf_resize(&b64_digest, 64); -// base64_encode(buf_to_slice(&b64_digest), {bin_digest, 48}); -// -// fprintf(stderr, "input params hash: %s\n", buf_ptr(&b64_digest)); -// // TODO next look for a manifest file that has all the files from the input parameters -// // use that to construct the real hash, which looks up the output directory and another manifest file -// -// return false; -//} +// Called before init() +static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { + Error err; + + CacheHash *ch = &g->cache_hash; + cache_init(ch, manifest_dir); + + cache_buf(ch, g->compiler_id); + cache_buf(ch, g->root_out_name); + cache_file(ch, get_resolved_root_src_path(g)); // Root source file + cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length); + cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length); + cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length); + cache_int(ch, g->emit_file_type); + cache_int(ch, g->build_mode); + cache_int(ch, g->out_type); + // TODO the rest of the struct CodeGen fields + + buf_resize(digest, 0); + if ((err = cache_hit(ch, digest))) + return err; + + return ErrorNone; +} void codegen_build(CodeGen *g) { + Error err; assert(g->out_type != OutTypeUnknown); - //if (build_with_cache(g)) - // return; + + Buf app_data_dir = BUF_INIT; + if ((err = os_get_app_data_dir(&app_data_dir, "zig"))) { + fprintf(stderr, "Unable to get app data dir: %s\n", err_str(err)); + exit(1); + } + Buf *stage1_dir = buf_alloc(); + os_path_join(&app_data_dir, buf_create_from_str("stage1"), stage1_dir); + + Buf *manifest_dir = buf_alloc(); + os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir); + + Buf digest = BUF_INIT; + if ((err = check_cache(g, manifest_dir, &digest))) { + fprintf(stderr, "Unable to check cache: %s\n", err_str(err)); + exit(1); + } + if (buf_len(&digest) != 0) { + Buf *artifact_dir = buf_alloc(); + os_path_join(stage1_dir, buf_create_from_str("artifact"), artifact_dir); + + Buf *this_artifact_dir = buf_alloc(); + os_path_join(artifact_dir, &digest, this_artifact_dir); + + fprintf(stderr, "copy artifacts from %s\n", buf_ptr(this_artifact_dir)); + return; + } + init(g); codegen_add_time_event(g, "Semantic Analysis"); diff --git a/src/codegen.hpp b/src/codegen.hpp index 55b38a0050..649cf06856 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -15,7 +15,7 @@ #include CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, - Buf *zig_lib_dir); + Buf *zig_lib_dir, Buf *compiler_id); 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); diff --git a/src/link.cpp b/src/link.cpp index 78ad204fe9..c0eb25bd55 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -34,7 +34,7 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) { static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) { ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode, - parent_gen->zig_lib_dir); + parent_gen->zig_lib_dir, parent_gen->compiler_id); child_gen->want_h_file = false; child_gen->verbose_tokenize = parent_gen->verbose_tokenize; diff --git a/src/main.cpp b/src/main.cpp index c385a1c88e..1520ae7d67 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -274,8 +274,6 @@ static Error get_compiler_id(Buf **result) { Buf *manifest_dir = buf_alloc(); os_path_join(stage1_dir, buf_create_from_str("exe"), manifest_dir); - if ((err = os_make_path(manifest_dir))) - return err; CacheHash cache_hash; CacheHash *ch = &cache_hash; cache_init(ch, manifest_dir); @@ -432,8 +430,14 @@ int main(int argc, char **argv) { Buf *build_runner_path = buf_alloc(); os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path); + Buf *compiler_id; + if ((err = get_compiler_id(&compiler_id))) { + fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err)); + return EXIT_FAILURE; + } - CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf); + CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf, + compiler_id); codegen_set_out_name(g, buf_create_from_str("build")); Buf *build_file_buf = buf_create_from_str(build_file); @@ -796,7 +800,7 @@ int main(int argc, char **argv) { switch (cmd) { case CmdBuiltin: { Buf *zig_lib_dir_buf = resolve_zig_lib_dir(); - CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, zig_lib_dir_buf); + CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, zig_lib_dir_buf, nullptr); Buf *builtin_source = codegen_generate_builtin_source(g); if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) { fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout))); @@ -871,7 +875,14 @@ int main(int argc, char **argv) { Buf *zig_lib_dir_buf = resolve_zig_lib_dir(); - CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, zig_lib_dir_buf); + Buf *compiler_id; + if ((err = get_compiler_id(&compiler_id))) { + fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err)); + return EXIT_FAILURE; + } + + CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, zig_lib_dir_buf, + compiler_id); 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); -- cgit v1.2.3 From 32be6e9b2a9e6de501aadbe271c554a4682a10f8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 10 Sep 2018 13:46:23 -0400 Subject: caching is working * add almost all the input parameter state to the hash - missing items are the detected MSVC installation on Windows and detected libc installation on POSIX - also missing are C files and .h files that libclang finds * artifacts are created in global cache directory instead of zig-cache. - exception: builtin.zig is still in zig-cache * zig run uses the new cache correctly * zig run uses execv on posix systems --- src/all_types.hpp | 265 ++++++++++++++++++++++++++--------------------------- src/cache_hash.cpp | 70 ++++++++++++-- src/cache_hash.hpp | 27 ++++-- src/codegen.cpp | 197 +++++++++++++++++++++++++++------------ src/codegen.hpp | 4 +- src/error.cpp | 1 + src/error.hpp | 1 + src/ir.cpp | 11 +-- src/link.cpp | 74 ++++----------- src/link.hpp | 17 ---- src/main.cpp | 64 ++++++------- src/os.cpp | 54 ++++------- src/os.hpp | 3 +- 13 files changed, 418 insertions(+), 370 deletions(-) delete mode 100644 src/link.hpp (limited to 'src/codegen.hpp') diff --git a/src/all_types.hpp b/src/all_types.hpp index 2dfbcaaa62..6d11244a25 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1554,6 +1554,40 @@ struct CodeGen { ZigLLVMDICompileUnit *compile_unit; ZigLLVMDIFile *compile_unit_file; LinkLib *libc_link_lib; + LLVMTargetDataRef target_data_ref; + LLVMTargetMachineRef target_machine; + ZigLLVMDIFile *dummy_di_file; + LLVMValueRef cur_ret_ptr; + LLVMValueRef cur_fn_val; + LLVMValueRef cur_err_ret_trace_val_arg; + LLVMValueRef cur_err_ret_trace_val_stack; + LLVMValueRef memcpy_fn_val; + LLVMValueRef memset_fn_val; + LLVMValueRef trap_fn_val; + LLVMValueRef return_address_fn_val; + LLVMValueRef frame_address_fn_val; + LLVMValueRef coro_destroy_fn_val; + LLVMValueRef coro_id_fn_val; + LLVMValueRef coro_alloc_fn_val; + LLVMValueRef coro_size_fn_val; + LLVMValueRef coro_begin_fn_val; + LLVMValueRef coro_suspend_fn_val; + LLVMValueRef coro_end_fn_val; + LLVMValueRef coro_free_fn_val; + LLVMValueRef coro_resume_fn_val; + LLVMValueRef coro_save_fn_val; + LLVMValueRef coro_promise_fn_val; + LLVMValueRef coro_alloc_helper_fn_val; + LLVMValueRef coro_frame_fn_val; + LLVMValueRef merge_err_ret_traces_fn_val; + LLVMValueRef add_error_return_trace_addr_fn_val; + LLVMValueRef stacksave_fn_val; + LLVMValueRef stackrestore_fn_val; + LLVMValueRef write_register_fn_val; + LLVMValueRef sp_md_node; + LLVMValueRef err_name_table; + LLVMValueRef safety_crash_err_fn; + LLVMValueRef return_err_fn; // reminder: hash tables must be initialized before use HashMap import_table; @@ -1576,8 +1610,23 @@ struct CodeGen { size_t resolve_queue_index; ZigList use_queue; size_t use_queue_index; + ZigList timing_events; + ZigList error_di_types; + ZigList tld_ref_source_node_stack; + ZigList inline_fns; + ZigList test_fns; + ZigList err_enumerators; + ZigList errors_by_index; + size_t largest_err_name_len; - uint32_t next_unresolved_index; + PackageTableEntry *std_package; + PackageTableEntry *panic_package; + PackageTableEntry *test_runner_package; + PackageTableEntry *compile_var_package; + ImportTableEntry *compile_var_import; + ImportTableEntry *root_import; + ImportTableEntry *bootstrap_import; + ImportTableEntry *test_runner_import; struct { ZigType *entry_bool; @@ -1613,30 +1662,45 @@ struct CodeGen { ZigType *entry_arg_tuple; ZigType *entry_promise; } builtin_types; + ZigType *align_amt_type; + ZigType *stack_trace_type; + ZigType *ptr_to_stack_trace_type; + ZigType *err_tag_type; + ZigType *test_fn_type; - CacheHash cache_hash; + Buf triple_str; + Buf global_asm; + Buf *out_h_path; + Buf cache_dir; + Buf artifact_dir; + Buf output_file_path; + Buf o_file_output_path; + Buf *wanted_output_file_path; - //////////////////////////// Participates in Input Parameter Cache Hash - Buf *compiler_id; - ZigList link_libs_list; - // add -framework [name] args to linker - ZigList darwin_frameworks; - // add -rpath [name] args to linker - ZigList rpath_list; + IrInstruction *invalid_instruction; - EmitFileType emit_file_type; - BuildMode build_mode; - OutType out_type; + ConstExprValue const_void_val; + ConstExprValue panic_msg_vals[PanicMsgIdCount]; + // The function definitions this module includes. + ZigList fn_defs; + size_t fn_defs_index; + ZigList global_vars; - //////////////////////////// Unsorted + ZigFn *cur_fn; + ZigFn *main_fn; + ZigFn *panic_fn; + AstNode *root_export_decl; - ZigTarget zig_target; - LLVMTargetDataRef target_data_ref; + CacheHash cache_hash; + ErrColor err_color; + uint32_t next_unresolved_index; unsigned pointer_size_bytes; + uint32_t target_os_index; + uint32_t target_arch_index; + uint32_t target_environ_index; + uint32_t target_oformat_index; bool is_big_endian; - bool is_static; - bool strip_debug_symbols; bool want_h_file; bool have_pub_main; bool have_c_main; @@ -1644,148 +1708,75 @@ struct CodeGen { bool have_winmain_crt_startup; bool have_dllmain_crt_startup; bool have_pub_panic; - Buf *libc_lib_dir; - Buf *libc_static_lib_dir; - Buf *libc_include_dir; - Buf *msvc_lib_dir; - Buf *kernel32_lib_dir; - Buf *zig_lib_dir; - Buf *zig_std_dir; - Buf *zig_c_headers_dir; - Buf *zig_std_special_dir; - Buf *dynamic_linker; - Buf *ar_path; - ZigWindowsSDK *win_sdk; - Buf triple_str; - bool is_test_build; bool have_err_ret_tracing; - uint32_t target_os_index; - uint32_t target_arch_index; - uint32_t target_environ_index; - uint32_t target_oformat_index; - LLVMTargetMachineRef target_machine; - ZigLLVMDIFile *dummy_di_file; - bool is_native_target; - PackageTableEntry *root_package; // participates in cache hash - PackageTableEntry *std_package; - PackageTableEntry *panic_package; - PackageTableEntry *test_runner_package; - PackageTableEntry *compile_var_package; - ImportTableEntry *compile_var_import; - Buf *root_out_name; // participates in cache hash - bool windows_subsystem_windows; - bool windows_subsystem_console; - Buf *mmacosx_version_min; - Buf *mios_version_min; - bool linker_rdynamic; - const char *linker_script; - - // The function definitions this module includes. - ZigList fn_defs; - size_t fn_defs_index; - ZigList global_vars; - - ZigFn *cur_fn; - ZigFn *main_fn; - ZigFn *panic_fn; - LLVMValueRef cur_ret_ptr; - LLVMValueRef cur_fn_val; - LLVMValueRef cur_err_ret_trace_val_arg; - LLVMValueRef cur_err_ret_trace_val_stack; bool c_want_stdint; bool c_want_stdbool; - AstNode *root_export_decl; - size_t version_major; - size_t version_minor; - size_t version_patch; bool verbose_tokenize; bool verbose_ast; bool verbose_link; bool verbose_ir; bool verbose_llvm_ir; bool verbose_cimport; - ErrColor err_color; - ImportTableEntry *root_import; - ImportTableEntry *bootstrap_import; - ImportTableEntry *test_runner_import; - LLVMValueRef memcpy_fn_val; - LLVMValueRef memset_fn_val; - LLVMValueRef trap_fn_val; - LLVMValueRef return_address_fn_val; - LLVMValueRef frame_address_fn_val; - LLVMValueRef coro_destroy_fn_val; - LLVMValueRef coro_id_fn_val; - LLVMValueRef coro_alloc_fn_val; - LLVMValueRef coro_size_fn_val; - LLVMValueRef coro_begin_fn_val; - LLVMValueRef coro_suspend_fn_val; - LLVMValueRef coro_end_fn_val; - LLVMValueRef coro_free_fn_val; - LLVMValueRef coro_resume_fn_val; - LLVMValueRef coro_save_fn_val; - LLVMValueRef coro_promise_fn_val; - LLVMValueRef coro_alloc_helper_fn_val; - LLVMValueRef coro_frame_fn_val; - LLVMValueRef merge_err_ret_traces_fn_val; - LLVMValueRef add_error_return_trace_addr_fn_val; - LLVMValueRef stacksave_fn_val; - LLVMValueRef stackrestore_fn_val; - LLVMValueRef write_register_fn_val; bool error_during_imports; + bool generate_error_name_table; - LLVMValueRef sp_md_node; - - const char **clang_argv; - size_t clang_argv_len; + //////////////////////////// Participates in Input Parameter Cache Hash + ZigList link_libs_list; + // add -framework [name] args to linker + ZigList darwin_frameworks; + // add -rpath [name] args to linker + ZigList rpath_list; + ZigList forbidden_libs; + ZigList link_objects; + ZigList assembly_files; ZigList lib_dirs; - const char **llvm_argv; - size_t llvm_argv_len; - - ZigList test_fns; - ZigType *test_fn_type; + Buf *compiler_id; + size_t version_major; + size_t version_minor; + size_t version_patch; + const char *linker_script; + EmitFileType emit_file_type; + BuildMode build_mode; + OutType out_type; + ZigTarget zig_target; + bool is_static; + bool strip_debug_symbols; + bool is_test_build; + bool is_native_target; + bool windows_subsystem_windows; + bool windows_subsystem_console; + bool linker_rdynamic; + bool no_rosegment_workaround; bool each_lib_rpath; - ZigType *err_tag_type; - ZigList err_enumerators; - ZigList errors_by_index; - bool generate_error_name_table; - LLVMValueRef err_name_table; - size_t largest_err_name_len; - LLVMValueRef safety_crash_err_fn; - - LLVMValueRef return_err_fn; - - IrInstruction *invalid_instruction; - ConstExprValue const_void_val; - - ConstExprValue panic_msg_vals[PanicMsgIdCount]; - - Buf global_asm; - ZigList link_objects; - ZigList assembly_files; - + Buf *mmacosx_version_min; + Buf *mios_version_min; + Buf *root_out_name; Buf *test_filter; Buf *test_name_prefix; + PackageTableEntry *root_package; - ZigList timing_events; - - Buf cache_dir; - Buf *out_h_path; - - ZigList inline_fns; - ZigList tld_ref_source_node_stack; - - ZigType *align_amt_type; - ZigType *stack_trace_type; - ZigType *ptr_to_stack_trace_type; + const char **llvm_argv; + size_t llvm_argv_len; - ZigList error_di_types; + const char **clang_argv; + size_t clang_argv_len; - ZigList forbidden_libs; + //////////////////////////// Unsorted - bool no_rosegment_workaround; + Buf *libc_lib_dir; + Buf *libc_static_lib_dir; + Buf *libc_include_dir; + Buf *msvc_lib_dir; + Buf *kernel32_lib_dir; + Buf *zig_lib_dir; + Buf *zig_std_dir; + Buf *zig_c_headers_dir; + Buf *zig_std_special_dir; + Buf *dynamic_linker; + ZigWindowsSDK *win_sdk; }; enum VarLinkage { diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp index a0c43bc810..b6aebdac67 100644 --- a/src/cache_hash.cpp +++ b/src/cache_hash.cpp @@ -37,6 +37,20 @@ void cache_int(CacheHash *ch, int x) { blake2b_update(&ch->blake, buf, sizeof(int) + 1); } +void cache_usize(CacheHash *ch, size_t x) { + assert(ch->manifest_file_path == nullptr); + // + 1 to include the null byte + uint8_t buf[sizeof(size_t) + 1]; + memcpy(buf, &x, sizeof(size_t)); + buf[sizeof(size_t)] = 0; + blake2b_update(&ch->blake, buf, sizeof(size_t) + 1); +} + +void cache_bool(CacheHash *ch, bool x) { + assert(ch->manifest_file_path == nullptr); + blake2b_update(&ch->blake, &x, 1); +} + void cache_buf(CacheHash *ch, Buf *buf) { assert(ch->manifest_file_path == nullptr); assert(buf != nullptr); @@ -74,6 +88,26 @@ void cache_list_of_buf(CacheHash *ch, Buf **ptr, size_t len) { cache_str(ch, ""); } +void cache_list_of_file(CacheHash *ch, Buf **ptr, size_t len) { + assert(ch->manifest_file_path == nullptr); + + for (size_t i = 0; i < len; i += 1) { + Buf *buf = ptr[i]; + cache_file(ch, buf); + } + cache_str(ch, ""); +} + +void cache_list_of_str(CacheHash *ch, const char **ptr, size_t len) { + assert(ch->manifest_file_path == nullptr); + + for (size_t i = 0; i < len; i += 1) { + const char *s = ptr[i]; + cache_str(ch, s); + } + cache_str(ch, ""); +} + void cache_file(CacheHash *ch, Buf *file_path) { assert(ch->manifest_file_path == nullptr); assert(file_path != nullptr); @@ -154,9 +188,13 @@ static Error base64_decode(Slice dest, Slice source) { return ErrorNone; } -static Error hash_file(uint8_t *digest, OsFile handle) { +static Error hash_file(uint8_t *digest, OsFile handle, Buf *contents) { Error err; + if (contents) { + buf_resize(contents, 0); + } + blake2b_state blake; int rc = blake2b_init(&blake, 48); assert(rc == 0); @@ -172,10 +210,13 @@ static Error hash_file(uint8_t *digest, OsFile handle) { return ErrorNone; } blake2b_update(&blake, buf, amt); + if (contents) { + buf_append_mem(contents, (char*)buf, amt); + } } } -static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf) { +static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents) { Error err; assert(chf->path != nullptr); @@ -189,7 +230,7 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf) { return err; } - if ((err = hash_file(chf->bin_digest, this_file))) { + if ((err = hash_file(chf->bin_digest, this_file, contents))) { os_file_close(this_file); return err; } @@ -323,7 +364,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { chf->mtime = actual_mtime; uint8_t actual_digest[48]; - if ((err = hash_file(actual_digest, this_file))) { + if ((err = hash_file(actual_digest, this_file, nullptr))) { os_file_close(this_file); os_file_close(ch->manifest_file); return err; @@ -344,7 +385,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { ch->manifest_dirty = true; for (; file_i < input_file_count; file_i += 1) { CacheHashFile *chf = &ch->files.at(file_i); - if ((err = populate_file_hash(ch, chf))) { + if ((err = populate_file_hash(ch, chf, nullptr))) { os_file_close(ch->manifest_file); return err; } @@ -355,13 +396,13 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { return cache_final(ch, out_digest); } -Error cache_add_file(CacheHash *ch, Buf *path) { +Error cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents) { Error err; assert(ch->manifest_file_path != nullptr); CacheHashFile *chf = ch->files.add_one(); - chf->path = path; - if ((err = populate_file_hash(ch, chf))) { + chf->path = resolved_path; + if ((err = populate_file_hash(ch, chf, contents))) { os_file_close(ch->manifest_file); return err; } @@ -369,6 +410,12 @@ Error cache_add_file(CacheHash *ch, Buf *path) { return ErrorNone; } +Error cache_add_file(CacheHash *ch, Buf *path) { + Buf *resolved_path = buf_alloc(); + *resolved_path = os_path_resolve(&path, 1); + return cache_add_file_fetch(ch, resolved_path, nullptr); +} + static Error write_manifest_file(CacheHash *ch) { Error err; Buf contents = BUF_INIT; @@ -398,7 +445,8 @@ Error cache_final(CacheHash *ch, Buf *out_digest) { buf_ptr(ch->manifest_file_path), err_str(err)); } } - os_file_close(ch->manifest_file); + // We don't close the manifest file yet, because we want to + // keep it locked until the API user is done using it. uint8_t bin_digest[48]; int rc = blake2b_final(&ch->blake, bin_digest, 48); @@ -408,3 +456,7 @@ Error cache_final(CacheHash *ch, Buf *out_digest) { return ErrorNone; } + +void cache_release(CacheHash *ch) { + os_file_close(ch->manifest_file); +} diff --git a/src/cache_hash.hpp b/src/cache_hash.hpp index 3c2d77abc0..ede7344c75 100644 --- a/src/cache_hash.hpp +++ b/src/cache_hash.hpp @@ -17,6 +17,7 @@ struct CacheHashFile { Buf *path; OsTimeStamp mtime; uint8_t bin_digest[48]; + Buf *contents; }; struct CacheHash { @@ -34,24 +35,36 @@ void cache_init(CacheHash *ch, Buf *manifest_dir); // Next, use the hash population functions to add the initial parameters. void cache_str(CacheHash *ch, const char *ptr); void cache_int(CacheHash *ch, int x); +void cache_bool(CacheHash *ch, bool x); +void cache_usize(CacheHash *ch, size_t x); void cache_buf(CacheHash *ch, Buf *buf); void cache_buf_opt(CacheHash *ch, Buf *buf); void cache_list_of_link_lib(CacheHash *ch, LinkLib **ptr, size_t len); void cache_list_of_buf(CacheHash *ch, Buf **ptr, size_t len); +void cache_list_of_file(CacheHash *ch, Buf **ptr, size_t len); +void cache_list_of_str(CacheHash *ch, const char **ptr, size_t len); void cache_file(CacheHash *ch, Buf *path); void cache_file_opt(CacheHash *ch, Buf *path); // Then call cache_hit when you're ready to see if you can skip the next step. -// out_b64_digest will be left unchanged if it was a cache miss +// out_b64_digest will be left unchanged if it was a cache miss. +// If you got a cache hit, the next step is cache_release. +// From this point on, there is a lock on the input params. Release +// the lock with cache_release. Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest); -// If you got a cache hit, the flow is done. No more functions to call. -// Next call this function for every file that is depended on. +// If you did not get a cache hit, call this function for every file +// that is depended on, and then finish with cache_final. Error ATTRIBUTE_MUST_USE cache_add_file(CacheHash *ch, Buf *path); -// If you did not get a cache hit, use the hash population functions again -// and do all the actual work. When done use cache_final to save the cache -// for next time. -Error ATTRIBUTE_MUST_USE cache_final(CacheHash *ch, Buf *out_digest); +// This variant of cache_add_file returns the file contents. +// Also the file path argument must be already resolved. +Error ATTRIBUTE_MUST_USE cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents); + +// out_b64_digest will be the same thing that cache_hit returns if you got a cache hit +Error ATTRIBUTE_MUST_USE cache_final(CacheHash *ch, Buf *out_b64_digest); + +// Until this function is called, no one will be able to get a lock on your input params. +void cache_release(CacheHash *ch); #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index a18b26bb18..1f53bb4c9d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -13,7 +13,6 @@ #include "error.hpp" #include "hash_map.hpp" #include "ir.hpp" -#include "link.hpp" #include "os.hpp" #include "translate_c.hpp" #include "target.hpp" @@ -188,6 +187,10 @@ void codegen_set_output_h_path(CodeGen *g, Buf *h_path) { g->out_h_path = h_path; } +void codegen_set_output_path(CodeGen *g, Buf *path) { + g->wanted_output_file_path = path; +} + void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) { g->clang_argv = args; g->clang_argv_len = len; @@ -5756,8 +5759,6 @@ static void validate_inline_fns(CodeGen *g) { static void do_code_gen(CodeGen *g) { assert(!g->errors.length); - codegen_add_time_event(g, "Code Generation"); - { // create debug type for error sets assert(g->err_enumerators.length == g->errors_by_index.length); @@ -6068,38 +6069,10 @@ static void do_code_gen(CodeGen *g) { codegen_add_time_event(g, "LLVM Emit Output"); - char *err_msg = nullptr; - Buf *o_basename = buf_create_from_buf(g->root_out_name); - - switch (g->emit_file_type) { - case EmitFileTypeBinary: - { - const char *o_ext = target_o_file_ext(&g->zig_target); - buf_append_str(o_basename, o_ext); - break; - } - case EmitFileTypeAssembly: - { - const char *asm_ext = target_asm_file_ext(&g->zig_target); - buf_append_str(o_basename, asm_ext); - break; - } - case EmitFileTypeLLVMIr: - { - const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target); - buf_append_str(o_basename, llvm_ir_ext); - break; - } - default: - zig_unreachable(); - } - - Buf *output_path = buf_alloc(); - os_path_join(&g->cache_dir, o_basename, output_path); - ensure_cache_dir(g); - bool is_small = g->build_mode == BuildModeSmallRelease; + Buf *output_path = &g->o_file_output_path; + char *err_msg = nullptr; switch (g->emit_file_type) { case EmitFileTypeBinary: if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), @@ -6118,7 +6091,6 @@ static void do_code_gen(CodeGen *g) { zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg); } validate_inline_fns(g); - g->link_objects.append(output_path); break; case EmitFileTypeLLVMIr: @@ -6128,7 +6100,6 @@ static void do_code_gen(CodeGen *g) { zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg); } validate_inline_fns(g); - g->link_objects.append(output_path); break; default: @@ -7035,8 +7006,8 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package Buf *resolved_path = buf_alloc(); *resolved_path = os_path_resolve(resolve_paths, 1); Buf *import_code = buf_alloc(); - int err; - if ((err = os_fetch_file_path(resolved_path, import_code, false))) { + Error err; + if ((err = cache_add_file_fetch(&g->cache_hash, resolved_path, import_code))) { zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err)); } @@ -7131,6 +7102,8 @@ static void gen_root_source(CodeGen *g) { Buf *source_code = buf_alloc(); int err; + // No need for using the caching system for this file fetch because it is handled + // separately. if ((err = os_fetch_file_path(resolved_path, source_code, true))) { fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(resolved_path), err_str(err)); exit(1); @@ -7197,6 +7170,8 @@ static void gen_global_asm(CodeGen *g) { int err; for (size_t i = 0; i < g->assembly_files.length; i += 1) { Buf *asm_file = g->assembly_files.at(i); + // No need to use the caching system for these fetches because they + // are handled separately. if ((err = os_fetch_file_path(asm_file, &contents, false))) { zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err)); } @@ -7460,14 +7435,9 @@ static Buf *preprocessor_mangle(Buf *src) { } static void gen_h_file(CodeGen *g) { - if (!g->want_h_file) - return; - GenH gen_h_data = {0}; GenH *gen_h = &gen_h_data; - codegen_add_time_event(g, "Generate .h"); - assert(!g->is_test_build); if (!g->out_h_path) { @@ -7675,6 +7645,24 @@ void codegen_add_time_event(CodeGen *g, const char *name) { g->timing_events.append({os_get_time(), name}); } +static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) { + if (buf_len(&pkg->root_src_path) == 0) + return; + + Buf *rel_full_path = buf_alloc(); + os_path_join(&pkg->root_src_dir, &pkg->root_src_path, rel_full_path); + cache_file(ch, rel_full_path); + + auto it = pkg->package_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + cache_buf(ch, entry->key); + add_cache_pkg(g, ch, entry->value); + } +} // Called before init() static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { @@ -7683,16 +7671,46 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { CacheHash *ch = &g->cache_hash; cache_init(ch, manifest_dir); + add_cache_pkg(g, ch, g->root_package); + if (g->linker_script != nullptr) { + cache_file(ch, buf_create_from_str(g->linker_script)); + } cache_buf(ch, g->compiler_id); cache_buf(ch, g->root_out_name); - cache_file(ch, get_resolved_root_src_path(g)); // Root source file cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length); cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length); cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length); + cache_list_of_buf(ch, g->forbidden_libs.items, g->forbidden_libs.length); + cache_list_of_file(ch, g->link_objects.items, g->link_objects.length); + cache_list_of_file(ch, g->assembly_files.items, g->assembly_files.length); cache_int(ch, g->emit_file_type); cache_int(ch, g->build_mode); cache_int(ch, g->out_type); - // TODO the rest of the struct CodeGen fields + cache_int(ch, g->zig_target.arch.arch); + cache_int(ch, g->zig_target.arch.sub_arch); + cache_int(ch, g->zig_target.vendor); + cache_int(ch, g->zig_target.os); + cache_int(ch, g->zig_target.env_type); + cache_int(ch, g->zig_target.oformat); + cache_bool(ch, g->is_static); + cache_bool(ch, g->strip_debug_symbols); + cache_bool(ch, g->is_test_build); + cache_bool(ch, g->is_native_target); + cache_bool(ch, g->windows_subsystem_windows); + cache_bool(ch, g->windows_subsystem_console); + cache_bool(ch, g->linker_rdynamic); + cache_bool(ch, g->no_rosegment_workaround); + cache_bool(ch, g->each_lib_rpath); + cache_buf_opt(ch, g->mmacosx_version_min); + cache_buf_opt(ch, g->mios_version_min); + cache_usize(ch, g->version_major); + cache_usize(ch, g->version_minor); + cache_usize(ch, g->version_patch); + cache_buf_opt(ch, g->test_filter); + cache_buf_opt(ch, g->test_name_prefix); + cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len); + cache_list_of_str(ch, g->clang_argv, g->clang_argv_len); + cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length); buf_resize(digest, 0); if ((err = cache_hit(ch, digest))) @@ -7701,10 +7719,53 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { return ErrorNone; } -void codegen_build(CodeGen *g) { +static void resolve_out_paths(CodeGen *g) { + Buf *o_basename = buf_create_from_buf(g->root_out_name); + + switch (g->emit_file_type) { + case EmitFileTypeBinary: + { + const char *o_ext = target_o_file_ext(&g->zig_target); + buf_append_str(o_basename, o_ext); + break; + } + case EmitFileTypeAssembly: + { + const char *asm_ext = target_asm_file_ext(&g->zig_target); + buf_append_str(o_basename, asm_ext); + break; + } + case EmitFileTypeLLVMIr: + { + const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target); + buf_append_str(o_basename, llvm_ir_ext); + break; + } + default: + zig_unreachable(); + } + + os_path_join(&g->artifact_dir, o_basename, &g->o_file_output_path); + + if (g->out_type == OutTypeObj) { + buf_init_from_buf(&g->output_file_path, &g->o_file_output_path); + } else if (g->out_type == OutTypeExe) { + assert(g->root_out_name); + + Buf basename = BUF_INIT; + buf_init_from_buf(&basename, g->root_out_name); + buf_append_str(&basename, target_exe_file_ext(&g->zig_target)); + os_path_join(&g->artifact_dir, &basename, &g->output_file_path); + } +} + + +void codegen_build_and_link(CodeGen *g) { Error err; assert(g->out_type != OutTypeUnknown); + codegen_add_time_event(g, "Check Cache"); + Buf app_data_dir = BUF_INIT; if ((err = os_get_app_data_dir(&app_data_dir, "zig"))) { fprintf(stderr, "Unable to get app data dir: %s\n", err_str(err)); @@ -7721,25 +7782,45 @@ void codegen_build(CodeGen *g) { fprintf(stderr, "Unable to check cache: %s\n", err_str(err)); exit(1); } + + Buf *artifact_dir = buf_alloc(); + os_path_join(stage1_dir, buf_create_from_str("artifact"), artifact_dir); + if (buf_len(&digest) != 0) { - Buf *artifact_dir = buf_alloc(); - os_path_join(stage1_dir, buf_create_from_str("artifact"), artifact_dir); + os_path_join(artifact_dir, &digest, &g->artifact_dir); + resolve_out_paths(g); + } else { + init(g); - Buf *this_artifact_dir = buf_alloc(); - os_path_join(artifact_dir, &digest, this_artifact_dir); + codegen_add_time_event(g, "Semantic Analysis"); - fprintf(stderr, "copy artifacts from %s\n", buf_ptr(this_artifact_dir)); - return; - } + gen_global_asm(g); + gen_root_source(g); - init(g); + if ((err = cache_final(&g->cache_hash, &digest))) { + fprintf(stderr, "Unable to finalize cache hash: %s\n", err_str(err)); + exit(1); + } + os_path_join(artifact_dir, &digest, &g->artifact_dir); + if ((err = os_make_path(&g->artifact_dir))) { + fprintf(stderr, "Unable to create artifact directory: %s\n", err_str(err)); + exit(1); + } + resolve_out_paths(g); - codegen_add_time_event(g, "Semantic Analysis"); + codegen_add_time_event(g, "Code Generation"); + do_code_gen(g); + if (g->want_h_file) { + codegen_add_time_event(g, "Generate .h"); + gen_h_file(g); + } + if (g->out_type != OutTypeObj) { + codegen_link(g); + } + } + // TODO hard link output_file_path to wanted_output_file_path - gen_global_asm(g); - gen_root_source(g); - do_code_gen(g); - gen_h_file(g); + codegen_add_time_event(g, "Done"); } PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path) { diff --git a/src/codegen.hpp b/src/codegen.hpp index 649cf06856..1e7fafa28a 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -48,9 +48,11 @@ void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix); void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch); void codegen_set_cache_dir(CodeGen *g, Buf cache_dir); void codegen_set_output_h_path(CodeGen *g, Buf *h_path); +void codegen_set_output_path(CodeGen *g, Buf *path); void codegen_add_time_event(CodeGen *g, const char *name); void codegen_print_timing_report(CodeGen *g, FILE *f); -void codegen_build(CodeGen *g); +void codegen_link(CodeGen *g); +void codegen_build_and_link(CodeGen *g); PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path); void codegen_add_assembly(CodeGen *g, Buf *path); diff --git a/src/error.cpp b/src/error.cpp index d9da6e6c52..d503eaa18b 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -29,6 +29,7 @@ const char *err_str(int err) { case ErrorCCompileErrors: return "C compile errors"; case ErrorEndOfFile: return "end of file"; case ErrorIsDir: return "is directory"; + case ErrorUnsupportedOperatingSystem: return "unsupported operating system"; } return "(invalid error)"; } diff --git a/src/error.hpp b/src/error.hpp index c99c6e6b12..8c1f8b9aa5 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -29,6 +29,7 @@ enum Error { ErrorCCompileErrors, ErrorEndOfFile, ErrorIsDir, + ErrorUnsupportedOperatingSystem, }; const char *err_str(int err); diff --git a/src/ir.cpp b/src/ir.cpp index 0269c29b1a..22d9a9bc49 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16232,6 +16232,8 @@ static ZigType *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUn } static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImport *import_instruction) { + Error err; + IrInstruction *name_value = import_instruction->name->other; Buf *import_target_str = ir_resolve_str(ira, name_value); if (!import_target_str) @@ -16275,8 +16277,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor return ira->codegen->builtin_types.entry_namespace; } - int err; - if ((err = os_fetch_file_path(resolved_path, import_code, true))) { + if ((err = cache_add_file_fetch(&ira->codegen->cache_hash, resolved_path, import_code))) { if (err == ErrorFileNotFound) { ir_add_error_node(ira, source_node, buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); @@ -16287,6 +16288,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor return ira->codegen->builtin_types.entry_invalid; } } + ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, resolved_path, import_code); scan_import(ira->codegen, target_import); @@ -18106,7 +18108,7 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE // load from file system into const expr Buf *file_contents = buf_alloc(); int err; - if ((err = os_fetch_file_path(&file_path, file_contents, false))) { + if ((err = cache_add_file_fetch(&ira->codegen->cache_hash, &file_path, file_contents))) { if (err == ErrorFileNotFound) { ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path))); return ira->codegen->builtin_types.entry_invalid; @@ -18116,9 +18118,6 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE } } - // TODO add dependency on the file we embedded so that we know if it changes - // we'll have to invalidate the cache - ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); init_const_str_lit(ira->codegen, out_val, file_contents); diff --git a/src/link.cpp b/src/link.cpp index c0eb25bd55..8c250fbbe1 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -5,7 +5,6 @@ * See http://opensource.org/licenses/MIT */ -#include "link.hpp" #include "os.hpp" #include "config.h" #include "codegen.hpp" @@ -13,7 +12,6 @@ struct LinkJob { CodeGen *codegen; - Buf out_file; ZigList args; bool link_in_crt; HashMap rpath_table; @@ -62,14 +60,8 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) new_link_lib->provided_explicitly = link_lib->provided_explicitly; } - codegen_build(child_gen); - const char *o_ext = target_o_file_ext(&child_gen->zig_target); - Buf *o_out_name = buf_sprintf("%s%s", oname, o_ext); - Buf *output_path = buf_alloc(); - os_path_join(&parent_gen->cache_dir, o_out_name, output_path); - codegen_link(child_gen, buf_ptr(output_path)); - - return output_path; + codegen_build_and_link(child_gen); + return &child_gen->output_file_path; } static Buf *build_o(CodeGen *parent_gen, const char *oname) { @@ -237,15 +229,15 @@ static void construct_linker_job_elf(LinkJob *lj) { } else if (shared) { lj->args.append("-shared"); - if (buf_len(&lj->out_file) == 0) { - buf_appendf(&lj->out_file, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "", + if (buf_len(&g->output_file_path) == 0) { + buf_appendf(&g->output_file_path, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch); } soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major); } lj->args.append("-o"); - lj->args.append(buf_ptr(&lj->out_file)); + lj->args.append(buf_ptr(&g->output_file_path)); if (lj->link_in_crt) { const char *crt1o; @@ -397,7 +389,7 @@ static void construct_linker_job_wasm(LinkJob *lj) { lj->args.append("--relocatable"); // So lld doesn't look for _start. lj->args.append("-o"); - lj->args.append(buf_ptr(&lj->out_file)); + lj->args.append(buf_ptr(&g->output_file_path)); // .o files for (size_t i = 0; i < g->link_objects.length; i += 1) { @@ -478,7 +470,7 @@ static void construct_linker_job_coff(LinkJob *lj) { // } //} - lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&lj->out_file)))); + lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); if (g->libc_link_lib != nullptr) { lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir)))); @@ -585,11 +577,11 @@ static void construct_linker_job_coff(LinkJob *lj) { buf_appendf(def_contents, "\n"); Buf *def_path = buf_alloc(); - os_path_join(&g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path); + os_path_join(&g->artifact_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path); os_write_file(def_path, def_contents); Buf *generated_lib_path = buf_alloc(); - os_path_join(&g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path); + os_path_join(&g->artifact_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path); gen_lib_args.resize(0); gen_lib_args.append("link"); @@ -797,8 +789,8 @@ static void construct_linker_job_macho(LinkJob *lj) { //lj->args.append("-install_name"); //lj->args.append(buf_ptr(dylib_install_name)); - if (buf_len(&lj->out_file) == 0) { - buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", + if (buf_len(&g->output_file_path) == 0) { + buf_appendf(&g->output_file_path, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch); } } @@ -832,13 +824,13 @@ static void construct_linker_job_macho(LinkJob *lj) { } lj->args.append("-o"); - lj->args.append(buf_ptr(&lj->out_file)); + lj->args.append(buf_ptr(&g->output_file_path)); for (size_t i = 0; i < g->rpath_list.length; i += 1) { Buf *rpath = g->rpath_list.at(i); add_rpath(lj, rpath); } - add_rpath(lj, &lj->out_file); + add_rpath(lj, &g->output_file_path); if (shared) { lj->args.append("-headerpad_max_install_names"); @@ -942,7 +934,8 @@ static void construct_linker_job(LinkJob *lj) { } } -void codegen_link(CodeGen *g, const char *out_file) { +void codegen_link(CodeGen *g) { + assert(g->out_type != OutTypeObj); codegen_add_time_event(g, "Build Dependencies"); LinkJob lj = {0}; @@ -953,11 +946,6 @@ void codegen_link(CodeGen *g, const char *out_file) { lj.rpath_table.init(4); lj.codegen = g; - if (out_file) { - buf_init_from_str(&lj.out_file, out_file); - } else { - buf_resize(&lj.out_file, 0); - } if (g->verbose_llvm_ir) { fprintf(stderr, "\nOptimization:\n"); @@ -966,35 +954,9 @@ void codegen_link(CodeGen *g, const char *out_file) { LLVMDumpModule(g->module); } - bool override_out_file = (buf_len(&lj.out_file) != 0); - if (!override_out_file) { - assert(g->root_out_name); - - buf_init_from_buf(&lj.out_file, g->root_out_name); - if (g->out_type == OutTypeExe) { - buf_append_str(&lj.out_file, target_exe_file_ext(&g->zig_target)); - } - } - - if (g->out_type == OutTypeObj) { - if (override_out_file) { - assert(g->link_objects.length == 1); - Buf *o_file_path = g->link_objects.at(0); - int err; - if ((err = os_rename(o_file_path, &lj.out_file))) { - zig_panic("unable to rename object file %s into final output %s: %s", buf_ptr(o_file_path), buf_ptr(&lj.out_file), err_str(err)); - } - } - return; - } - if (g->out_type == OutTypeLib && g->is_static) { - // invoke `ar` - // example: - // # static link into libfoo.a - // ar rcs libfoo.a foo1.o foo2.o - zig_panic("TODO invoke ar"); - return; + fprintf(stderr, "Zig does not yet support creating static libraries\nSee https://github.com/ziglang/zig/issues/1493\n"); + exit(1); } lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe); @@ -1017,6 +979,4 @@ void codegen_link(CodeGen *g, const char *out_file) { fprintf(stderr, "%s\n", buf_ptr(&diag)); exit(1); } - - codegen_add_time_event(g, "Done"); } diff --git a/src/link.hpp b/src/link.hpp deleted file mode 100644 index 9f978c28d9..0000000000 --- a/src/link.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2015 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#ifndef ZIG_LINK_HPP -#define ZIG_LINK_HPP - -#include "all_types.hpp" - -void codegen_link(CodeGen *g, const char *out_file); - - -#endif - diff --git a/src/main.cpp b/src/main.cpp index 1520ae7d67..ff2c061a83 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,7 +10,6 @@ #include "codegen.hpp" #include "config.h" #include "error.hpp" -#include "link.hpp" #include "os.hpp" #include "target.hpp" #include "cache_hash.hpp" @@ -385,8 +384,7 @@ int main(int argc, char **argv) { CliPkg *cur_pkg = allocate(1); BuildMode build_mode = BuildModeDebug; ZigList test_exec_args = {0}; - int comptime_args_end = 0; - int runtime_args_start = argc; + int runtime_args_start = -1; bool no_rosegment_workaround = false; if (argc >= 2 && strcmp(argv[1], "build") == 0) { @@ -454,8 +452,6 @@ int main(int argc, char **argv) { full_cache_dir = os_path_resolve(&cache_dir_buf, 1); } - Buf *path_to_build_exe = buf_alloc(); - os_path_join(&full_cache_dir, buf_create_from_str("build"), path_to_build_exe); codegen_set_cache_dir(g, full_cache_dir); args.items[1] = buf_ptr(&build_file_dirname); @@ -525,14 +521,13 @@ int main(int argc, char **argv) { PackageTableEntry *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname), buf_ptr(&build_file_basename)); g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg); - codegen_build(g); - codegen_link(g, buf_ptr(path_to_build_exe)); + codegen_build_and_link(g); Termination term; - os_spawn_process(buf_ptr(path_to_build_exe), args, &term); + os_spawn_process(buf_ptr(&g->output_file_path), args, &term); if (term.how != TerminationIdClean || term.code != 0) { fprintf(stderr, "\nBuild failed. The following command failed:\n"); - fprintf(stderr, "%s", buf_ptr(path_to_build_exe)); + fprintf(stderr, "%s", buf_ptr(&g->output_file_path)); for (size_t i = 0; i < args.length; i += 1) { fprintf(stderr, " %s", args.at(i)); } @@ -541,15 +536,11 @@ int main(int argc, char **argv) { return (term.how == TerminationIdClean) ? term.code : -1; } - for (int i = 1; i < argc; i += 1, comptime_args_end += 1) { + for (int i = 1; i < argc; i += 1) { char *arg = argv[i]; if (arg[0] == '-') { - if (strcmp(arg, "--") == 0) { - // ignore -- from both compile and runtime arg sets - runtime_args_start = i + 1; - break; - } else if (strcmp(arg, "--release-fast") == 0) { + if (strcmp(arg, "--release-fast") == 0) { build_mode = BuildModeFastRelease; } else if (strcmp(arg, "--release-safe") == 0) { build_mode = BuildModeSafeRelease; @@ -746,6 +737,10 @@ int main(int argc, char **argv) { case CmdTest: if (!in_file) { in_file = arg; + if (cmd == CmdRun) { + runtime_args_start = i + 1; + break; // rest of the args are for the program + } } else { fprintf(stderr, "Unexpected extra parameter: %s\n", arg); return usage(arg0); @@ -856,19 +851,10 @@ int main(int argc, char **argv) { Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf; Buf full_cache_dir = BUF_INIT; - Buf *run_exec_path = buf_alloc(); - if (cmd == CmdRun) { - if (buf_out_name == nullptr) { - buf_out_name = buf_create_from_str("run"); - } - - Buf *global_cache_dir = buf_alloc(); - os_get_global_cache_directory(global_cache_dir); - os_path_join(global_cache_dir, buf_out_name, run_exec_path); - full_cache_dir = os_path_resolve(&global_cache_dir, 1); - - out_file = buf_ptr(run_exec_path); - } else { + if (cmd == CmdRun && buf_out_name == nullptr) { + buf_out_name = buf_create_from_str("run"); + } + { Buf *resolve_paths = buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir); full_cache_dir = os_path_resolve(&resolve_paths, 1); } @@ -957,6 +943,8 @@ int main(int argc, char **argv) { codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix)); } + if (out_file) + codegen_set_output_path(g, buf_create_from_str(out_file)); if (out_file_h) codegen_set_output_h_path(g, buf_create_from_str(out_file_h)); @@ -976,8 +964,7 @@ int main(int argc, char **argv) { if (cmd == CmdBuild || cmd == CmdRun) { codegen_set_emit_file_type(g, emit_file_type); - codegen_build(g); - codegen_link(g, out_file); + codegen_build_and_link(g); if (timing_info) codegen_print_timing_report(g, stdout); @@ -987,8 +974,14 @@ int main(int argc, char **argv) { args.append(argv[i]); } + const char *exec_path = buf_ptr(&g->output_file_path); + args.append(nullptr); + + os_execv(exec_path, args.items); + + args.pop(); Termination term; - os_spawn_process(buf_ptr(run_exec_path), args, &term); + os_spawn_process(exec_path, args, &term); return term.code; } @@ -1005,11 +998,8 @@ int main(int argc, char **argv) { ZigTarget native; get_native_target(&native); - ZigTarget *non_null_target = target ? target : &native; - - Buf *test_exe_name = buf_sprintf("test%s", target_exe_file_ext(non_null_target)); - Buf *test_exe_path = buf_alloc(); - os_path_join(&full_cache_dir, test_exe_name, test_exe_path); + codegen_build_and_link(g); + Buf *test_exe_path = &g->output_file_path; for (size_t i = 0; i < test_exec_args.length; i += 1) { if (test_exec_args.items[i] == nullptr) { @@ -1017,8 +1007,6 @@ int main(int argc, char **argv) { } } - codegen_build(g); - codegen_link(g, buf_ptr(test_exe_path)); if (!target_can_exec(&native, target)) { fprintf(stderr, "Created %s but skipping execution because it is non-native.\n", diff --git a/src/os.cpp b/src/os.cpp index 4ee4618184..8502e72715 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -972,6 +972,22 @@ static int os_exec_process_windows(const char *exe, ZigList &args, } #endif +Error os_execv(const char *exe, const char **argv) { +#if defined(ZIG_OS_WINDOWS) + return ErrorUnsupportedOperatingSystem; +#else + execv(exe, (char *const *)argv); + switch (errno) { + case ENOMEM: + return ErrorSystemResources; + case EIO: + return ErrorFileSystem; + default: + return ErrorUnexpected; + } +#endif +} + int os_exec_process(const char *exe, ZigList &args, Termination *term, Buf *out_stderr, Buf *out_stdout) { @@ -1238,44 +1254,6 @@ int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) { #endif } -#if defined(ZIG_OS_POSIX) -int os_get_global_cache_directory(Buf *out_tmp_path) { - const char *tmp_dir = getenv("TMPDIR"); - if (!tmp_dir) { - tmp_dir = P_tmpdir; - } - - Buf *tmp_dir_buf = buf_create_from_str(tmp_dir); - Buf *cache_dirname_buf = buf_create_from_str("zig-cache"); - - buf_resize(out_tmp_path, 0); - os_path_join(tmp_dir_buf, cache_dirname_buf, out_tmp_path); - - buf_deinit(tmp_dir_buf); - buf_deinit(cache_dirname_buf); - return 0; -} -#endif - -#if defined(ZIG_OS_WINDOWS) -int os_get_global_cache_directory(Buf *out_tmp_path) { - char tmp_dir[MAX_PATH + 1]; - if (GetTempPath(MAX_PATH, tmp_dir) == 0) { - zig_panic("GetTempPath failed"); - } - - Buf *tmp_dir_buf = buf_create_from_str(tmp_dir); - Buf *cache_dirname_buf = buf_create_from_str("zig-cache"); - - buf_resize(out_tmp_path, 0); - os_path_join(tmp_dir_buf, cache_dirname_buf, out_tmp_path); - - buf_deinit(tmp_dir_buf); - buf_deinit(cache_dirname_buf); - return 0; -} -#endif - int os_delete_file(Buf *path) { if (remove(buf_ptr(path))) { return ErrorFileSystem; diff --git a/src/os.hpp b/src/os.hpp index c64eccf8d4..fc2a34326f 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -87,6 +87,7 @@ int os_init(void); void os_spawn_process(const char *exe, ZigList &args, Termination *term); int os_exec_process(const char *exe, ZigList &args, Termination *term, Buf *out_stderr, Buf *out_stdout); +Error os_execv(const char *exe, const char **argv); void os_path_dirname(Buf *full_path, Buf *out_dirname); void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename); @@ -96,8 +97,6 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path); Buf os_path_resolve(Buf **paths_ptr, size_t paths_len); bool os_path_is_absolute(Buf *path); -int os_get_global_cache_directory(Buf *out_tmp_path); - Error ATTRIBUTE_MUST_USE os_make_path(Buf *path); Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path); -- cgit v1.2.3 From 5ee5933ade09c535bd1806d91cb606f49d07acea Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 10 Sep 2018 17:30:45 -0400 Subject: stage1 caching: zig no longer uses zig-cache --- CMakeLists.txt | 1 + src/all_types.hpp | 2 - src/cache_hash.cpp | 7 ++++ src/codegen.cpp | 110 ++++++++++++++++++++++++++++++++++++----------------- src/codegen.hpp | 3 +- src/compiler.cpp | 66 ++++++++++++++++++++++++++++++++ src/compiler.hpp | 17 +++++++++ src/link.cpp | 4 +- src/main.cpp | 78 ++----------------------------------- src/os.cpp | 22 ++++++----- src/os.hpp | 6 +-- 11 files changed, 187 insertions(+), 129 deletions(-) create mode 100644 src/compiler.cpp create mode 100644 src/compiler.hpp (limited to 'src/codegen.hpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index 8339be71b9..11bb31892c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -411,6 +411,7 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp" "${CMAKE_SOURCE_DIR}/src/cache_hash.cpp" "${CMAKE_SOURCE_DIR}/src/codegen.cpp" + "${CMAKE_SOURCE_DIR}/src/compiler.cpp" "${CMAKE_SOURCE_DIR}/src/errmsg.cpp" "${CMAKE_SOURCE_DIR}/src/error.cpp" "${CMAKE_SOURCE_DIR}/src/ir.cpp" diff --git a/src/all_types.hpp b/src/all_types.hpp index 6d11244a25..4a15162076 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1671,7 +1671,6 @@ struct CodeGen { Buf triple_str; Buf global_asm; Buf *out_h_path; - Buf cache_dir; Buf artifact_dir; Buf output_file_path; Buf o_file_output_path; @@ -1731,7 +1730,6 @@ struct CodeGen { ZigList assembly_files; ZigList lib_dirs; - Buf *compiler_id; size_t version_major; size_t version_minor; size_t version_patch; diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp index b6aebdac67..b302946310 100644 --- a/src/cache_hash.cpp +++ b/src/cache_hash.cpp @@ -248,6 +248,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { int rc = blake2b_final(&ch->blake, bin_digest, 48); assert(rc == 0); + if (ch->files.length == 0) { + buf_resize(out_digest, 64); + base64_encode(buf_to_slice(out_digest), {bin_digest, 48}); + return ErrorNone; + } + Buf b64_digest = BUF_INIT; buf_resize(&b64_digest, 64); base64_encode(buf_to_slice(&b64_digest), {bin_digest, 48}); @@ -458,5 +464,6 @@ Error cache_final(CacheHash *ch, Buf *out_digest) { } void cache_release(CacheHash *ch) { + assert(ch->manifest_file_path != nullptr); os_file_close(ch->manifest_file); } diff --git a/src/codegen.cpp b/src/codegen.cpp index 1f53bb4c9d..578fb314a8 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8,6 +8,7 @@ #include "analyze.hpp" #include "ast_render.hpp" #include "codegen.hpp" +#include "compiler.hpp" #include "config.h" #include "errmsg.hpp" #include "error.hpp" @@ -87,13 +88,12 @@ static const char *symbols_that_llvm_depends_on[] = { }; CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, - Buf *zig_lib_dir, Buf *compiler_id) + Buf *zig_lib_dir) { CodeGen *g = allocate(1); codegen_add_time_event(g, "Initialize"); - g->compiler_id = compiler_id; g->zig_lib_dir = zig_lib_dir; g->zig_std_dir = buf_alloc(); @@ -243,10 +243,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) { g->root_out_name = out_name; } -void codegen_set_cache_dir(CodeGen *g, Buf cache_dir) { - g->cache_dir = cache_dir; -} - void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) { g->libc_lib_dir = libc_lib_dir; } @@ -5728,13 +5724,6 @@ static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *na return result; } -static void ensure_cache_dir(CodeGen *g) { - int err; - if ((err = os_make_path(&g->cache_dir))) { - zig_panic("unable to make cache dir: %s", err_str(err)); - } -} - static void report_errors_and_maybe_exit(CodeGen *g) { if (g->errors.length != 0) { for (size_t i = 0; i < g->errors.length; i += 1) { @@ -6824,36 +6813,84 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { return contents; } -static void define_builtin_compile_vars(CodeGen *g) { +static Error define_builtin_compile_vars(CodeGen *g) { if (g->std_package == nullptr) - return; + return ErrorNone; + + Error err; + + Buf *manifest_dir = buf_alloc(); + os_path_join(get_stage1_cache_path(), buf_create_from_str("builtin"), manifest_dir); + + CacheHash cache_hash; + cache_init(&cache_hash, manifest_dir); + + Buf *compiler_id; + if ((err = get_compiler_id(&compiler_id))) + return err; + + // Only a few things affect builtin.zig + cache_buf(&cache_hash, compiler_id); + cache_int(&cache_hash, g->build_mode); + cache_bool(&cache_hash, g->is_test_build); + cache_int(&cache_hash, g->zig_target.arch.arch); + cache_int(&cache_hash, g->zig_target.arch.sub_arch); + cache_int(&cache_hash, g->zig_target.vendor); + cache_int(&cache_hash, g->zig_target.os); + cache_int(&cache_hash, g->zig_target.env_type); + cache_int(&cache_hash, g->zig_target.oformat); + cache_bool(&cache_hash, g->have_err_ret_tracing); + cache_bool(&cache_hash, g->libc_link_lib != nullptr); + + Buf digest = BUF_INIT; + buf_resize(&digest, 0); + if ((err = cache_hit(&cache_hash, &digest))) + return err; + + // We should always get a cache hit because there are no + // files in the input hash. + assert(buf_len(&digest) != 0); + + Buf *this_dir = buf_alloc(); + os_path_join(manifest_dir, &digest, this_dir); + + if ((err = os_make_path(this_dir))) + return err; const char *builtin_zig_basename = "builtin.zig"; Buf *builtin_zig_path = buf_alloc(); - os_path_join(&g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path); - - Buf *contents = codegen_generate_builtin_source(g); - ensure_cache_dir(g); - os_write_file(builtin_zig_path, contents); + os_path_join(this_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path); - Buf *resolved_path = buf_alloc(); - Buf *resolve_paths[] = {builtin_zig_path}; - *resolved_path = os_path_resolve(resolve_paths, 1); + bool hit; + if ((err = os_file_exists(builtin_zig_path, &hit))) + return err; + Buf *contents; + if (hit) { + contents = buf_alloc(); + if ((err = os_fetch_file_path(builtin_zig_path, contents, false))) { + fprintf(stderr, "Unable to open '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err)); + exit(1); + } + } else { + contents = codegen_generate_builtin_source(g); + os_write_file(builtin_zig_path, contents); + } assert(g->root_package); assert(g->std_package); - g->compile_var_package = new_package(buf_ptr(&g->cache_dir), builtin_zig_basename); + g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename); 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->compile_var_import = add_source_file(g, g->compile_var_package, resolved_path, contents); + g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents); scan_import(g, g->compile_var_import); + + return ErrorNone; } static void init(CodeGen *g) { if (g->module) return; - if (g->llvm_argv_len > 0) { const char **args = allocate_nonzero(g->llvm_argv_len + 2); args[0] = "zig (LLVM option parsing)"; @@ -6960,7 +6997,11 @@ static void init(CodeGen *g) { g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease && g->build_mode != BuildModeSmallRelease; define_builtin_fns(g); - define_builtin_compile_vars(g); + Error err; + if ((err = define_builtin_compile_vars(g))) { + fprintf(stderr, "Unable to create builtin.zig: %s\n", err_str(err)); + exit(1); + } } void codegen_translate_c(CodeGen *g, Buf *full_path) { @@ -7668,6 +7709,10 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) { static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { Error err; + Buf *compiler_id; + if ((err = get_compiler_id(&compiler_id))) + return err; + CacheHash *ch = &g->cache_hash; cache_init(ch, manifest_dir); @@ -7675,7 +7720,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { if (g->linker_script != nullptr) { cache_file(ch, buf_create_from_str(g->linker_script)); } - cache_buf(ch, g->compiler_id); + cache_buf(ch, compiler_id); cache_buf(ch, g->root_out_name); cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length); cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length); @@ -7766,13 +7811,7 @@ void codegen_build_and_link(CodeGen *g) { codegen_add_time_event(g, "Check Cache"); - Buf app_data_dir = BUF_INIT; - if ((err = os_get_app_data_dir(&app_data_dir, "zig"))) { - fprintf(stderr, "Unable to get app data dir: %s\n", err_str(err)); - exit(1); - } - Buf *stage1_dir = buf_alloc(); - os_path_join(&app_data_dir, buf_create_from_str("stage1"), stage1_dir); + Buf *stage1_dir = get_stage1_cache_path(); Buf *manifest_dir = buf_alloc(); os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir); @@ -7820,6 +7859,7 @@ void codegen_build_and_link(CodeGen *g) { } // TODO hard link output_file_path to wanted_output_file_path + cache_release(&g->cache_hash); codegen_add_time_event(g, "Done"); } diff --git a/src/codegen.hpp b/src/codegen.hpp index 1e7fafa28a..203e2d2b94 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -15,7 +15,7 @@ #include CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, - Buf *zig_lib_dir, Buf *compiler_id); + Buf *zig_lib_dir); 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); @@ -46,7 +46,6 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script); void codegen_set_test_filter(CodeGen *g, Buf *filter); void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix); void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch); -void codegen_set_cache_dir(CodeGen *g, Buf cache_dir); void codegen_set_output_h_path(CodeGen *g, Buf *h_path); void codegen_set_output_path(CodeGen *g, Buf *path); void codegen_add_time_event(CodeGen *g, const char *name); diff --git a/src/compiler.cpp b/src/compiler.cpp new file mode 100644 index 0000000000..dd02b541dd --- /dev/null +++ b/src/compiler.cpp @@ -0,0 +1,66 @@ +#include "cache_hash.hpp" + +#include + +static Buf saved_compiler_id = BUF_INIT; +static Buf saved_app_data_dir = BUF_INIT; +static Buf saved_stage1_path = BUF_INIT; + +Buf *get_stage1_cache_path() { + if (saved_stage1_path.list.length != 0) { + return &saved_stage1_path; + } + Error err; + if ((err = os_get_app_data_dir(&saved_app_data_dir, "zig"))) { + fprintf(stderr, "Unable to get app data dir: %s\n", err_str(err)); + exit(1); + } + os_path_join(&saved_app_data_dir, buf_create_from_str("stage1"), &saved_stage1_path); + return &saved_stage1_path; +} + +Error get_compiler_id(Buf **result) { + if (saved_compiler_id.list.length != 0) { + *result = &saved_compiler_id; + return ErrorNone; + } + + Error err; + Buf *stage1_dir = get_stage1_cache_path(); + Buf *manifest_dir = buf_alloc(); + os_path_join(stage1_dir, buf_create_from_str("exe"), manifest_dir); + + CacheHash cache_hash; + CacheHash *ch = &cache_hash; + cache_init(ch, manifest_dir); + Buf self_exe_path = BUF_INIT; + if ((err = os_self_exe_path(&self_exe_path))) + return err; + + cache_file(ch, &self_exe_path); + + buf_resize(&saved_compiler_id, 0); + if ((err = cache_hit(ch, &saved_compiler_id))) + return err; + if (buf_len(&saved_compiler_id) != 0) { + cache_release(ch); + *result = &saved_compiler_id; + return ErrorNone; + } + ZigList lib_paths = {}; + if ((err = os_self_exe_shared_libs(lib_paths))) + return err; + for (size_t i = 0; i < lib_paths.length; i += 1) { + Buf *lib_path = lib_paths.at(i); + if ((err = cache_add_file(ch, lib_path))) + return err; + } + if ((err = cache_final(ch, &saved_compiler_id))) + return err; + + cache_release(ch); + + *result = &saved_compiler_id; + return ErrorNone; +} + diff --git a/src/compiler.hpp b/src/compiler.hpp new file mode 100644 index 0000000000..b95e4ceda7 --- /dev/null +++ b/src/compiler.hpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_COMPILER_HPP +#define ZIG_COMPILER_HPP + +#include "buffer.hpp" +#include "error.hpp" + +Buf *get_stage1_cache_path(); +Error get_compiler_id(Buf **result); + +#endif diff --git a/src/link.cpp b/src/link.cpp index 8c250fbbe1..8d7b8b4d5f 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -32,7 +32,7 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) { static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) { ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode, - parent_gen->zig_lib_dir, parent_gen->compiler_id); + parent_gen->zig_lib_dir); child_gen->want_h_file = false; child_gen->verbose_tokenize = parent_gen->verbose_tokenize; @@ -42,8 +42,6 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) child_gen->verbose_llvm_ir = parent_gen->verbose_llvm_ir; child_gen->verbose_cimport = parent_gen->verbose_cimport; - codegen_set_cache_dir(child_gen, parent_gen->cache_dir); - codegen_set_strip(child_gen, parent_gen->strip_debug_symbols); codegen_set_is_static(child_gen, parent_gen->is_static); diff --git a/src/main.cpp b/src/main.cpp index ff2c061a83..10b789a6e1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,11 +8,11 @@ #include "ast_render.hpp" #include "buffer.hpp" #include "codegen.hpp" +#include "compiler.hpp" #include "config.h" #include "error.hpp" #include "os.hpp" #include "target.hpp" -#include "cache_hash.hpp" #include @@ -257,53 +257,6 @@ static void add_package(CodeGen *g, CliPkg *cli_pkg, PackageTableEntry *pkg) { } } -static Buf saved_compiler_id = BUF_INIT; -static Error get_compiler_id(Buf **result) { - if (saved_compiler_id.list.length != 0) { - *result = &saved_compiler_id; - return ErrorNone; - } - - Error err; - Buf app_data_dir = BUF_INIT; - if ((err = os_get_app_data_dir(&app_data_dir, "zig"))) - return err; - Buf *stage1_dir = buf_alloc(); - os_path_join(&app_data_dir, buf_create_from_str("stage1"), stage1_dir); - Buf *manifest_dir = buf_alloc(); - os_path_join(stage1_dir, buf_create_from_str("exe"), manifest_dir); - - CacheHash cache_hash; - CacheHash *ch = &cache_hash; - cache_init(ch, manifest_dir); - Buf self_exe_path = BUF_INIT; - if ((err = os_self_exe_path(&self_exe_path))) - return err; - - cache_file(ch, &self_exe_path); - - buf_resize(&saved_compiler_id, 0); - if ((err = cache_hit(ch, &saved_compiler_id))) - return err; - if (buf_len(&saved_compiler_id) != 0) { - *result = &saved_compiler_id; - return ErrorNone; - } - ZigList lib_paths = {}; - if ((err = os_self_exe_shared_libs(lib_paths))) - return err; - for (size_t i = 0; i < lib_paths.length; i += 1) { - Buf *lib_path = lib_paths.at(i); - if ((err = cache_add_file(ch, lib_path))) - return err; - } - if ((err = cache_final(ch, &saved_compiler_id))) - return err; - - *result = &saved_compiler_id; - return ErrorNone; -} - int main(int argc, char **argv) { if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) { printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", @@ -428,14 +381,7 @@ int main(int argc, char **argv) { Buf *build_runner_path = buf_alloc(); os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path); - Buf *compiler_id; - if ((err = get_compiler_id(&compiler_id))) { - fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err)); - return EXIT_FAILURE; - } - - CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf, - compiler_id); + CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf); codegen_set_out_name(g, buf_create_from_str("build")); Buf *build_file_buf = buf_create_from_str(build_file); @@ -452,8 +398,6 @@ int main(int argc, char **argv) { full_cache_dir = os_path_resolve(&cache_dir_buf, 1); } - codegen_set_cache_dir(g, full_cache_dir); - args.items[1] = buf_ptr(&build_file_dirname); args.items[2] = buf_ptr(&full_cache_dir); @@ -795,7 +739,7 @@ int main(int argc, char **argv) { switch (cmd) { case CmdBuiltin: { Buf *zig_lib_dir_buf = resolve_zig_lib_dir(); - CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, zig_lib_dir_buf, nullptr); + CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, zig_lib_dir_buf); Buf *builtin_source = codegen_generate_builtin_source(g); if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) { fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout))); @@ -850,30 +794,16 @@ int main(int argc, char **argv) { Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf; - Buf full_cache_dir = BUF_INIT; if (cmd == CmdRun && buf_out_name == nullptr) { buf_out_name = buf_create_from_str("run"); } - { - Buf *resolve_paths = buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir); - full_cache_dir = os_path_resolve(&resolve_paths, 1); - } - Buf *zig_lib_dir_buf = resolve_zig_lib_dir(); - Buf *compiler_id; - if ((err = get_compiler_id(&compiler_id))) { - fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err)); - return EXIT_FAILURE; - } - - CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, zig_lib_dir_buf, - compiler_id); + CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, zig_lib_dir_buf); 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); codegen_set_linker_script(g, linker_script); - codegen_set_cache_dir(g, full_cache_dir); if (each_lib_rpath) codegen_set_each_lib_rpath(g, each_lib_rpath); diff --git a/src/os.cpp b/src/os.cpp index 8502e72715..3950711c56 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -721,7 +721,7 @@ Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) { #endif } -int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) { +Error os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) { static const ssize_t buf_size = 0x2000; buf_resize(out_buf, buf_size); ssize_t actual_buf_len = 0; @@ -757,7 +757,7 @@ int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) { if (amt_read != buf_size) { if (feof(f)) { buf_resize(out_buf, actual_buf_len); - return 0; + return ErrorNone; } else { return ErrorFileSystem; } @@ -769,13 +769,13 @@ int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) { zig_unreachable(); } -int os_file_exists(Buf *full_path, bool *result) { +Error os_file_exists(Buf *full_path, bool *result) { #if defined(ZIG_OS_WINDOWS) *result = GetFileAttributes(buf_ptr(full_path)) != INVALID_FILE_ATTRIBUTES; - return 0; + return ErrorNone; #else *result = access(buf_ptr(full_path), F_OK) != -1; - return 0; + return ErrorNone; #endif } @@ -834,13 +834,15 @@ static int os_exec_process_posix(const char *exe, ZigList &args, FILE *stdout_f = fdopen(stdout_pipe[0], "rb"); FILE *stderr_f = fdopen(stderr_pipe[0], "rb"); - os_fetch_file(stdout_f, out_stdout, false); - os_fetch_file(stderr_f, out_stderr, false); + Error err1 = os_fetch_file(stdout_f, out_stdout, false); + Error err2 = os_fetch_file(stderr_f, out_stderr, false); fclose(stdout_f); fclose(stderr_f); - return 0; + if (err1) return err1; + if (err2) return err2; + return ErrorNone; } } #endif @@ -1064,7 +1066,7 @@ int os_copy_file(Buf *src_path, Buf *dest_path) { } } -int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { +Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { FILE *f = fopen(buf_ptr(full_path), "rb"); if (!f) { switch (errno) { @@ -1083,7 +1085,7 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { return ErrorFileSystem; } } - int result = os_fetch_file(f, out_contents, skip_shebang); + Error result = os_fetch_file(f, out_contents, skip_shebang); fclose(f); return result; } diff --git a/src/os.hpp b/src/os.hpp index fc2a34326f..ac422fbd21 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -111,8 +111,8 @@ void os_file_close(OsFile file); void os_write_file(Buf *full_path, Buf *contents); int os_copy_file(Buf *src_path, Buf *dest_path); -int os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang); -int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang); +Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang); +Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang); int os_get_cwd(Buf *out_cwd); @@ -122,7 +122,7 @@ void os_stderr_set_color(TermColor color); int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path); int os_delete_file(Buf *path); -int os_file_exists(Buf *full_path, bool *result); +Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result); int os_rename(Buf *src_path, Buf *dest_path); double os_get_time(void); -- cgit v1.2.3