mirror of
https://github.com/ziglang/zig.git
synced 2026-01-04 12:33:19 +00:00
when linking with libc use the C runtime library
This commit is contained in:
parent
f2a9b40231
commit
f5a3281877
@ -61,7 +61,7 @@ compromises backward compatibility.
|
|||||||
```
|
```
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd)
|
cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd) -DZIG_LIBC_DIR=path/to/libc/dir
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
./run_tests
|
./run_tests
|
||||||
@ -72,7 +72,7 @@ make install
|
|||||||
```
|
```
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
cmake .. -DCMAKE_BUILD_TYPE=Release -DZIG_LIBC_DIR=path/to/libc/dir
|
||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
```
|
```
|
||||||
|
|||||||
@ -6,7 +6,7 @@ extern {
|
|||||||
fn exit(__status: i32) -> unreachable;
|
fn exit(__status: i32) -> unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
export fn main(argc: i32, argv: &&u8, env: &&u8) -> i32 {
|
||||||
printf(c"Hello, world!\n");
|
printf(c"Hello, world!\n");
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -164,7 +164,9 @@ struct CodeGen {
|
|||||||
unsigned pointer_size_bytes;
|
unsigned pointer_size_bytes;
|
||||||
bool is_static;
|
bool is_static;
|
||||||
bool strip_debug_symbols;
|
bool strip_debug_symbols;
|
||||||
bool insert_bootstrap_code;
|
bool have_exported_main;
|
||||||
|
bool link_libc;
|
||||||
|
Buf *libc_path;
|
||||||
CodeGenBuildType build_type;
|
CodeGenBuildType build_type;
|
||||||
LLVMTargetMachineRef target_machine;
|
LLVMTargetMachineRef target_machine;
|
||||||
LLVMZigDIFile *dummy_di_file;
|
LLVMZigDIFile *dummy_di_file;
|
||||||
|
|||||||
@ -58,6 +58,10 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
|
|||||||
g->root_out_name = out_name;
|
g->root_out_name = out_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void codegen_set_libc_path(CodeGen *g, Buf *libc_path) {
|
||||||
|
g->libc_path = libc_path;
|
||||||
|
}
|
||||||
|
|
||||||
static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
|
static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
|
||||||
|
|
||||||
|
|
||||||
@ -1517,6 +1521,18 @@ static void init(CodeGen *g, Buf *source_path) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool directives_contains_link_libc(ZigList<AstNode*> *directives) {
|
||||||
|
for (int i = 0; i < directives->length; i += 1) {
|
||||||
|
AstNode *directive_node = directives->at(i);
|
||||||
|
if (buf_eql_str(&directive_node->data.directive.name, "link") &&
|
||||||
|
buf_eql_str(&directive_node->data.directive.param, "c"))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
|
static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
|
||||||
int err;
|
int err;
|
||||||
Buf *full_path = buf_alloc();
|
Buf *full_path = buf_alloc();
|
||||||
@ -1613,11 +1629,13 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src
|
|||||||
assert(proto_node->type == NodeTypeFnProto);
|
assert(proto_node->type == NodeTypeFnProto);
|
||||||
Buf *proto_name = &proto_node->data.fn_proto.name;
|
Buf *proto_name = &proto_node->data.fn_proto.name;
|
||||||
|
|
||||||
bool is_exported = (proto_node->data.fn_proto.visib_mod != FnProtoVisibModPrivate);
|
bool is_private = (proto_node->data.fn_proto.visib_mod == FnProtoVisibModPrivate);
|
||||||
|
|
||||||
if (buf_eql_str(proto_name, "main") && is_exported) {
|
if (buf_eql_str(proto_name, "main") && !is_private) {
|
||||||
g->insert_bootstrap_code = true;
|
g->have_exported_main = true;
|
||||||
}
|
}
|
||||||
|
} else if (top_level_decl->type == NodeTypeExternBlock) {
|
||||||
|
g->link_libc = directives_contains_link_libc(top_level_decl->data.extern_block.directives);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1633,7 +1651,7 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
|
|||||||
|
|
||||||
g->root_import = codegen_add_code(g, src_dir, src_basename, source_code);
|
g->root_import = codegen_add_code(g, src_dir, src_basename, source_code);
|
||||||
|
|
||||||
if (g->insert_bootstrap_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_dir = buf_create_from_str(ZIG_STD_DIR);
|
||||||
Buf *bootstrap_basename = buf_create_from_str("bootstrap.zig");
|
Buf *bootstrap_basename = buf_create_from_str("bootstrap.zig");
|
||||||
Buf path_to_bootstrap_src = BUF_INIT;
|
Buf path_to_bootstrap_src = BUF_INIT;
|
||||||
@ -1788,6 +1806,22 @@ static void generate_h_file(CodeGen *g) {
|
|||||||
zig_panic("unable to close h file: %s", strerror(errno));
|
zig_panic("unable to close h file: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void find_libc_path(CodeGen *g) {
|
||||||
|
if (g->libc_path && buf_len(g->libc_path))
|
||||||
|
return;
|
||||||
|
g->libc_path = buf_create_from_str(ZIG_LIBC_DIR);
|
||||||
|
if (g->libc_path && buf_len(g->libc_path))
|
||||||
|
return;
|
||||||
|
fprintf(stderr, "Unable to determine libc path. Consider using `--libc-path [path]`\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *get_libc_file(CodeGen *g, const char *file) {
|
||||||
|
Buf *out_buf = buf_alloc();
|
||||||
|
os_path_join(g->libc_path, buf_create_from_str(file), out_buf);
|
||||||
|
return buf_ptr(out_buf);
|
||||||
|
}
|
||||||
|
|
||||||
void codegen_link(CodeGen *g, const char *out_file) {
|
void codegen_link(CodeGen *g, const char *out_file) {
|
||||||
bool is_optimized = (g->build_type == CodeGenBuildTypeRelease);
|
bool is_optimized = (g->build_type == CodeGenBuildTypeRelease);
|
||||||
if (is_optimized) {
|
if (is_optimized) {
|
||||||
@ -1826,6 +1860,9 @@ void codegen_link(CodeGen *g, const char *out_file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (g->out_type == OutTypeObj) {
|
if (g->out_type == OutTypeObj) {
|
||||||
|
if (g->verbose) {
|
||||||
|
fprintf(stderr, "OK\n");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1840,8 +1877,12 @@ void codegen_link(CodeGen *g, const char *out_file) {
|
|||||||
|
|
||||||
// invoke `ld`
|
// invoke `ld`
|
||||||
ZigList<const char *> args = {0};
|
ZigList<const char *> args = {0};
|
||||||
|
const char *crt1o;
|
||||||
if (g->is_static) {
|
if (g->is_static) {
|
||||||
args.append("-static");
|
args.append("-static");
|
||||||
|
crt1o = "crt1.o";
|
||||||
|
} else {
|
||||||
|
crt1o = "Scrt1.o";
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER");
|
char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER");
|
||||||
@ -1868,8 +1909,21 @@ void codegen_link(CodeGen *g, const char *out_file) {
|
|||||||
args.append("-o");
|
args.append("-o");
|
||||||
args.append(out_file);
|
args.append(out_file);
|
||||||
|
|
||||||
|
bool link_in_crt = (g->link_libc && g->out_type == OutTypeExe);
|
||||||
|
|
||||||
|
if (link_in_crt) {
|
||||||
|
find_libc_path(g);
|
||||||
|
|
||||||
|
args.append(get_libc_file(g, crt1o));
|
||||||
|
args.append(get_libc_file(g, "crti.o"));
|
||||||
|
}
|
||||||
|
|
||||||
args.append((const char *)buf_ptr(&out_file_o));
|
args.append((const char *)buf_ptr(&out_file_o));
|
||||||
|
|
||||||
|
if (link_in_crt) {
|
||||||
|
args.append(get_libc_file(g, "crtn.o"));
|
||||||
|
}
|
||||||
|
|
||||||
auto it = g->link_table.entry_iterator();
|
auto it = g->link_table.entry_iterator();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto *entry = it.next();
|
auto *entry = it.next();
|
||||||
@ -1880,7 +1934,24 @@ void codegen_link(CodeGen *g, const char *out_file) {
|
|||||||
args.append(buf_ptr(arg));
|
args.append(buf_ptr(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
os_spawn_process("ld", args, false);
|
if (g->verbose) {
|
||||||
|
fprintf(stderr, "ld");
|
||||||
|
for (int i = 0; i < args.length; i += 1) {
|
||||||
|
fprintf(stderr, " %s", args.at(i));
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int return_code;
|
||||||
|
Buf ld_stderr = BUF_INIT;
|
||||||
|
Buf ld_stdout = BUF_INIT;
|
||||||
|
os_exec_process("ld", args, &return_code, &ld_stderr, &ld_stdout);
|
||||||
|
|
||||||
|
if (return_code != 0) {
|
||||||
|
fprintf(stderr, "ld failed with return code %d\n", return_code);
|
||||||
|
fprintf(stderr, "%s\n", buf_ptr(&ld_stderr));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (g->out_type == OutTypeLib) {
|
if (g->out_type == OutTypeLib) {
|
||||||
generate_h_file(g);
|
generate_h_file(g);
|
||||||
|
|||||||
@ -33,6 +33,7 @@ void codegen_set_verbose(CodeGen *codegen, bool verbose);
|
|||||||
void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
|
void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
|
||||||
void codegen_set_out_type(CodeGen *codegen, OutType out_type);
|
void codegen_set_out_type(CodeGen *codegen, OutType out_type);
|
||||||
void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
|
void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
|
||||||
|
void codegen_set_libc_path(CodeGen *codegen, Buf *libc_path);
|
||||||
|
|
||||||
void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
|
void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
|
||||||
|
|
||||||
|
|||||||
@ -8,5 +8,6 @@
|
|||||||
|
|
||||||
#define ZIG_HEADERS_DIR "@CMAKE_INSTALL_PREFIX@/@C_HEADERS_DEST@"
|
#define ZIG_HEADERS_DIR "@CMAKE_INSTALL_PREFIX@/@C_HEADERS_DEST@"
|
||||||
#define ZIG_STD_DIR "@CMAKE_INSTALL_PREFIX@/@ZIG_STD_DEST@"
|
#define ZIG_STD_DIR "@CMAKE_INSTALL_PREFIX@/@ZIG_STD_DEST@"
|
||||||
|
#define ZIG_LIBC_DIR "@ZIG_LIBC_DIR@"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -29,6 +29,7 @@ static int usage(const char *arg0) {
|
|||||||
" --output [file] override destination path\n"
|
" --output [file] override destination path\n"
|
||||||
" --verbose turn on compiler debug output\n"
|
" --verbose turn on compiler debug output\n"
|
||||||
" --color [auto|off|on] enable or disable colored error messages\n"
|
" --color [auto|off|on] enable or disable colored error messages\n"
|
||||||
|
" --libc-path [path] set the C compiler data path\n"
|
||||||
"Command: parseh target\n"
|
"Command: parseh target\n"
|
||||||
" -isystem [dir] add additional search path for other .h files\n"
|
" -isystem [dir] add additional search path for other .h files\n"
|
||||||
" -dirafter [dir] same as -isystem but do it last\n"
|
" -dirafter [dir] same as -isystem but do it last\n"
|
||||||
@ -52,6 +53,7 @@ struct Build {
|
|||||||
const char *out_name;
|
const char *out_name;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
ErrColor color;
|
ErrColor color;
|
||||||
|
const char *libc_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int build(const char *arg0, int argc, char **argv) {
|
static int build(const char *arg0, int argc, char **argv) {
|
||||||
@ -99,6 +101,8 @@ static int build(const char *arg0, int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
} else if (strcmp(arg, "--name") == 0) {
|
} else if (strcmp(arg, "--name") == 0) {
|
||||||
b.out_name = argv[i];
|
b.out_name = argv[i];
|
||||||
|
} else if (strcmp(arg, "--libc-path") == 0) {
|
||||||
|
b.libc_path = argv[i];
|
||||||
} else {
|
} else {
|
||||||
return usage(arg0);
|
return usage(arg0);
|
||||||
}
|
}
|
||||||
@ -142,6 +146,8 @@ static int build(const char *arg0, int argc, char **argv) {
|
|||||||
codegen_set_out_type(g, b.out_type);
|
codegen_set_out_type(g, b.out_type);
|
||||||
if (b.out_name)
|
if (b.out_name)
|
||||||
codegen_set_out_name(g, buf_create_from_str(b.out_name));
|
codegen_set_out_name(g, buf_create_from_str(b.out_name));
|
||||||
|
if (b.libc_path)
|
||||||
|
codegen_set_libc_path(g, buf_create_from_str(b.libc_path));
|
||||||
codegen_set_verbose(g, b.verbose);
|
codegen_set_verbose(g, b.verbose);
|
||||||
codegen_set_errmsg_color(g, b.color);
|
codegen_set_errmsg_color(g, b.color);
|
||||||
codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
|
codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
|
||||||
|
|||||||
@ -77,7 +77,9 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
|
|||||||
|
|
||||||
void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
|
void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
|
||||||
buf_init_from_buf(out_full_path, dirname);
|
buf_init_from_buf(out_full_path, dirname);
|
||||||
buf_append_char(out_full_path, '/');
|
uint8_t c = *(buf_ptr(out_full_path) + buf_len(out_full_path) - 1);
|
||||||
|
if (c != '/')
|
||||||
|
buf_append_char(out_full_path, '/');
|
||||||
buf_append_buf(out_full_path, basename);
|
buf_append_buf(out_full_path, basename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -100,43 +100,34 @@ static void add_compiling_test_cases(void) {
|
|||||||
#link("c")
|
#link("c")
|
||||||
extern {
|
extern {
|
||||||
fn puts(s: &const u8) -> i32;
|
fn puts(s: &const u8) -> i32;
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
export fn main(argc: i32, argv: &&u8, env: &&u8) -> i32 {
|
||||||
puts(c"Hello, world!");
|
puts(c"Hello, world!");
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "Hello, world!\n");
|
)SOURCE", "Hello, world!\n");
|
||||||
|
|
||||||
add_simple_case("function call", R"SOURCE(
|
add_simple_case("function call", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn empty_function_1() {}
|
fn empty_function_1() {}
|
||||||
fn empty_function_2() { return; }
|
fn empty_function_2() { return; }
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
empty_function_1();
|
empty_function_1();
|
||||||
empty_function_2();
|
empty_function_2();
|
||||||
this_is_a_function();
|
this_is_a_function();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn this_is_a_function() -> unreachable {
|
fn this_is_a_function() -> unreachable {
|
||||||
puts(c"OK");
|
print_str("OK\n" as string);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
)SOURCE", "OK\n");
|
)SOURCE", "OK\n");
|
||||||
|
|
||||||
add_simple_case("comments", R"SOURCE(
|
add_simple_case("comments", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* multi line doc comment
|
* multi line doc comment
|
||||||
@ -145,9 +136,9 @@ static void add_compiling_test_cases(void) {
|
|||||||
|
|
||||||
/// this is a documentation comment
|
/// this is a documentation comment
|
||||||
/// doc comment line 2
|
/// doc comment line 2
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
puts(/* mid-line comment /* nested */ */ c"OK");
|
print_str(/* mid-line comment /* nested */ */ "OK\n" as string);
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "OK\n");
|
)SOURCE", "OK\n");
|
||||||
|
|
||||||
@ -156,7 +147,7 @@ static void add_compiling_test_cases(void) {
|
|||||||
use "libc.zig";
|
use "libc.zig";
|
||||||
use "foo.zig";
|
use "foo.zig";
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
export fn main(argc: i32, argv: &&u8, env: &&u8) -> i32 {
|
||||||
private_function();
|
private_function();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,180 +181,144 @@ static void add_compiling_test_cases(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
add_simple_case("if statements", R"SOURCE(
|
add_simple_case("if statements", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
if 1 != 0 {
|
if 1 != 0 {
|
||||||
puts(c"1 is true");
|
print_str("1 is true\n" as string);
|
||||||
} else {
|
} else {
|
||||||
puts(c"1 is false");
|
print_str("1 is false\n" as string);
|
||||||
}
|
}
|
||||||
if 0 != 0 {
|
if 0 != 0 {
|
||||||
puts(c"0 is true");
|
print_str("0 is true\n" as string);
|
||||||
} else if 1 - 1 != 0 {
|
} else if 1 - 1 != 0 {
|
||||||
puts(c"1 - 1 is true");
|
print_str("1 - 1 is true\n" as string);
|
||||||
}
|
}
|
||||||
if !(0 != 0) {
|
if !(0 != 0) {
|
||||||
puts(c"!0 is true");
|
print_str("!0 is true\n" as string);
|
||||||
}
|
}
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "1 is true\n!0 is true\n");
|
)SOURCE", "1 is true\n!0 is true\n");
|
||||||
|
|
||||||
add_simple_case("params", R"SOURCE(
|
add_simple_case("params", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add(a: i32, b: i32) -> i32 {
|
fn add(a: i32, b: i32) -> i32 {
|
||||||
a + b
|
a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
if add(22, 11) == 33 {
|
if add(22, 11) == 33 {
|
||||||
puts(c"pass");
|
print_str("pass\n" as string);
|
||||||
}
|
}
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "pass\n");
|
)SOURCE", "pass\n");
|
||||||
|
|
||||||
add_simple_case("goto", R"SOURCE(
|
add_simple_case("goto", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn loop(a : i32) {
|
fn loop(a : i32) {
|
||||||
if a == 0 {
|
if a == 0 {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
puts(c"loop");
|
print_str("loop\n" as string);
|
||||||
loop(a - 1);
|
loop(a - 1);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
loop(3);
|
loop(3);
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "loop\nloop\nloop\n");
|
)SOURCE", "loop\nloop\nloop\n");
|
||||||
|
|
||||||
add_simple_case("local variables", R"SOURCE(
|
add_simple_case("local variables", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
const a : i32 = 1;
|
const a : i32 = 1;
|
||||||
const b = 2 as i32;
|
const b = 2 as i32;
|
||||||
if (a + b == 3) {
|
if (a + b == 3) {
|
||||||
puts(c"OK");
|
print_str("OK\n" as string);
|
||||||
}
|
}
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "OK\n");
|
)SOURCE", "OK\n");
|
||||||
|
|
||||||
add_simple_case("bool literals", R"SOURCE(
|
add_simple_case("bool literals", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
if (true) { puts(c"OK 1"); }
|
if (true) { print_str("OK 1\n" as string); }
|
||||||
if (false) { puts(c"BAD 1"); }
|
if (false) { print_str("BAD 1\n" as string); }
|
||||||
if (!true) { puts(c"BAD 2"); }
|
if (!true) { print_str("BAD 2\n" as string); }
|
||||||
if (!false) { puts(c"OK 2"); }
|
if (!false) { print_str("OK 2\n" as string); }
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "OK 1\nOK 2\n");
|
)SOURCE", "OK 1\nOK 2\n");
|
||||||
|
|
||||||
add_simple_case("separate block scopes", R"SOURCE(
|
add_simple_case("separate block scopes", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
if (true) {
|
if (true) {
|
||||||
const no_conflict : i32 = 5;
|
const no_conflict : i32 = 5;
|
||||||
if (no_conflict == 5) { puts(c"OK 1"); }
|
if (no_conflict == 5) { print_str("OK 1\n" as string); }
|
||||||
}
|
}
|
||||||
|
|
||||||
const c = {
|
const c = {
|
||||||
const no_conflict = 10 as i32;
|
const no_conflict = 10 as i32;
|
||||||
no_conflict
|
no_conflict
|
||||||
};
|
};
|
||||||
if (c == 10) { puts(c"OK 2"); }
|
if (c == 10) { print_str("OK 2\n" as string); }
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "OK 1\nOK 2\n");
|
)SOURCE", "OK 1\nOK 2\n");
|
||||||
|
|
||||||
add_simple_case("void parameters", R"SOURCE(
|
add_simple_case("void parameters", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
void_fun(1, void, 2);
|
void_fun(1, void, 2);
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void_fun(a : i32, b : void, c : i32) {
|
fn void_fun(a : i32, b : void, c : i32) {
|
||||||
const v = b;
|
const v = b;
|
||||||
const vv : void = if (a == 1) {v} else {};
|
const vv : void = if (a == 1) {v} else {};
|
||||||
if (a + c == 3) { puts(c"OK"); }
|
if (a + c == 3) { print_str("OK\n" as string); }
|
||||||
return vv;
|
return vv;
|
||||||
}
|
}
|
||||||
)SOURCE", "OK\n");
|
)SOURCE", "OK\n");
|
||||||
|
|
||||||
add_simple_case("mutable local variables", R"SOURCE(
|
add_simple_case("mutable local variables", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
var zero : i32;
|
var zero : i32;
|
||||||
if (zero == 0) { puts(c"zero"); }
|
if (zero == 0) { print_str("zero\n" as string); }
|
||||||
|
|
||||||
var i = 0 as i32;
|
var i = 0 as i32;
|
||||||
loop_start:
|
loop_start:
|
||||||
if i == 3 {
|
if i == 3 {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
puts(c"loop");
|
print_str("loop\n" as string);
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
goto loop_start;
|
goto loop_start;
|
||||||
done:
|
done:
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "zero\nloop\nloop\nloop\n");
|
)SOURCE", "zero\nloop\nloop\nloop\n");
|
||||||
|
|
||||||
add_simple_case("arrays", R"SOURCE(
|
add_simple_case("arrays", R"SOURCE(
|
||||||
#link("c")
|
use "std.zig";
|
||||||
extern {
|
|
||||||
fn puts(s: &const u8) -> i32;
|
|
||||||
fn exit(code: i32) -> unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||||
var array : [i32; 5];
|
var array : [i32; 5];
|
||||||
|
|
||||||
var i : i32 = 0;
|
var i : i32 = 0;
|
||||||
@ -391,10 +346,10 @@ loop_2_start:
|
|||||||
loop_2_end:
|
loop_2_end:
|
||||||
|
|
||||||
if accumulator == 15 {
|
if accumulator == 15 {
|
||||||
puts(c"OK");
|
print_str("OK\n" as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "OK\n");
|
)SOURCE", "OK\n");
|
||||||
|
|
||||||
@ -481,12 +436,11 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
|||||||
#link("c")
|
#link("c")
|
||||||
extern {
|
extern {
|
||||||
fn printf(__format: &const u8, ...) -> i32;
|
fn printf(__format: &const u8, ...) -> i32;
|
||||||
fn exit(__status: i32) -> unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn _start() -> unreachable {
|
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
||||||
printf(c"0=%d\n", 0 as i32); // TODO: more tests
|
printf(c"0=%d\n", 0 as i32); // TODO: more tests
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
)SOURCE", "0=0\n");
|
)SOURCE", "0=0\n");
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user