authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-06 06:40:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-06 06:40:25-07:00
log5f0bfcac24036e1fff0b2beda643a60dad465213
tree7576c1acb2245b119c2b8b985cc3b8e2be9845d4
parent5e64c4d92f109638111d78b6ab97feb645ee0a01

fix undefined reference to memcpy in release mode

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
117117
118set(ZIG_STD_SRC118set(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)
123125
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}
21812181
2182static 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
2182void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {2200void 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
21922210
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);
21942212
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 }
22092217
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 }
22122220
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.a2427 // # 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 @@
1use "std.zig";1use "syscall.zig";
22
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
10export 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
19export 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 @@
1const SYS_write : usize = 1;1use "syscall.zig";
2const SYS_exit : usize = 60;
3const SYS_getrandom : usize = 318;
4
5fn 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
12fn 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
19pub 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
23pub fn exit(status: i32) -> unreachable {
24 syscall1(SYS_exit, status as usize);
25 unreachable
26}
27
28pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize {
29 syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize
30}
312
32const stdout_fileno : isize = 1;3const stdout_fileno : isize = 1;
33const stderr_fileno : isize = 2;4const stderr_fileno : isize = 2;
std/syscall.zig created+31
...@@ -0,0 +1,31 @@
1const SYS_write : usize = 1;
2const SYS_exit : usize = 60;
3const SYS_getrandom : usize = 318;
4
5fn 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
12fn 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
19pub 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
23pub fn exit(status: i32) -> unreachable {
24 syscall1(SYS_exit, status as usize);
25 unreachable
26}
27
28pub 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) {
109109
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";
112113
113 fn empty_function_1() {}114 fn empty_function_1() {}
114 fn empty_function_2() { return; }115 fn empty_function_2() { return; }