diff options
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | example/cat/main.zig | 45 | ||||
| -rw-r--r-- | src/all_types.hpp | 5 | ||||
| -rw-r--r-- | src/analyze.cpp | 31 | ||||
| -rw-r--r-- | src/codegen.cpp | 15 | ||||
| -rw-r--r-- | std/index.zig | 21 | ||||
| -rw-r--r-- | std/io.zig | 53 | ||||
| -rw-r--r-- | std/linux.zig | 295 | ||||
| -rw-r--r-- | std/linux_i386.zig | 92 | ||||
| -rw-r--r-- | std/linux_x86_64.zig | 116 | ||||
| -rw-r--r-- | std/test_runner.zig | 12 | ||||
| -rw-r--r-- | test/self_hosted.zig | 13 |
12 files changed, 398 insertions, 302 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ed30bd3e74..f3cba1c289 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,6 +198,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/errno.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/math.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/index.zig" DESTINATION "${ZIG_STD_DEST}") +install(FILES "${CMAKE_SOURCE_DIR}/std/linux_x86_64.zig" DESTINATION "${ZIG_STD_DEST}") +install(FILES "${CMAKE_SOURCE_DIR}/std/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}") add_executable(run_tests ${TEST_SOURCES}) target_link_libraries(run_tests) diff --git a/example/cat/main.zig b/example/cat/main.zig index 329e712612..e7971d92a0 100644 --- a/example/cat/main.zig +++ b/example/cat/main.zig @@ -1,58 +1,61 @@ -export executable "cat"; +use @import("std"); -import "std.zig"; - -// Things to do to make this work: -// * var args printing -// * cast err type to string -// * string equality +// TODO var args printing pub fn main(args: [][]u8) -> %void { const exe = args[0]; var catted_anything = false; - for (arg, args[1...]) { - if (arg == "-") { + for (args[1...]) |arg| { + if (str_eql(arg, "-")) { catted_anything = true; - cat_stream(stdin) %% |err| return err; + cat_stream(io.stdin) %% |err| return err; } else if (arg[0] == '-') { return usage(exe); } else { - var is = input_stream_open(arg, OpenReadOnly) %% |err| { - %%stderr.print("Unable to open file: {}", ([]u8)(err)); + var is = io.InStream.open(arg) %% |err| { + %%io.stderr.write("Unable to open file: "); + %%io.stderr.write(@err_name(err)); + %%io.stderr.write("\n"); return err; }; - defer is.close(); + defer %%is.close(); catted_anything = true; cat_stream(is) %% |err| return err; } } if (!catted_anything) { - cat_stream(stdin) %% |err| return err; + cat_stream(io.stdin) %% |err| return err; } } fn usage(exe: []u8) -> %void { - %%stderr.print("Usage: {} [FILE]...\n", exe); + %%io.stderr.write("Usage: "); + %%io.stderr.write(exe); + %%io.stderr.write(" [FILE]...\n"); return error.Invalid; } -fn cat_stream(is: InputStream) -> %void { +fn cat_stream(is: io.InStream) -> %void { var buf: [1024 * 4]u8 = undefined; while (true) { const bytes_read = is.read(buf) %% |err| { - %%stderr.print("Unable to read from stream: {}", ([]u8)(err)); + %%io.stderr.write("Unable to read from stream: "); + %%io.stderr.write(@err_name(err)); + %%io.stderr.write("\n"); return err; - } + }; if (bytes_read == 0) { break; } - stdout.write(buf[0...bytes_read]) %% |err| { - %%stderr.print("Unable to write to stdout: {}", ([]u8)(err)); + io.stdout.write(buf[0...bytes_read]) %% |err| { + %%io.stderr.write("Unable to write to stdout: "); + %%io.stderr.write(@err_name(err)); + %%io.stderr.write("\n"); return err; - } + }; } } diff --git a/src/all_types.hpp b/src/all_types.hpp index 7677232d8f..f51d242d3b 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1044,6 +1044,7 @@ enum BuiltinFnId { BuiltinFnIdClz, BuiltinFnIdImport, BuiltinFnIdCImport, + BuiltinFnIdErrName, }; struct BuiltinFnEntry { @@ -1177,7 +1178,7 @@ struct CodeGen { LLVMValueRef trap_fn_val; bool error_during_imports; uint32_t next_node_index; - uint32_t error_value_count; + ZigList<AstNode *> error_decls; TypeTableEntry *err_tag_type; LLVMValueRef int_overflow_fns[2][3][4]; // [0-signed,1-unsigned][0-add,1-sub,2-mul][0-8,1-16,2-32,3-64] LLVMValueRef int_builtin_fns[2][4]; // [0-ctz,1-clz][0-8,1-16,2-32,3-64] @@ -1189,6 +1190,8 @@ struct CodeGen { uint32_t test_fn_count; bool check_unused; + + bool generate_error_name_table; }; struct VariableTableEntry { diff --git a/src/analyze.cpp b/src/analyze.cpp index 96eca1de91..fc647c82d7 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1415,9 +1415,10 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) { // duplicate error definitions allowed and they get the same value err->value = existing_entry->value->value; } else { - assert(g->error_value_count < (((uint32_t)1) << (uint32_t)g->err_tag_type->data.integral.bit_count)); - err->value = g->error_value_count; - g->error_value_count += 1; + int error_value_count = g->error_decls.length; + assert(error_value_count < (((uint32_t)1) << (uint32_t)g->err_tag_type->data.integral.bit_count)); + err->value = error_value_count; + g->error_decls.append(node); g->error_table.put(&err->name, err); } @@ -4084,7 +4085,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B wanted_type->id == TypeTableEntryIdInt) { BigNum bn; - bignum_init_unsigned(&bn, g->error_value_count); + bignum_init_unsigned(&bn, g->error_decls.length); if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) { @@ -4242,6 +4243,25 @@ static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_imp return resolve_expr_const_val_as_import(g, node, child_import); } +static TypeTableEntry *analyze_err_name(CodeGen *g, ImportTableEntry *import, + BlockContext *context, AstNode *node) +{ + assert(node->type == NodeTypeFnCallExpr); + + AstNode *err_value = node->data.fn_call_expr.params.at(0); + TypeTableEntry *resolved_type = analyze_expression(g, import, context, + g->builtin_types.entry_pure_error, err_value); + + if (resolved_type->id == TypeTableEntryIdInvalid) { + return resolved_type; + } + + g->generate_error_name_table = true; + + TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); + return str_type; +} + static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, TypeTableEntry *expected_type, AstNode *node) { @@ -4570,7 +4590,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry return analyze_import(g, import, context, node); case BuiltinFnIdCImport: return analyze_c_import(g, import, context, node); - + case BuiltinFnIdErrName: + return analyze_err_name(g, import, context, node); } zig_unreachable(); } diff --git a/src/codegen.cpp b/src/codegen.cpp index fc7c036061..ec4ec8f0d2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -65,7 +65,9 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { g->generic_table.init(16); g->is_release_build = false; g->is_test_build = false; - g->error_value_count = 1; + + // the error.Ok value + g->error_decls.append(nullptr); g->root_package = new_package(buf_ptr(root_source_dir), ""); g->std_package = new_package(ZIG_STD_DIR, "index.zig"); @@ -328,6 +330,14 @@ static LLVMValueRef get_handle_value(CodeGen *g, AstNode *source_node, LLVMValue } } +static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) { + zig_panic("TODO"); + //assert(node->type == NodeTypeFnCallExpr); + //AstNode *err_val_node = node->data.fn_call_expr.params.at(0); + //LLVMValueRef err_val = gen_expr(g, err_val_node); + //arg +} + static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { assert(node->type == NodeTypeFnCallExpr); AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; @@ -467,6 +477,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { zig_unreachable(); case BuiltinFnIdCompileVar: return nullptr; + case BuiltinFnIdErrName: + return gen_err_name(g, node); } zig_unreachable(); } @@ -3739,6 +3751,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn_with_arg_count(g, BuiltinFnIdClz, "clz", 2); create_builtin_fn_with_arg_count(g, BuiltinFnIdImport, "import", 1); create_builtin_fn_with_arg_count(g, BuiltinFnIdCImport, "c_import", 1); + create_builtin_fn_with_arg_count(g, BuiltinFnIdErrName, "err_name", 1); } static void init(CodeGen *g, Buf *source_path) { diff --git a/std/index.zig b/std/index.zig index 88827dc798..07f06ea07c 100644 --- a/std/index.zig +++ b/std/index.zig @@ -2,3 +2,24 @@ pub const Rand = @import("rand.zig").Rand; pub const io = @import("io.zig"); pub const os = @import("os.zig"); pub const math = @import("math.zig"); + +pub fn assert(b: bool) { + if (!b) unreachable{} +} + +pub const str_eql = slice_eql(u8); + +pub fn slice_eql(T: type)(a: []T, b: []T) -> bool { + if (a.len != b.len) return false; + for (a) |item, index| { + if (b[index] != item) return false; + } + return true; +} + +#attribute("test") +fn string_equality() { + assert(str_eql("abcd", "abcd")); + assert(!str_eql("abcdef", "abZdef")); + assert(!str_eql("abcdefg", "abcdef")); +} diff --git a/std/io.zig b/std/io.zig index a653a8c8e9..f579db6cd9 100644 --- a/std/io.zig +++ b/std/io.zig @@ -39,37 +39,51 @@ pub error NoSpaceLeft; pub error BadPerm; pub error PipeFail; pub error BadFd; +pub error IsDir; +pub error NotDir; +pub error SymLinkLoop; +pub error ProcessFdQuotaExceeded; +pub error SystemFdQuotaExceeded; +pub error NameTooLong; +pub error NoDevice; +pub error PathNotFound; +pub error NoMem; const buffer_size = 4 * 1024; const max_u64_base10_digits = 20; const max_f64_digits = 65; +pub const OpenRead = 0b0001; +pub const OpenWrite = 0b0010; +pub const OpenCreate = 0b0100; +pub const OpenTruncate = 0b1000; + pub struct OutStream { fd: isize, buffer: [buffer_size]u8, index: isize, - pub fn print_str(os: &OutStream, str: []const u8) -> %isize { - var src_bytes_left = str.len; - var src_index: @typeof(str.len) = 0; + pub fn write(os: &OutStream, bytes: []const u8) -> %isize { + var src_bytes_left = bytes.len; + var src_index: @typeof(bytes.len) = 0; const dest_space_left = os.buffer.len - os.index; while (src_bytes_left > 0) { const copy_amt = math.min_isize(dest_space_left, src_bytes_left); - @memcpy(&os.buffer[os.index], &str[src_index], copy_amt); + @memcpy(&os.buffer[os.index], &bytes[src_index], copy_amt); os.index += copy_amt; if (os.index == os.buffer.len) { %return os.flush(); } src_bytes_left -= copy_amt; } - return str.len; + return bytes.len; } /// Prints a byte buffer, flushes the buffer, then returns the number of /// bytes printed. The "f" is for "flush". pub fn printf(os: &OutStream, str: []const u8) -> %isize { - const byte_count = %return os.print_str(str); + const byte_count = %return os.write(str); %return os.flush(); return byte_count; } @@ -138,6 +152,33 @@ pub struct OutStream { pub struct InStream { fd: isize, + pub fn open(path: []u8) -> %InStream { + const fd = linux.open(path, linux.O_LARGEFILE|linux.O_RDONLY, 0); + if (fd < 0) { + return switch (-fd) { + errno.EFAULT => unreachable{}, + errno.EINVAL => unreachable{}, + errno.EACCES => error.BadPerm, + errno.EFBIG, errno.EOVERFLOW => error.FileTooBig, + errno.EINTR => error.SigInterrupt, + errno.EISDIR => error.IsDir, + errno.ELOOP => error.SymLinkLoop, + errno.EMFILE => error.ProcessFdQuotaExceeded, + errno.ENAMETOOLONG => error.NameTooLong, + errno.ENFILE => error.SystemFdQuotaExceeded, + errno.ENODEV => error.NoDevice, + errno.ENOENT => error.PathNotFound, + errno.ENOMEM => error.NoMem, + errno.ENOSPC => error.NoSpaceLeft, + errno.ENOTDIR => error.NotDir, + errno.EPERM => error.BadPerm, + else => error.Unexpected, + } + } + + return InStream { .fd = fd, }; + } + pub fn read(is: &InStream, buf: []u8) -> %isize { const amt_read = linux.read(is.fd, &buf[0], buf.len); if (amt_read < 0) { diff --git a/std/linux.zig b/std/linux.zig index dd5c6c61d0..6f9b384f70 100644 --- a/std/linux.zig +++ b/std/linux.zig @@ -1,86 +1,6 @@ -const SYS_read = switch (@compile_var("arch")) { - x86_64 => 0, - i386 => 3, - else => unreachable{}, -}; -const SYS_write = switch (@compile_var("arch")) { - x86_64 => 1, - i386 => 4, - else => unreachable{}, -}; -const SYS_open = switch (@compile_var("arch")) { - x86_64 => 2, - i386 => 5, - else => unreachable{}, -}; -const SYS_close = switch (@compile_var("arch")) { - x86_64 => 3, - i386 => 6, - else => unreachable{}, -}; -const SYS_creat = switch (@compile_var("arch")) { - x86_64 => 85, - i386 => 8, - else => unreachable{}, -}; -const SYS_lseek = switch (@compile_var("arch")) { - x86_64 => 8, - i386 => 19, - else => unreachable{}, -}; -const SYS_mmap = switch (@compile_var("arch")) { - x86_64 => 9, - i386 => 90, - else => unreachable{}, -}; -const SYS_munmap = switch (@compile_var("arch")) { - x86_64 => 11, - i386 => 91, - else => unreachable{}, -}; -const SYS_rt_sigprocmask = switch (@compile_var("arch")) { - x86_64 => 14, - i386 => 175, - else => unreachable{}, -}; -const SYS_exit = switch (@compile_var("arch")) { - x86_64 => 60, - i386 => 1, - else => unreachable{}, -}; -const SYS_kill = switch (@compile_var("arch")) { - x86_64 => 62, - i386 => 37, - else => unreachable{}, -}; -const SYS_getgid = switch (@compile_var("arch")) { - x86_64 => 104, - i386 => 47, - else => unreachable{}, -}; -const SYS_gettid = switch (@compile_var("arch")) { - x86_64 => 186, - i386 => 224, - else => unreachable{}, -}; -const SYS_tkill = switch (@compile_var("arch")) { - x86_64 => 200, - i386 => 238, - else => unreachable{}, -}; -const SYS_tgkill = switch (@compile_var("arch")) { - x86_64 => 234, - i386 => 270, - else => unreachable{}, -}; -const SYS_openat = switch (@compile_var("arch")) { - x86_64 => 257, - i386 => 295, - else => unreachable{}, -}; -const SYS_getrandom = switch (@compile_var("arch")) { - x86_64 => 318, - i386 => 355, +const arch = switch (@compile_var("arch")) { + x86_64 => @import("linux_x86_64.zig"), + i386 => @import("linux_i386.zig"), else => unreachable{}, }; @@ -95,15 +15,6 @@ pub const MMAP_MAP_PRIVATE = 2; pub const MMAP_MAP_FIXED = 16; pub const MMAP_MAP_ANON = 32; -pub const O_RDONLY = 0x0; -pub const O_WRONLY = 0x1; -pub const O_RDWR = 0x2; -pub const O_CREAT = 0x40; -pub const O_EXCL = 0x80; -pub const O_TRUNC = 0x200; -pub const O_APPEND = 0x400; -pub const O_SYNC = 0x101000; - pub const SIGHUP = 1; pub const SIGINT = 2; pub const SIGQUIT = 3; @@ -139,209 +50,93 @@ pub const SIGPWR = 30; pub const SIGSYS = 31; pub const SIGUNUSED = SIGSYS; +pub const O_RDONLY = 0o0; +pub const O_WRONLY = 0o1; +pub const O_RDWR = 0o2; + +pub const O_CREAT = arch.O_CREAT; +pub const O_EXCL = arch.O_EXCL; +pub const O_NOCTTY = arch.O_NOCTTY; +pub const O_TRUNC = arch.O_TRUNC; +pub const O_APPEND = arch.O_APPEND; +pub const O_NONBLOCK = arch.O_NONBLOCK; +pub const O_DSYNC = arch.O_DSYNC; +pub const O_SYNC = arch.O_SYNC; +pub const O_RSYNC = arch.O_RSYNC; +pub const O_DIRECTORY = arch.O_DIRECTORY; +pub const O_NOFOLLOW = arch.O_NOFOLLOW; +pub const O_CLOEXEC = arch.O_CLOEXEC; + +pub const O_ASYNC = arch.O_ASYNC; +pub const O_DIRECT = arch.O_DIRECT; +pub const O_LARGEFILE = arch.O_LARGEFILE; +pub const O_NOATIME = arch.O_NOATIME; +pub const O_PATH = arch.O_PATH; +pub const O_TMPFILE = arch.O_TMPFILE; +pub const O_NDELAY = arch.O_NDELAY; + const SIG_BLOCK = 0; const SIG_UNBLOCK = 1; const SIG_SETMASK = 2; -const syscall0 = switch (@compile_var("arch")) { - x86_64 => x86_64_syscall0, - i386 => i386_syscall0, - else => unreachable{}, -}; -const syscall1 = switch (@compile_var("arch")) { - x86_64 => x86_64_syscall1, - i386 => i386_syscall1, - else => unreachable{}, -}; -const syscall2 = switch (@compile_var("arch")) { - x86_64 => x86_64_syscall2, - i386 => i386_syscall2, - else => unreachable{}, -}; -const syscall3 = switch (@compile_var("arch")) { - x86_64 => x86_64_syscall3, - i386 => i386_syscall3, - else => unreachable{}, -}; -const syscall4 = switch (@compile_var("arch")) { - x86_64 => x86_64_syscall4, - i386 => i386_syscall4, - else => unreachable{}, -}; -const syscall6 = switch (@compile_var("arch")) { - x86_64 => x86_64_syscall6, - i386 => i386_syscall6, - else => unreachable{}, -}; - -fn x86_64_syscall0(number: isize) -> isize { - asm volatile ("syscall" - : [ret] "={rax}" (-> isize) - : [number] "{rax}" (number) - : "rcx", "r11") -} - -fn x86_64_syscall1(number: isize, arg1: isize) -> isize { - asm volatile ("syscall" - : [ret] "={rax}" (-> isize) - : [number] "{rax}" (number), - [arg1] "{rdi}" (arg1) - : "rcx", "r11") -} - -fn x86_64_syscall2(number: isize, arg1: isize, arg2: isize) -> isize { - asm volatile ("syscall" - : [ret] "={rax}" (-> isize) - : [number] "{rax}" (number), - [arg1] "{rdi}" (arg1), - [arg2] "{rsi}" (arg2) - : "rcx", "r11") -} - -fn x86_64_syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize { - asm volatile ("syscall" - : [ret] "={rax}" (-> isize) - : [number] "{rax}" (number), - [arg1] "{rdi}" (arg1), - [arg2] "{rsi}" (arg2), - [arg3] "{rdx}" (arg3) - : "rcx", "r11") -} - -fn x86_64_syscall4(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize) -> isize { - asm volatile ("syscall" - : [ret] "={rax}" (-> isize) - : [number] "{rax}" (number), - [arg1] "{rdi}" (arg1), - [arg2] "{rsi}" (arg2), - [arg3] "{rdx}" (arg3), - [arg4] "{r10}" (arg4) - : "rcx", "r11") -} - -fn x86_64_syscall6(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize, arg5: isize, arg6: isize) -> isize { - asm volatile ("syscall" - : [ret] "={rax}" (-> isize) - : [number] "{rax}" (number), - [arg1] "{rdi}" (arg1), - [arg2] "{rsi}" (arg2), - [arg3] "{rdx}" (arg3), - [arg4] "{r10}" (arg4), - [arg5] "{r8}" (arg5), - [arg6] "{r9}" (arg6) - : "rcx", "r11") -} - -fn i386_syscall0(number: isize) -> isize { - asm volatile ("int $0x80" - : [ret] "={eax}" (-> isize) - : [number] "{eax}" (number)) -} - -fn i386_syscall1(number: isize, arg1: isize) -> isize { - asm volatile ("int $0x80" - : [ret] "={eax}" (-> isize) - : [number] "{eax}" (number), - [arg1] "{ebx}" (arg1)) -} - -fn i386_syscall2(number: isize, arg1: isize, arg2: isize) -> isize { - asm volatile ("int $0x80" - : [ret] "={eax}" (-> isize) - : [number] "{eax}" (number), - [arg1] "{ebx}" (arg1), - [arg2] "{ecx}" (arg2)) -} - -fn i386_syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize { - asm volatile ("int $0x80" - : [ret] "={eax}" (-> isize) - : [number] "{eax}" (number), - [arg1] "{ebx}" (arg1), - [arg2] "{ecx}" (arg2), - [arg3] "{edx}" (arg3)) -} - -fn i386_syscall4(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize) -> isize { - asm volatile ("int $0x80" - : [ret] "={eax}" (-> isize) - : [number] "{eax}" (number), - [arg1] "{ebx}" (arg1), - [arg2] "{ecx}" (arg2), - [arg3] "{edx}" (arg3), - [arg4] "{esi}" (arg4)) -} - -fn i386_syscall6(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize, arg5: isize, arg6: isize) -> isize { - asm volatile ("int $0x80" - : [ret] "={eax}" (-> isize) - : [number] "{eax}" (number), - [arg1] "{ebx}" (arg1), - [arg2] "{ecx}" (arg2), - [arg3] "{edx}" (arg3), - [arg4] "{esi}" (arg4), - [arg5] "{edi}" (arg5), - [arg6] "{ebp}" (arg6)) -} - pub fn mmap(address: ?&u8, length: isize, prot: isize, flags: isize, fd: isize, offset: isize) -> isize { // TODO ability to cast maybe pointer to isize const addr = if (const unwrapped ?= address) isize(unwrapped) else 0; - syscall6(SYS_mmap, addr, length, prot, flags, fd, offset) + arch.syscall6(arch.SYS_mmap, addr, length, prot, flags, fd, offset) } pub fn munmap(address: &u8, length: isize) -> isize { - syscall2(SYS_munmap, isize(address), length) + arch.syscall2(arch.SYS_munmap, isize(address), length) } pub fn read(fd: isize, buf: &u8, count: isize) -> isize { - syscall3(SYS_read, isize(fd), isize(buf), count) + arch.syscall3(arch.SYS_read, isize(fd), isize(buf), count) } pub fn write(fd: isize, buf: &const u8, count: isize) -> isize { - syscall3(SYS_write, isize(fd), isize(buf), count) + arch.syscall3(arch.SYS_write, isize(fd), isize(buf), count) } pub fn open(path: []u8, flags: isize, perm: isize) -> isize { var buf: [path.len + 1]u8 = undefined; @memcpy(&buf[0], &path[0], path.len); buf[path.len] = 0; - syscall3(SYS_open, isize(&buf[0]), flags, perm) + arch.syscall3(arch.SYS_open, isize(&buf[0]), flags, perm) } pub fn create(path: []u8, perm: isize) -> isize { var buf: [path.len + 1]u8 = undefined; @memcpy(&buf[0], &path[0], path.len); buf[path.len] = 0; - syscall2(SYS_creat, isize(&buf[0]), perm) + arch.syscall2(arch.SYS_creat, isize(&buf[0]), perm) } pub fn openat(dirfd: isize, path: []u8, flags: isize, mode: isize) -> isize { var buf: [path.len + 1]u8 = undefined; @memcpy(&buf[0], &path[0], path.len); buf[path.len] = 0; - syscall4(SYS_openat, dirfd, isize(&buf[0]), flags, mode) + arch.syscall4(arch.SYS_openat, dirfd, isize(&buf[0]), flags, mode) } pub fn close(fd: isize) -> isize { - syscall1(SYS_close, fd) + arch.syscall1(arch.SYS_close, fd) } pub fn lseek(fd: isize, offset: isize, ref_pos: isize) -> isize { - syscall3(SYS_lseek, fd, offset, ref_pos) + arch.syscall3(arch.SYS_lseek, fd, offset, ref_pos) } pub fn exit(status: i32) -> unreachable { - syscall1(SYS_exit, isize(status)); + arch.syscall1(arch.SYS_exit, isize(status)); unreachable{} } pub fn getrandom(buf: &u8, count: isize, flags: u32) -> isize { - syscall3(SYS_getrandom, isize(buf), count, isize(flags)) + arch.syscall3(arch.SYS_getrandom, isize(buf), count, isize(flags)) } pub fn kill(pid: i32, sig: i32) -> i32 { - i32(syscall2(SYS_kill, pid, sig)) + i32(arch.syscall2(arch.SYS_kill, pid, sig)) } const NSIG = 65; @@ -352,20 +147,20 @@ const app_mask = []u8 { 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, }; pub fn raise(sig: i32) -> i32 { var set: sigset_t = undefined; block_app_signals(&set); - const tid = i32(syscall0(SYS_gettid)); - const ret = i32(syscall2(SYS_tkill, tid, sig)); + const tid = i32(arch.syscall0(arch.SYS_gettid)); + const ret = i32(arch.syscall2(arch.SYS_tkill, tid, sig)); restore_signals(&set); return ret; } fn block_all_signals(set: &sigset_t) { - syscall4(SYS_rt_sigprocmask, SIG_BLOCK, isize(&all_mask), isize(set), NSIG/8); + arch.syscall4(arch.SYS_rt_sigprocmask, SIG_BLOCK, isize(&all_mask), isize(set), NSIG/8); } fn block_app_signals(set: &sigset_t) { - syscall4(SYS_rt_sigprocmask, SIG_BLOCK, isize(&app_mask), isize(set), NSIG/8); + arch.syscall4(arch.SYS_rt_sigprocmask, SIG_BLOCK, isize(&app_mask), isize(set), NSIG/8); } fn restore_signals(set: &sigset_t) { - syscall4(SYS_rt_sigprocmask, SIG_SETMASK, isize(set), 0, NSIG/8); + arch.syscall4(arch.SYS_rt_sigprocmask, SIG_SETMASK, isize(set), 0, NSIG/8); } diff --git a/std/linux_i386.zig b/std/linux_i386.zig new file mode 100644 index 0000000000..19440d1d5c --- /dev/null +++ b/std/linux_i386.zig @@ -0,0 +1,92 @@ +pub const O_CREAT = 0o100; +pub const O_EXCL = 0o200; +pub const O_NOCTTY = 0o400; +pub const O_TRUNC = 0o1000; +pub const O_APPEND = 0o2000; +pub const O_NONBLOCK = 0o4000; +pub const O_DSYNC = 0o10000; +pub const O_SYNC = 0o4010000; +pub const O_RSYNC = 0o4010000; +pub const O_DIRECTORY = 0o200000; +pub const O_NOFOLLOW = 0o400000; +pub const O_CLOEXEC = 0o2000000; + +pub const O_ASYNC = 0o20000; +pub const O_DIRECT = 0o40000; +pub const O_LARGEFILE = 0o100000; +pub const O_NOATIME = 0o1000000; +pub const O_PATH = 0o10000000; +pub const O_TMPFILE = 0o20200000; +pub const O_NDELAY = O_NONBLOCK; + +pub const F_DUPFD = 0; +pub const F_GETFD = 1; +pub const F_SETFD = 2; +pub const F_GETFL = 3; +pub const F_SETFL = 4; + +pub const F_SETOWN = 8; +pub const F_GETOWN = 9; +pub const F_SETSIG = 10; +pub const F_GETSIG = 11; + +pub const F_GETLK = 12; +pub const F_SETLK = 13; +pub const F_SETLKW = 14; + +pub const F_SETOWN_EX = 15; +pub const F_GETOWN_EX = 16; + +pub const F_GETOWNER_UIDS = 17; + +pub fn syscall0(number: isize) -> isize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> isize) + : [number] "{eax}" (number)) +} + +pub fn syscall1(number: isize, arg1: isize) -> isize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> isize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1)) +} + +pub fn syscall2(number: isize, arg1: isize, arg2: isize) -> isize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> isize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1), + [arg2] "{ecx}" (arg2)) +} + +pub fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> isize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1), + [arg2] "{ecx}" (arg2), + [arg3] "{edx}" (arg3)) +} + +pub fn syscall4(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize) -> isize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> isize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1), + [arg2] "{ecx}" (arg2), + [arg3] "{edx}" (arg3), + [arg4] "{esi}" (arg4)) +} + +pub fn syscall6(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize, arg5: isize, arg6: isize) -> isize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> isize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1), + [arg2] "{ecx}" (arg2), + [arg3] "{edx}" (arg3), + [arg4] "{esi}" (arg4), + [arg5] "{edi}" (arg5), + [arg6] "{ebp}" (arg6)) +} diff --git a/std/linux_x86_64.zig b/std/linux_x86_64.zig new file mode 100644 index 0000000000..6d37a1a09e --- /dev/null +++ b/std/linux_x86_64.zig @@ -0,0 +1,116 @@ +pub const SYS_read = 0; +pub const SYS_write = 1; +pub const SYS_open = 2; +pub const SYS_close = 3; +pub const SYS_creat = 85; +pub const SYS_lseek = 8; +pub const SYS_mmap = 9; +pub const SYS_munmap = 11; +pub const SYS_rt_sigprocmask = 14; +pub const SYS_exit = 60; +pub const SYS_kill = 62; +pub const SYS_getgid = 104; +pub const SYS_gettid = 186; +pub const SYS_tkill = 200; +pub const SYS_tgkill = 234; +pub const SYS_openat = 257; +pub const SYS_getrandom = 318; + +pub const O_CREAT = 0o100; +pub const O_EXCL = 0o200; +pub const O_NOCTTY = 0o400; +pub const O_TRUNC = 0o1000; +pub const O_APPEND = 0o2000; +pub const O_NONBLOCK = 0o4000; +pub const O_DSYNC = 0o10000; +pub const O_SYNC = 0o4010000; +pub const O_RSYNC = 0o4010000; +pub const O_DIRECTORY = 0o200000; +pub const O_NOFOLLOW = 0o400000; +pub const O_CLOEXEC = 0o2000000; + +pub const O_ASYNC = 0o20000; +pub const O_DIRECT = 0o40000; +pub const O_LARGEFILE = 0; +pub const O_NOATIME = 0o1000000; +pub const O_PATH = 0o10000000; +pub const O_TMPFILE = 0o20200000; +pub const O_NDELAY = O_NONBLOCK; + +pub const F_DUPFD = 0; +pub const F_GETFD = 1; +pub const F_SETFD = 2; +pub const F_GETFL = 3; +pub const F_SETFL = 4; + +pub const F_SETOWN = 8; +pub const F_GETOWN = 9; +pub const F_SETSIG = 10; +pub const F_GETSIG = 11; + +pub const F_GETLK = 5; +pub const F_SETLK = 6; +pub const F_SETLKW = 7; + +pub const F_SETOWN_EX = 15; +pub const F_GETOWN_EX = 16; + +pub const F_GETOWNER_UIDS = 17; + +pub fn syscall0(number: isize) -> isize { + asm volatile ("syscall" + : [ret] "={rax}" (-> isize) + : [number] "{rax}" (number) + : "rcx", "r11") +} + +pub fn syscall1(number: isize, arg1: isize) -> isize { + asm volatile ("syscall" + : [ret] "={rax}" (-> isize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1) + : "rcx", "r11") +} + +pub fn syscall2(number: isize, arg1: isize, arg2: isize) -> isize { + asm volatile ("syscall" + : [ret] "={rax}" (-> isize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2) + : "rcx", "r11") +} + +pub fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize { + asm volatile ("syscall" + : [ret] "={rax}" (-> isize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2), + [arg3] "{rdx}" (arg3) + : "rcx", "r11") +} + +pub fn syscall4(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize) -> isize { + asm volatile ("syscall" + : [ret] "={rax}" (-> isize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2), + [arg3] "{rdx}" (arg3), + [arg4] "{r10}" (arg4) + : "rcx", "r11") +} + +pub fn syscall6(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize, arg5: isize, arg6: isize) -> isize { + asm volatile ("syscall" + : [ret] "={rax}" (-> isize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2), + [arg3] "{rdx}" (arg3), + [arg4] "{r10}" (arg4), + [arg5] "{r8}" (arg5), + [arg6] "{r9}" (arg6) + : "rcx", "r11") +} diff --git a/std/test_runner.zig b/std/test_runner.zig index 5123eff8e2..9533aeadb9 100644 --- a/std/test_runner.zig +++ b/std/test_runner.zig @@ -9,19 +9,19 @@ extern var zig_test_fn_list: []TestFn; pub fn run_tests() -> %void { for (zig_test_fn_list) |test_fn, i| { - %%io.stderr.print_str("Test "); + %%io.stderr.write("Test "); %%io.stderr.print_i64(i + 1); - %%io.stderr.print_str("/"); + %%io.stderr.write("/"); %%io.stderr.print_i64(zig_test_fn_list.len); - %%io.stderr.print_str(" "); - %%io.stderr.print_str(test_fn.name); - %%io.stderr.print_str("..."); + %%io.stderr.write(" "); + %%io.stderr.write(test_fn.name); + %%io.stderr.write("..."); %%io.stderr.flush(); test_fn.func(); - %%io.stderr.print_str("OK\n"); + %%io.stderr.write("OK\n"); %%io.stderr.flush(); } } diff --git a/test/self_hosted.zig b/test/self_hosted.zig index 847bc604bc..a2c2383f41 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -1,5 +1,5 @@ // test std library -const std = @import("std"); +use @import("std"); #attribute("test") fn empty_function() {} @@ -554,14 +554,3 @@ fn mem_alloc(T: type)(n: isize) -> %[]T { fn mem_free(T: type)(mem: []T) { } -fn assert(b: bool) { - if (!b) unreachable{} -} - -fn str_eql(s1: []u8, s2: []u8) -> bool { - if (s1.len != s2.len) return false; - for (s1) |c, i| { - if (s2[i] != c) return false; - } - return true; -} |
