From 5f0bfcac24036e1fff0b2beda643a60dad465213 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 6 Jan 2016 06:40:25 -0700 Subject: [PATCH] fix undefined reference to memcpy in release mode when not depending on libc, we generate memcpy and memset implementations. --- CMakeLists.txt | 2 ++ src/codegen.cpp | 38 +++++++++++++++++++++++--------------- std/bootstrap.zig | 2 +- std/builtin.zig | 26 ++++++++++++++++++++++++++ std/std.zig | 31 +------------------------------ std/syscall.zig | 31 +++++++++++++++++++++++++++++++ test/run_tests.cpp | 1 + 7 files changed, 85 insertions(+), 46 deletions(-) create mode 100644 std/builtin.zig create mode 100644 std/syscall.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index e4bbed243395b9bacba55f2201c7e6493f2d114c..143fe66206b56a4e3b7ac284dd98ca81971b72d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,7 +117,9 @@ set(C_HEADERS set(ZIG_STD_SRC "${CMAKE_SOURCE_DIR}/std/bootstrap.zig" + "${CMAKE_SOURCE_DIR}/std/builtin.zig" "${CMAKE_SOURCE_DIR}/std/std.zig" + "${CMAKE_SOURCE_DIR}/std/syscall.zig" "${CMAKE_SOURCE_DIR}/std/rand.zig" ) diff --git a/src/codegen.cpp b/src/codegen.cpp index f87ca7ef246c56f276a55b2b59ecb05346cfb761..3e555a5778db6547a446dc350abf9fc16e7ca13d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2179,6 +2179,24 @@ done_looking_at_imports: return import_entry; } +static ImportTableEntry *add_special_code(CodeGen *g, const char *basename) { + Buf *std_dir = buf_create_from_str(ZIG_STD_DIR); + Buf *code_basename = buf_create_from_str(basename); + Buf path_to_code_src = BUF_INIT; + os_path_join(std_dir, code_basename, &path_to_code_src); + Buf *abs_full_path = buf_alloc(); + int err; + if ((err = os_path_real(&path_to_code_src, abs_full_path))) { + zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err)); + } + Buf *import_code = buf_alloc(); + if ((err = os_fetch_file_path(abs_full_path, import_code))) { + zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err)); + } + + return codegen_add_code(g, abs_full_path, std_dir, code_basename, import_code); +} + void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) { Buf source_path = BUF_INIT; 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 g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code); - if (g->have_exported_main && !g->link_libc && g->out_type != OutTypeLib) { - Buf *bootstrap_dir = buf_create_from_str(ZIG_STD_DIR); - Buf *bootstrap_basename = buf_create_from_str("bootstrap.zig"); - Buf path_to_bootstrap_src = BUF_INIT; - os_path_join(bootstrap_dir, bootstrap_basename, &path_to_bootstrap_src); - Buf *abs_full_path = buf_alloc(); - if ((err = os_path_real(&path_to_bootstrap_src, abs_full_path))) { - zig_panic("unable to open '%s': %s", buf_ptr(&path_to_bootstrap_src), err_str(err)); - } - Buf *import_code = buf_alloc(); - int err; - if ((err = os_fetch_file_path(abs_full_path, import_code))) { - zig_panic("unable to open '%s': %s", buf_ptr(&path_to_bootstrap_src), err_str(err)); + if (!g->link_libc) { + if (g->have_exported_main && g->out_type != OutTypeLib) { + g->bootstrap_import = add_special_code(g, "bootstrap.zig"); } - g->bootstrap_import = codegen_add_code(g, abs_full_path, bootstrap_dir, bootstrap_basename, import_code); + add_special_code(g, "builtin.zig"); } if (g->verbose) { @@ -2417,7 +2425,7 @@ void codegen_link(CodeGen *g, const char *out_file) { // invoke `ar` // example: // # static link into libfoo.a - // ar cq libfoo.a foo1.o foo2.o + // ar rcs libfoo.a foo1.o foo2.o zig_panic("TODO invoke ar"); return; } diff --git a/std/bootstrap.zig b/std/bootstrap.zig index 374aa1b9dd9c9e5a8127b25974e8cd8c09781351..b7b52353f8d676103a2c06392a55ba8533e711a9 100644 --- a/std/bootstrap.zig +++ b/std/bootstrap.zig @@ -1,4 +1,4 @@ -use "std.zig"; +use "syscall.zig"; // The compiler treats this file special by implicitly importing the function `main` // from the root source file. diff --git a/std/builtin.zig b/std/builtin.zig new file mode 100644 index 0000000000000000000000000000000000000000..0e78eb01bb48d1290f15fca0d16ccd22c32cdd11 --- /dev/null +++ b/std/builtin.zig @@ -0,0 +1,26 @@ +// These functions are provided when not linking against libc because LLVM +// sometimes generates code that calls them. + +// In the future we may put these functions in separate compile units, make them .o files, +// and then use +// ar rcs foo.a foo.o memcpy.o memset.o +// ld -o foo foo.a +// This will omit the machine code if the function is unused. + +export fn memset(dest: &u8, c: u8, n: usize) -> &u8 { + var index : #typeof(n) = 0; + while (index != n) { + dest[index] = c; + index += 1; + } + return dest; +} + +export fn memcpy(dest: &u8, src: &const u8, n: usize) -> &u8 { + var index : #typeof(n) = 0; + while (index != n) { + dest[index] = src[index]; + index += 1; + } + return dest; +} diff --git a/std/std.zig b/std/std.zig index ad6acea51dca9b9b8c187a7567bcc86223af082a..a53dbb6027caeef9aa9a2cf44fb1653f9b6bb197 100644 --- a/std/std.zig +++ b/std/std.zig @@ -1,33 +1,4 @@ -const SYS_write : usize = 1; -const SYS_exit : usize = 60; -const SYS_getrandom : usize = 318; - -fn syscall1(number: usize, arg1: usize) -> usize { - asm volatile ("syscall" - : [ret] "={rax}" (-> usize) - : [number] "{rax}" (number), [arg1] "{rdi}" (arg1) - : "rcx", "r11") -} - -fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { - asm volatile ("syscall" - : [ret] "={rax}" (-> usize) - : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3) - : "rcx", "r11") -} - -pub fn write(fd: isize, buf: &const u8, count: usize) -> isize { - syscall3(SYS_write, fd as usize, buf as usize, count) as isize -} - -pub fn exit(status: i32) -> unreachable { - syscall1(SYS_exit, status as usize); - unreachable -} - -pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize { - syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize -} +use "syscall.zig"; const stdout_fileno : isize = 1; const stderr_fileno : isize = 2; diff --git a/std/syscall.zig b/std/syscall.zig new file mode 100644 index 0000000000000000000000000000000000000000..1bcbcdbe31fff37b48f5c2f47fc0dc0b3b9e1f32 --- /dev/null +++ b/std/syscall.zig @@ -0,0 +1,31 @@ +const SYS_write : usize = 1; +const SYS_exit : usize = 60; +const SYS_getrandom : usize = 318; + +fn syscall1(number: usize, arg1: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), [arg1] "{rdi}" (arg1) + : "rcx", "r11") +} + +fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3) + : "rcx", "r11") +} + +pub fn write(fd: isize, buf: &const u8, count: usize) -> isize { + syscall3(SYS_write, fd as usize, buf as usize, count) as isize +} + +pub fn exit(status: i32) -> unreachable { + syscall1(SYS_exit, status as usize); + unreachable +} + +pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize { + syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize +} + diff --git a/test/run_tests.cpp b/test/run_tests.cpp index b44dc6ac7a2de9935f7fabda6e3a216674e1ac38..661100f6b4489c5f51a7cd0322c72452745e5912 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -109,6 +109,7 @@ static void add_compiling_test_cases(void) { add_simple_case("function call", R"SOURCE( use "std.zig"; + use "syscall.zig"; fn empty_function_1() {} fn empty_function_2() { return; } -- 2.54.0