diff --git a/CMakeLists.txt b/CMakeLists.txt index ffdc252b0e51caa14ac64f8a19a61da195ad93ae..8114f4315a925617c417a42db866b05f9b74addf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,7 @@ set(C_HEADERS set(ZIG_STD_SRC "${CMAKE_SOURCE_DIR}/std/bootstrap.zig" + "${CMAKE_SOURCE_DIR}/std/std.zig" ) set(C_HEADERS_DEST "lib/zig/include") diff --git a/example/hello_world/hello2.zig b/example/hello_world/hello2.zig index b31d0542bc1ad941423ed5c7f8546ab1e9d20320..45756a3b1d4f6384081ce1daba19e077e0bc13ac 100644 --- a/example/hello_world/hello2.zig +++ b/example/hello_world/hello2.zig @@ -1,11 +1,8 @@ export executable "hello"; -#link("c") -extern { - fn printf(__format: *const u8, ...) -> i32; -} +use "std.zig"; export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 { - printf("argc = %zu\n", argc); + print_str("Hello, world!", 13); return 0; } diff --git a/src/analyze.hpp b/src/analyze.hpp index cf719edbe5f172216f137f64c90a27e70c351708..2f9bb209d4292704202943de7e215ce7d564ad6d 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -108,6 +108,8 @@ struct CodeGen { LLVMZigDIBuilder *dbuilder; LLVMZigDICompileUnit *compile_unit; + ZigList lib_search_paths; + // reminder: hash tables must be initialized before use HashMap fn_table; HashMap str_table; diff --git a/src/codegen.cpp b/src/codegen.cpp index 5a177792b44b5194e0b4ef28c161445c15ffb4ab..b03c769a0dd3e0f3e33ab550326940a7e0ca3299 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -26,6 +26,7 @@ CodeGen *codegen_create(Buf *root_source_dir) { g->import_table.init(32); g->build_type = CodeGenBuildTypeDebug; g->root_source_dir = root_source_dir; + return g; } @@ -1066,6 +1067,9 @@ static void define_primitive_types(CodeGen *g) { static void init(CodeGen *g, Buf *source_path) { + g->lib_search_paths.append(g->root_source_dir); + g->lib_search_paths.append(buf_create_from_str(ZIG_STD_DIR)); + LLVMInitializeAllTargets(); LLVMInitializeAllTargetMCs(); LLVMInitializeAllAsmPrinters(); @@ -1188,17 +1192,34 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *source_path, Buf *sou AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i); if (top_level_decl->type == NodeTypeUse) { - auto entry = g->import_table.maybe_get(&top_level_decl->data.use.path); + Buf *import_target_path = &top_level_decl->data.use.path; + auto entry = g->import_table.maybe_get(import_target_path); if (!entry) { Buf full_path = BUF_INIT; - os_path_join(g->root_source_dir, &top_level_decl->data.use.path, &full_path); Buf *import_code = buf_alloc(); - if ((err = os_fetch_file_path(&full_path, import_code))) { + bool found_it = false; + + for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) { + Buf *search_path = g->lib_search_paths.at(path_i); + os_path_join(search_path, import_target_path, &full_path); + + if ((err = os_fetch_file_path(&full_path, import_code))) { + if (err == ErrorFileNotFound) { + continue; + } else { + add_node_error(g, top_level_decl, + buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err))); + goto done_looking_at_imports; + } + } + codegen_add_code(g, &top_level_decl->data.use.path, import_code); + found_it = true; + break; + } + if (!found_it) { add_node_error(g, top_level_decl, - buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err))); - break; + buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); } - codegen_add_code(g, &top_level_decl->data.use.path, import_code); } } else if (top_level_decl->type == NodeTypeFnDef) { AstNode *proto_node = top_level_decl->data.fn_def.fn_proto; @@ -1213,6 +1234,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *source_path, Buf *sou } } +done_looking_at_imports: + return import_entry; } diff --git a/std/std.zig b/std/std.zig new file mode 100644 index 0000000000000000000000000000000000000000..3bcf9e4783f247389c91b6446e590578555d69da --- /dev/null +++ b/std/std.zig @@ -0,0 +1,23 @@ +fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize { + let mut result : isize; + asm volatile ( + "mov %[number], %%rax\n" + "mov %[arg1], %%rdi\n" + "mov %[arg2], %%rsi\n" + "mov %[arg3], %%rdx\n" + "syscall\n" + "mov %%rax, %[ret]\n" + : [ret] "=r" (result) + : [number] "r" (number), [arg1] "r" (arg1), [arg2] "r" (arg2), [arg3] "r" (arg3) + : "rcx", "r11", "rax", "rdi", "rsi", "rdx"); + return result; +} + +// TODO error handling +// TODO zig strings instead of C strings +// TODO handle buffering and flushing +pub print_str(str : *const u8, len: isize) { + let SYS_write = 1; + let stdout_fileno = 1; + syscall3(SYS_write, stdout_fileno, str as isize, str_len); +} diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 2ea6befd0dee771e1feba06e1300b038650b5d00..5d28e54ebf6dbbb8ba53a0f461e08ae7265c98d1 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -461,7 +461,7 @@ export executable "test"; add_compile_fail_case("bad import", R"SOURCE( use "bogus-does-not-exist.zig"; - )SOURCE", 1, ".tmp_source.zig:2:1: error: unable to open './bogus-does-not-exist.zig': file not found"); + )SOURCE", 1, ".tmp_source.zig:2:1: error: unable to find 'bogus-does-not-exist.zig'"); add_compile_fail_case("undeclared identifier", R"SOURCE( fn a() {