| author | |
| committer | |
| log | 5f0bfcac24036e1fff0b2beda643a60dad465213 |
| tree | 7576c1acb2245b119c2b8b985cc3b8e2be9845d4 |
| parent | 5e64c4d92f109638111d78b6ab97feb645ee0a01 |
when not depending on libc, we generate memcpy and memset
implementations.7 files changed, 85 insertions(+), 46 deletions(-)
CMakeLists.txt+2| ... | @@ -117,7 +117,9 @@ set(C_HEADERS | ... | @@ -117,7 +117,9 @@ set(C_HEADERS |
| 117 | 117 | ||
| 118 | set(ZIG_STD_SRC | 118 | set(ZIG_STD_SRC |
| 119 | "${CMAKE_SOURCE_DIR}/std/bootstrap.zig" | 119 | "${CMAKE_SOURCE_DIR}/std/bootstrap.zig" |
| 120 | "${CMAKE_SOURCE_DIR}/std/builtin.zig" | ||
| 120 | "${CMAKE_SOURCE_DIR}/std/std.zig" | 121 | "${CMAKE_SOURCE_DIR}/std/std.zig" |
| 122 | "${CMAKE_SOURCE_DIR}/std/syscall.zig" | ||
| 121 | "${CMAKE_SOURCE_DIR}/std/rand.zig" | 123 | "${CMAKE_SOURCE_DIR}/std/rand.zig" |
| 122 | ) | 124 | ) |
| 123 | 125 |
src/codegen.cpp+23-15| ... | @@ -2179,6 +2179,24 @@ done_looking_at_imports: | ... | @@ -2179,6 +2179,24 @@ done_looking_at_imports: |
| 2179 | return import_entry; | 2179 | return import_entry; |
| 2180 | } | 2180 | } |
| 2181 | 2181 | ||
| 2182 | static ImportTableEntry *add_special_code(CodeGen *g, const char *basename) { | ||
| 2183 | Buf *std_dir = buf_create_from_str(ZIG_STD_DIR); | ||
| 2184 | Buf *code_basename = buf_create_from_str(basename); | ||
| 2185 | Buf path_to_code_src = BUF_INIT; | ||
| 2186 | os_path_join(std_dir, code_basename, &path_to_code_src); | ||
| 2187 | Buf *abs_full_path = buf_alloc(); | ||
| 2188 | int err; | ||
| 2189 | if ((err = os_path_real(&path_to_code_src, abs_full_path))) { | ||
| 2190 | zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err)); | ||
| 2191 | } | ||
| 2192 | Buf *import_code = buf_alloc(); | ||
| 2193 | if ((err = os_fetch_file_path(abs_full_path, import_code))) { | ||
| 2194 | zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err)); | ||
| 2195 | } | ||
| 2196 | |||
| 2197 | return codegen_add_code(g, abs_full_path, std_dir, code_basename, import_code); | ||
| 2198 | } | ||
| 2199 | |||
| 2182 | void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) { | 2200 | void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) { |
| 2183 | Buf source_path = BUF_INIT; | 2201 | Buf source_path = BUF_INIT; |
| 2184 | os_path_join(src_dir, src_basename, &source_path); | 2202 | os_path_join(src_dir, src_basename, &source_path); |
| ... | @@ -2192,22 +2210,12 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou | ... | @@ -2192,22 +2210,12 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou |
| 2192 | 2210 | ||
| 2193 | g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code); | 2211 | g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code); |
| 2194 | 2212 | ||
| 2195 | if (g->have_exported_main && !g->link_libc && g->out_type != OutTypeLib) { | 2213 | if (!g->link_libc) { |
| 2196 | Buf *bootstrap_dir = buf_create_from_str(ZIG_STD_DIR); | 2214 | if (g->have_exported_main && g->out_type != OutTypeLib) { |
| 2197 | Buf *bootstrap_basename = buf_create_from_str("bootstrap.zig"); | 2215 | g->bootstrap_import = add_special_code(g, "bootstrap.zig"); |
| 2198 | Buf path_to_bootstrap_src = BUF_INIT; | ||
| 2199 | os_path_join(bootstrap_dir, bootstrap_basename, &path_to_bootstrap_src); | ||
| 2200 | Buf *abs_full_path = buf_alloc(); | ||
| 2201 | if ((err = os_path_real(&path_to_bootstrap_src, abs_full_path))) { | ||
| 2202 | zig_panic("unable to open '%s': %s", buf_ptr(&path_to_bootstrap_src), err_str(err)); | ||
| 2203 | } | ||
| 2204 | Buf *import_code = buf_alloc(); | ||
| 2205 | int err; | ||
| 2206 | if ((err = os_fetch_file_path(abs_full_path, import_code))) { | ||
| 2207 | zig_panic("unable to open '%s': %s", buf_ptr(&path_to_bootstrap_src), err_str(err)); | ||
| 2208 | } | 2216 | } |
| 2209 | 2217 | ||
| 2210 | g->bootstrap_import = codegen_add_code(g, abs_full_path, bootstrap_dir, bootstrap_basename, import_code); | 2218 | add_special_code(g, "builtin.zig"); |
| 2211 | } | 2219 | } |
| 2212 | 2220 | ||
| 2213 | if (g->verbose) { | 2221 | if (g->verbose) { |
| ... | @@ -2417,7 +2425,7 @@ void codegen_link(CodeGen *g, const char *out_file) { | ... | @@ -2417,7 +2425,7 @@ void codegen_link(CodeGen *g, const char *out_file) { |
| 2417 | // invoke `ar` | 2425 | // invoke `ar` |
| 2418 | // example: | 2426 | // example: |
| 2419 | // # static link into libfoo.a | 2427 | // # static link into libfoo.a |
| 2420 | // ar cq libfoo.a foo1.o foo2.o | 2428 | // ar rcs libfoo.a foo1.o foo2.o |
| 2421 | zig_panic("TODO invoke ar"); | 2429 | zig_panic("TODO invoke ar"); |
| 2422 | return; | 2430 | return; |
| 2423 | } | 2431 | } |
std/bootstrap.zig+1-1| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | use "std.zig"; | 1 | use "syscall.zig"; |
| 2 | 2 | ||
| 3 | // The compiler treats this file special by implicitly importing the function `main` | 3 | // The compiler treats this file special by implicitly importing the function `main` |
| 4 | // from the root source file. | 4 | // from the root source file. |
std/builtin.zig created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | // These functions are provided when not linking against libc because LLVM | ||
| 2 | // sometimes generates code that calls them. | ||
| 3 | |||
| 4 | // In the future we may put these functions in separate compile units, make them .o files, | ||
| 5 | // and then use | ||
| 6 | // ar rcs foo.a foo.o memcpy.o memset.o | ||
| 7 | // ld -o foo foo.a | ||
| 8 | // This will omit the machine code if the function is unused. | ||
| 9 | |||
| 10 | export fn memset(dest: &u8, c: u8, n: usize) -> &u8 { | ||
| 11 | var index : #typeof(n) = 0; | ||
| 12 | while (index != n) { | ||
| 13 | dest[index] = c; | ||
| 14 | index += 1; | ||
| 15 | } | ||
| 16 | return dest; | ||
| 17 | } | ||
| 18 | |||
| 19 | export fn memcpy(dest: &u8, src: &const u8, n: usize) -> &u8 { | ||
| 20 | var index : #typeof(n) = 0; | ||
| 21 | while (index != n) { | ||
| 22 | dest[index] = src[index]; | ||
| 23 | index += 1; | ||
| 24 | } | ||
| 25 | return dest; | ||
| 26 | } | ||
std/std.zig+1-30| ... | @@ -1,33 +1,4 @@ | ... | @@ -1,33 +1,4 @@ |
| 1 | const SYS_write : usize = 1; | 1 | use "syscall.zig"; |
| 2 | const SYS_exit : usize = 60; | ||
| 3 | const SYS_getrandom : usize = 318; | ||
| 4 | |||
| 5 | fn syscall1(number: usize, arg1: usize) -> usize { | ||
| 6 | asm volatile ("syscall" | ||
| 7 | : [ret] "={rax}" (-> usize) | ||
| 8 | : [number] "{rax}" (number), [arg1] "{rdi}" (arg1) | ||
| 9 | : "rcx", "r11") | ||
| 10 | } | ||
| 11 | |||
| 12 | fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { | ||
| 13 | asm volatile ("syscall" | ||
| 14 | : [ret] "={rax}" (-> usize) | ||
| 15 | : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3) | ||
| 16 | : "rcx", "r11") | ||
| 17 | } | ||
| 18 | |||
| 19 | pub fn write(fd: isize, buf: &const u8, count: usize) -> isize { | ||
| 20 | syscall3(SYS_write, fd as usize, buf as usize, count) as isize | ||
| 21 | } | ||
| 22 | |||
| 23 | pub fn exit(status: i32) -> unreachable { | ||
| 24 | syscall1(SYS_exit, status as usize); | ||
| 25 | unreachable | ||
| 26 | } | ||
| 27 | |||
| 28 | pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize { | ||
| 29 | syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize | ||
| 30 | } | ||
| 31 | 2 | ||
| 32 | const stdout_fileno : isize = 1; | 3 | const stdout_fileno : isize = 1; |
| 33 | const stderr_fileno : isize = 2; | 4 | const stderr_fileno : isize = 2; |
std/syscall.zig created+31| ... | @@ -0,0 +1,31 @@ | ||
| 1 | const SYS_write : usize = 1; | ||
| 2 | const SYS_exit : usize = 60; | ||
| 3 | const SYS_getrandom : usize = 318; | ||
| 4 | |||
| 5 | fn syscall1(number: usize, arg1: usize) -> usize { | ||
| 6 | asm volatile ("syscall" | ||
| 7 | : [ret] "={rax}" (-> usize) | ||
| 8 | : [number] "{rax}" (number), [arg1] "{rdi}" (arg1) | ||
| 9 | : "rcx", "r11") | ||
| 10 | } | ||
| 11 | |||
| 12 | fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { | ||
| 13 | asm volatile ("syscall" | ||
| 14 | : [ret] "={rax}" (-> usize) | ||
| 15 | : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3) | ||
| 16 | : "rcx", "r11") | ||
| 17 | } | ||
| 18 | |||
| 19 | pub fn write(fd: isize, buf: &const u8, count: usize) -> isize { | ||
| 20 | syscall3(SYS_write, fd as usize, buf as usize, count) as isize | ||
| 21 | } | ||
| 22 | |||
| 23 | pub fn exit(status: i32) -> unreachable { | ||
| 24 | syscall1(SYS_exit, status as usize); | ||
| 25 | unreachable | ||
| 26 | } | ||
| 27 | |||
| 28 | pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize { | ||
| 29 | syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize | ||
| 30 | } | ||
| 31 | |||
test/run_tests.cpp+1| ... | @@ -109,6 +109,7 @@ static void add_compiling_test_cases(void) { | ... | @@ -109,6 +109,7 @@ static void add_compiling_test_cases(void) { |
| 109 | 109 | ||
| 110 | add_simple_case("function call", R"SOURCE( | 110 | add_simple_case("function call", R"SOURCE( |
| 111 | use "std.zig"; | 111 | use "std.zig"; |
| 112 | use "syscall.zig"; | ||
| 112 | 113 | ||
| 113 | fn empty_function_1() {} | 114 | fn empty_function_1() {} |
| 114 | fn empty_function_2() { return; } | 115 | fn empty_function_2() { return; } |