diff --git a/src/all_types.hpp b/src/all_types.hpp index dbaa3b5467..0b0de58791 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1543,23 +1543,17 @@ struct LinkLib { bool provided_explicitly; }; +// When adding fields, check if they should be added to the hash computation in build_with_cache struct CodeGen { + //////////////////////////// Runtime State LLVMModuleRef module; ZigList errors; LLVMBuilderRef builder; ZigLLVMDIBuilder *dbuilder; ZigLLVMDICompileUnit *compile_unit; ZigLLVMDIFile *compile_unit_file; - - ZigList link_libs_list; LinkLib *libc_link_lib; - // add -framework [name] args to linker - ZigList darwin_frameworks; - // add -rpath [name] args to linker - ZigList rpath_list; - - // reminder: hash tables must be initialized before use HashMap import_table; HashMap builtin_fn_table; @@ -1575,7 +1569,6 @@ struct CodeGen { HashMap string_literals_table; HashMap type_info_cache; - ZigList import_queue; size_t import_queue_index; ZigList resolve_queue; @@ -1620,7 +1613,20 @@ struct CodeGen { ZigType *entry_promise; } builtin_types; + //////////////////////////// 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; + EmitFileType emit_file_type; + BuildMode build_mode; + OutType out_type; + + + //////////////////////////// Unsorted + ZigTarget zig_target; LLVMTargetDataRef target_data_ref; unsigned pointer_size_bytes; @@ -1647,7 +1653,6 @@ struct CodeGen { Buf *ar_path; ZigWindowsSDK *win_sdk; Buf triple_str; - BuildMode build_mode; bool is_test_build; bool have_err_ret_tracing; uint32_t target_os_index; @@ -1657,13 +1662,13 @@ struct CodeGen { LLVMTargetMachineRef target_machine; ZigLLVMDIFile *dummy_di_file; bool is_native_target; - PackageTableEntry *root_package; + 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; + Buf *root_out_name; // participates in cache hash bool windows_subsystem_windows; bool windows_subsystem_console; Buf *mmacosx_version_min; @@ -1676,7 +1681,6 @@ struct CodeGen { size_t fn_defs_index; ZigList global_vars; - OutType out_type; ZigFn *cur_fn; ZigFn *main_fn; ZigFn *panic_fn; diff --git a/src/codegen.cpp b/src/codegen.cpp index 0300ccca99..e258f8d609 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -19,6 +19,7 @@ #include "target.hpp" #include "util.hpp" #include "zig_llvm.h" +#include "blake2.h" #include #include @@ -183,10 +184,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out return g; } -void codegen_destroy(CodeGen *codegen) { - LLVMDisposeTargetMachine(codegen->target_machine); -} - void codegen_set_output_h_path(CodeGen *g, Buf *h_path) { g->out_h_path = h_path; } @@ -7112,23 +7109,30 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig"); } -static void gen_root_source(CodeGen *g) { +static Buf *get_resolved_root_src_path(CodeGen *g) { + // TODO memoize if (buf_len(&g->root_package->root_src_path) == 0) - return; + return nullptr; - codegen_add_time_event(g, "Semantic Analysis"); - - Buf *rel_full_path = buf_alloc(); - os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, rel_full_path); + Buf rel_full_path = BUF_INIT; + os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, &rel_full_path); Buf *resolved_path = buf_alloc(); - Buf *resolve_paths[] = {rel_full_path}; + Buf *resolve_paths[] = {&rel_full_path}; *resolved_path = os_path_resolve(resolve_paths, 1); + return resolved_path; +} + +static void gen_root_source(CodeGen *g) { + Buf *resolved_path = get_resolved_root_src_path(g); + if (resolved_path == nullptr) + return; + Buf *source_code = buf_alloc(); int err; - if ((err = os_fetch_file_path(rel_full_path, source_code, true))) { - fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(rel_full_path), err_str(err)); + 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); } @@ -7671,10 +7675,155 @@ void codegen_add_time_event(CodeGen *g, const char *name) { g->timing_events.append({os_get_time(), name}); } +static void add_cache_str(blake2b_state *blake, const char *ptr) { + assert(ptr != nullptr); + // + 1 to include the null byte + blake2b_update(blake, ptr, strlen(ptr) + 1); +} + +static void add_cache_int(blake2b_state *blake, int x) { + // + 1 to include the null byte + uint8_t buf[sizeof(int) + 1]; + memcpy(buf, &x, sizeof(int)); + buf[sizeof(int)] = 0; + blake2b_update(blake, buf, sizeof(int) + 1); +} + +static void add_cache_buf(blake2b_state *blake, Buf *buf) { + assert(buf != nullptr); + // + 1 to include the null byte + blake2b_update(blake, buf_ptr(buf), buf_len(buf) + 1); +} + +static void add_cache_buf_opt(blake2b_state *blake, Buf *buf) { + if (buf == nullptr) { + add_cache_str(blake, ""); + add_cache_str(blake, ""); + } else { + add_cache_buf(blake, buf); + } +} + +static void add_cache_list_of_link_lib(blake2b_state *blake, LinkLib **ptr, size_t len) { + for (size_t i = 0; i < len; i += 1) { + LinkLib *lib = ptr[i]; + if (lib->provided_explicitly) { + add_cache_buf(blake, lib->name); + } + } + add_cache_str(blake, ""); +} + +static void add_cache_list_of_buf(blake2b_state *blake, Buf **ptr, size_t len) { + for (size_t i = 0; i < len; i += 1) { + Buf *buf = ptr[i]; + add_cache_buf(blake, buf); + } + add_cache_str(blake, ""); +} + +//static void add_cache_file(CodeGen *g, blake2b_state *blake, Buf *resolved_path) { +// assert(file_name != nullptr); +// g->cache_files.append(resolved_path); +//} +// +//static void add_cache_file_opt(CodeGen *g, blake2b_state *blake, Buf *resolved_path) { +// if (resolved_path == nullptr) { +// add_cache_str(blake, ""); +// add_cache_str(blake, ""); +// } else { +// add_cache_file(g, blake, resolved_path); +// } +//} + +// Ported from std/base64.zig +static uint8_t base64_fs_alphabet[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; +static void base64_encode(Slice dest, Slice source) { + size_t dest_len = ((source.len + 2) / 3) * 4; + assert(dest.len == dest_len); + + size_t i = 0; + size_t out_index = 0; + for (; i + 2 < source.len; i += 3) { + dest.ptr[out_index] = base64_fs_alphabet[(source.ptr[i] >> 2) & 0x3f]; + out_index += 1; + + dest.ptr[out_index] = base64_fs_alphabet[((source.ptr[i] & 0x3) << 4) | ((source.ptr[i + 1] & 0xf0) >> 4)]; + out_index += 1; + + dest.ptr[out_index] = base64_fs_alphabet[((source.ptr[i + 1] & 0xf) << 2) | ((source.ptr[i + 2] & 0xc0) >> 6)]; + out_index += 1; + + dest.ptr[out_index] = base64_fs_alphabet[source.ptr[i + 2] & 0x3f]; + out_index += 1; + } + + // Assert that we never need pad characters. + assert(i == source.len); + //if (i < source.len) { + // dest.ptr[out_index] = base64_fs_alphabet[(source.ptr[i] >> 2) & 0x3f]; + // out_index += 1; + + // if (i + 1 == source.len) { + // dest.ptr[out_index] = base64_fs_alphabet[(source.ptr[i] & 0x3) << 4]; + // out_index += 1; + + // dest.ptr[out_index] = encoder.pad_char; + // out_index += 1; + // } else { + // dest.ptr[out_index] = base64_fs_alphabet[((source.ptr[i] & 0x3) << 4) | ((source.ptr[i + 1] & 0xf0) >> 4)]; + // out_index += 1; + + // dest.ptr[out_index] = base64_fs_alphabet[(source.ptr[i + 1] & 0xf) << 2]; + // out_index += 1; + // } + + // dest.ptr[out_index] = encoder.pad_char; + // out_index += 1; + //} +} + +// Called before init() +static bool build_with_cache(CodeGen *g) { + blake2b_state blake; + int rc = blake2b_init(&blake, 48); + assert(rc == 0); + + // TODO zig exe & dynamic libraries + + 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; +} + void codegen_build(CodeGen *g) { assert(g->out_type != OutTypeUnknown); + if (build_with_cache(g)) + return; init(g); + codegen_add_time_event(g, "Semantic Analysis"); + gen_global_asm(g); gen_root_source(g); do_code_gen(g); 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); diff --git a/src/link.cpp b/src/link.cpp index f44e8b105e..78ad204fe9 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -69,8 +69,6 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) os_path_join(&parent_gen->cache_dir, o_out_name, output_path); codegen_link(child_gen, buf_ptr(output_path)); - codegen_destroy(child_gen); - return output_path; } diff --git a/src/main.cpp b/src/main.cpp index 4394a1d9ae..eed31438d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -461,7 +461,6 @@ int main(int argc, char **argv) { 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_destroy(g); Termination term; os_spawn_process(buf_ptr(path_to_build_exe), args, &term);