From 1ac46fac15953820948b77b94083828f84673641 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 10 Nov 2017 14:02:45 -0500 Subject: [PATCH 1/5] add a std lib test for reading and writing files * fix fstat wrong on darwin * move std.debug.global_allocator to std.debug.global_allocator_state and make it private * add std.debug.global_allocator as a pointer (to upgrade your zig code remove the '&') --- std/array_list.zig | 2 +- std/buffer.zig | 2 +- std/c/darwin.zig | 26 ++++++++++++++------------ std/c/index.zig | 1 + std/debug.zig | 7 ++++--- std/hash_map.zig | 2 +- std/io.zig | 6 ++++++ std/io_test.zig | 45 +++++++++++++++++++++++++++++++++++++++++++++ std/linked_list.zig | 2 +- std/mem.zig | 4 ++-- std/os/darwin.zig | 2 +- std/os/index.zig | 7 +++---- std/os/path.zig | 32 ++++++++++++++++---------------- 13 files changed, 96 insertions(+), 42 deletions(-) create mode 100644 std/io_test.zig diff --git a/std/array_list.zig b/std/array_list.zig index 842cc048c..65b7e023e 100644 --- a/std/array_list.zig +++ b/std/array_list.zig @@ -101,7 +101,7 @@ pub fn ArrayList(comptime T: type) -> type{ } test "basic ArrayList test" { - var list = ArrayList(i32).init(&debug.global_allocator); + var list = ArrayList(i32).init(debug.global_allocator); defer list.deinit(); {var i: usize = 0; while (i < 10) : (i += 1) { diff --git a/std/buffer.zig b/std/buffer.zig index 5eb67beef..a1aa8faf9 100644 --- a/std/buffer.zig +++ b/std/buffer.zig @@ -135,7 +135,7 @@ pub const Buffer = struct { test "simple Buffer" { const cstr = @import("cstr.zig"); - var buf = %%Buffer.init(&debug.global_allocator, ""); + var buf = %%Buffer.init(debug.global_allocator, ""); assert(buf.len() == 0); %%buf.append("hello"); %%buf.appendByte(' '); diff --git a/std/c/darwin.zig b/std/c/darwin.zig index 7ce29b507..433463fde 100644 --- a/std/c/darwin.zig +++ b/std/c/darwin.zig @@ -6,26 +6,28 @@ pub const _errno = __error; /// Renamed to Stat to not conflict with the stat function. pub const Stat = extern struct { - dev: u32, + dev: i32, mode: u16, nlink: u16, ino: u64, uid: u32, gid: u32, - rdev: u64, - - atim: timespec, - mtim: timespec, - ctim: timespec, - - size: u64, - blocks: u64, - blksize: u32, + rdev: i32, + atime: usize, + atimensec: usize, + mtime: usize, + mtimensec: usize, + ctime: usize, + ctimensec: usize, + birthtime: usize, + birthtimensec: usize, + size: i64, + blocks: i64, + blksize: i32, flags: u32, gen: u32, lspare: i32, - qspare: [2]u64, - + qspare: [2]i64, }; pub const timespec = extern struct { diff --git a/std/c/index.zig b/std/c/index.zig index 315ccc529..2ac867ee7 100644 --- a/std/c/index.zig +++ b/std/c/index.zig @@ -14,6 +14,7 @@ pub extern "c" fn exit(code: c_int) -> noreturn; pub extern "c" fn isatty(fd: c_int) -> c_int; pub extern "c" fn close(fd: c_int) -> c_int; pub extern "c" fn fstat(fd: c_int, buf: &Stat) -> c_int; +pub extern "c" fn @"fstat$INODE64"(fd: c_int, buf: &Stat) -> c_int; pub extern "c" fn lseek(fd: c_int, offset: isize, whence: c_int) -> isize; pub extern "c" fn open(path: &const u8, oflag: c_int, ...) -> c_int; pub extern "c" fn raise(sig: c_int) -> c_int; diff --git a/std/debug.zig b/std/debug.zig index 23e951219..50322024c 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -38,7 +38,7 @@ fn getStderrStream() -> %&io.OutStream { /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. pub fn dumpStackTrace() { const stderr = getStderrStream() %% return; - writeStackTrace(stderr, &global_allocator, stderr_file.isTty(), 1) %% return; + writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% return; } /// This function invokes undefined behavior when `ok` is `false`. @@ -86,7 +86,7 @@ pub fn panic(comptime format: []const u8, args: ...) -> noreturn { const stderr = getStderrStream() %% os.abort(); stderr.print(format ++ "\n", args) %% os.abort(); - writeStackTrace(stderr, &global_allocator, stderr_file.isTty(), 1) %% os.abort(); + writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% os.abort(); os.abort(); } @@ -967,7 +967,8 @@ fn readILeb128(in_stream: &io.InStream) -> %i64 { } } -pub var global_allocator = mem.Allocator { +pub const global_allocator = &global_allocator_state; +var global_allocator_state = mem.Allocator { .allocFn = globalAlloc, .reallocFn = globalRealloc, .freeFn = globalFree, diff --git a/std/hash_map.zig b/std/hash_map.zig index 582aa7cca..d124d7b57 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -232,7 +232,7 @@ pub fn HashMap(comptime K: type, comptime V: type, } test "basicHashMapTest" { - var map = HashMap(i32, i32, hash_i32, eql_i32).init(&debug.global_allocator); + var map = HashMap(i32, i32, hash_i32, eql_i32).init(debug.global_allocator); defer map.deinit(); assert(%%map.put(1, 11) == null); diff --git a/std/io.zig b/std/io.zig index dea327cf1..02d96489a 100644 --- a/std/io.zig +++ b/std/io.zig @@ -20,6 +20,12 @@ const fmt = std.fmt; const is_posix = builtin.os != builtin.Os.windows; const is_windows = builtin.os == builtin.Os.windows; +test "import io tests" { + comptime { + _ = @import("io_test.zig"); + } +} + /// The function received invalid input at runtime. An Invalid error means a /// bug in the program that called the function. error Invalid; diff --git a/std/io_test.zig b/std/io_test.zig new file mode 100644 index 000000000..14e98bc74 --- /dev/null +++ b/std/io_test.zig @@ -0,0 +1,45 @@ +const std = @import("index.zig"); +const io = std.io; +const allocator = std.debug.global_allocator; +const Rand = std.rand.Rand; +const assert = std.debug.assert; +const mem = std.mem; +const os = std.os; + +test "write a file, read it, then delete it" { + var data: [1024]u8 = undefined; + var rng = Rand.init(1234); + rng.fillBytes(data[0..]); + const tmp_file_name = "temp_test_file.txt"; + { + var file = %%io.File.openWrite(tmp_file_name, allocator); + defer file.close(); + + var file_out_stream = io.FileOutStream.init(&file); + var buf_stream = io.BufferedOutStream.init(&file_out_stream.stream); + const st = &buf_stream.stream; + %%st.print("begin"); + %%st.write(data[0..]); + %%st.print("end"); + %%buf_stream.flush(); + } + { + var file = %%io.File.openRead(tmp_file_name, allocator); + defer file.close(); + + const file_size = %%file.getEndPos(); + const expected_file_size = "begin".len + data.len + "end".len; + assert(file_size == expected_file_size); + + var file_in_stream = io.FileInStream.init(&file); + var buf_stream = io.BufferedInStream.init(&file_in_stream.stream); + const st = &buf_stream.stream; + const contents = %%st.readAllAlloc(allocator, 2 * 1024); + defer allocator.free(contents); + + assert(mem.eql(u8, contents[0.."begin".len], "begin")); + assert(mem.eql(u8, contents["begin".len..contents.len - "end".len], data)); + assert(mem.eql(u8, contents[contents.len - "end".len ..], "end")); + } + %%os.deleteFile(allocator, tmp_file_name); +} diff --git a/std/linked_list.zig b/std/linked_list.zig index f1cd60303..cbcef793d 100644 --- a/std/linked_list.zig +++ b/std/linked_list.zig @@ -195,7 +195,7 @@ pub fn LinkedList(comptime T: type) -> type { } test "basic linked list test" { - const allocator = &debug.global_allocator; + const allocator = debug.global_allocator; var list = LinkedList(u32).init(); var one = %%list.createNode(1, allocator); diff --git a/std/mem.zig b/std/mem.zig index e37ccf011..3cfdb25b3 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -331,8 +331,8 @@ pub fn join(allocator: &Allocator, sep: u8, strings: ...) -> %[]u8 { } test "mem.join" { - assert(eql(u8, %%join(&debug.global_allocator, ',', "a", "b", "c"), "a,b,c")); - assert(eql(u8, %%join(&debug.global_allocator, ',', "a"), "a")); + assert(eql(u8, %%join(debug.global_allocator, ',', "a", "b", "c"), "a,b,c")); + assert(eql(u8, %%join(debug.global_allocator, ',', "a"), "a")); } test "testStringEquality" { diff --git a/std/os/darwin.zig b/std/os/darwin.zig index 04c72f71c..9d80c6400 100644 --- a/std/os/darwin.zig +++ b/std/os/darwin.zig @@ -129,7 +129,7 @@ pub fn isatty(fd: i32) -> bool { } pub fn fstat(fd: i32, buf: &c.Stat) -> usize { - errnoWrap(c.fstat(fd, buf)) + errnoWrap(c.@"fstat$INODE64"(fd, buf)) } pub fn lseek(fd: i32, offset: isize, whence: c_int) -> usize { diff --git a/std/os/index.zig b/std/os/index.zig index 58bfe611c..c3f33c4cc 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -562,7 +562,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { test "os.getCwd" { // at least call it so it gets compiled - _ = getCwd(&debug.global_allocator); + _ = getCwd(debug.global_allocator); } pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) -> %void { @@ -1432,10 +1432,10 @@ test "windows arg parsing" { fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const u8) { var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line); for (expected_args) |expected_arg| { - const arg = %%??it.next(&debug.global_allocator); + const arg = %%??it.next(debug.global_allocator); assert(mem.eql(u8, arg, expected_arg)); } - assert(it.next(&debug.global_allocator) == null); + assert(it.next(debug.global_allocator) == null); } test "std.os" { @@ -1500,4 +1500,3 @@ pub fn isTty(handle: FileHandle) -> bool { } } } - diff --git a/std/os/path.zig b/std/os/path.zig index 9a7b6b139..a372b5b07 100644 --- a/std/os/path.zig +++ b/std/os/path.zig @@ -41,23 +41,23 @@ pub fn joinPosix(allocator: &Allocator, paths: ...) -> %[]u8 { } test "os.path.join" { - assert(mem.eql(u8, %%joinWindows(&debug.global_allocator, "c:\\a\\b", "c"), "c:\\a\\b\\c")); - assert(mem.eql(u8, %%joinWindows(&debug.global_allocator, "c:\\a\\b\\", "c"), "c:\\a\\b\\c")); + assert(mem.eql(u8, %%joinWindows(debug.global_allocator, "c:\\a\\b", "c"), "c:\\a\\b\\c")); + assert(mem.eql(u8, %%joinWindows(debug.global_allocator, "c:\\a\\b\\", "c"), "c:\\a\\b\\c")); - assert(mem.eql(u8, %%joinWindows(&debug.global_allocator, "c:\\", "a", "b\\", "c"), "c:\\a\\b\\c")); - assert(mem.eql(u8, %%joinWindows(&debug.global_allocator, "c:\\a\\", "b\\", "c"), "c:\\a\\b\\c")); + assert(mem.eql(u8, %%joinWindows(debug.global_allocator, "c:\\", "a", "b\\", "c"), "c:\\a\\b\\c")); + assert(mem.eql(u8, %%joinWindows(debug.global_allocator, "c:\\a\\", "b\\", "c"), "c:\\a\\b\\c")); - assert(mem.eql(u8, %%joinWindows(&debug.global_allocator, + assert(mem.eql(u8, %%joinWindows(debug.global_allocator, "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig"), "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig")); - assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/a/b", "c"), "/a/b/c")); - assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/a/b/", "c"), "/a/b/c")); + assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/a/b", "c"), "/a/b/c")); + assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/a/b/", "c"), "/a/b/c")); - assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c")); - assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/a/", "b/", "c"), "/a/b/c")); + assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c")); + assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/a/", "b/", "c"), "/a/b/c")); - assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/home/andy/dev/zig/build/lib/zig/std", "io.zig"), + assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/home/andy/dev/zig/build/lib/zig/std", "io.zig"), "/home/andy/dev/zig/build/lib/zig/std/io.zig")); } @@ -453,7 +453,7 @@ pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) -> %[]u8 { } test "os.path.resolve" { - const cwd = %%os.getCwd(&debug.global_allocator); + const cwd = %%os.getCwd(debug.global_allocator); if (is_windows) { assert(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd)); } else { @@ -492,11 +492,11 @@ test "os.path.resolvePosix" { } fn testResolveWindows(paths: []const []const u8) -> []u8 { - return %%resolveWindows(&debug.global_allocator, paths); + return %%resolveWindows(debug.global_allocator, paths); } fn testResolvePosix(paths: []const []const u8) -> []u8 { - return %%resolvePosix(&debug.global_allocator, paths); + return %%resolvePosix(debug.global_allocator, paths); } pub fn dirname(path: []const u8) -> []const u8 { @@ -899,12 +899,12 @@ test "os.path.relative" { } fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) { - const result = %%relativePosix(&debug.global_allocator, from, to); + const result = %%relativePosix(debug.global_allocator, from, to); assert(mem.eql(u8, result, expected_output)); } fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) { - const result = %%relativeWindows(&debug.global_allocator, from, to); + const result = %%relativeWindows(debug.global_allocator, from, to); assert(mem.eql(u8, result, expected_output)); } @@ -1022,5 +1022,5 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { test "os.path.real" { // at least call it so it gets compiled - _ = real(&debug.global_allocator, "some_path"); + _ = real(debug.global_allocator, "some_path"); } From 20c2dbdbd3847cfaa580878fca2566347a2f4733 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 10 Nov 2017 14:36:03 -0500 Subject: [PATCH 2/5] add windows implementation of io.File.getEndPos --- std/io.zig | 31 ++++++++++++++++++++++--------- std/os/windows/index.zig | 3 +++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/std/io.zig b/std/io.zig index 02d96489a..64946b28b 100644 --- a/std/io.zig +++ b/std/io.zig @@ -253,17 +253,30 @@ pub const File = struct { } pub fn getEndPos(self: &File) -> %usize { - var stat: system.Stat = undefined; - const err = system.getErrno(system.fstat(self.handle, &stat)); - if (err > 0) { - return switch (err) { - system.EBADF => error.BadFd, - system.ENOMEM => error.OutOfMemory, - else => os.unexpectedErrorPosix(err), + if (is_posix) { + var stat: system.Stat = undefined; + const err = system.getErrno(system.fstat(self.handle, &stat)); + if (err > 0) { + return switch (err) { + system.EBADF => error.BadFd, + system.ENOMEM => error.OutOfMemory, + else => os.unexpectedErrorPosix(err), + } } - } - return usize(stat.size); + return usize(stat.size); + } else if (is_windows) { + var file_size: system.LARGE_INTEGER = undefined; + if (system.GetFileSizeEx(self.handle, &file_size) == 0) { + const err = system.GetLastError(); + return switch (err) { + else => os.unexpectedErrorWindows(err), + }; + } + return @bitCast(usize, file_size); + } else { + unreachable; + } } pub fn read(self: &File, buffer: []u8) -> %usize { diff --git a/std/os/windows/index.zig b/std/os/windows/index.zig index a398deb0b..913cc7980 100644 --- a/std/os/windows/index.zig +++ b/std/os/windows/index.zig @@ -46,6 +46,8 @@ pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuf pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: &DWORD) -> BOOL; +pub extern "kernel32" stdcallcc fn GetFileSizeEx(hFile: HANDLE, lpFileSize: &LARGE_INTEGER) -> BOOL; + pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD; pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE, @@ -115,6 +117,7 @@ pub const ULONG_PTR = usize; pub const UNICODE = false; pub const WCHAR = u16; pub const WORD = u16; +pub const LARGE_INTEGER = i64; pub const TRUE = 1; pub const FALSE = 0; From 029d37d6a7dc96f71dded5d5a9c8e7477aaa4146 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 10 Nov 2017 14:58:50 -0500 Subject: [PATCH 3/5] fix bug when multiple function definitions exist This might be related to #529 --- src/codegen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 38a1a2cbe..248dc7a38 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -408,6 +408,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); if (existing_llvm_fn) { fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0)); + return fn_table_entry->llvm_value; } else { fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); } From 403a46abccbc03e70e7975d00a5134867a1d4fc7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 10 Nov 2017 16:03:14 -0500 Subject: [PATCH 4/5] fix test failure on 32 bit windows --- std/io.zig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/std/io.zig b/std/io.zig index 64946b28b..d57092748 100644 --- a/std/io.zig +++ b/std/io.zig @@ -273,7 +273,9 @@ pub const File = struct { else => os.unexpectedErrorWindows(err), }; } - return @bitCast(usize, file_size); + if (file_size < 0) + return error.Overflow; + return math.cast(usize, u64(file_size)); } else { unreachable; } From 019f18058bb74816f8754de63a219347597e06da Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 10 Nov 2017 16:32:37 -0500 Subject: [PATCH 5/5] fix test failures put all the codegen for fn prototypes to the same place --- example/cat/main.zig | 2 +- src/all_types.hpp | 6 +-- src/analyze.cpp | 3 -- src/codegen.cpp | 96 ++++++++++++++++++++------------------------ src/ir.cpp | 1 - 5 files changed, 45 insertions(+), 63 deletions(-) diff --git a/example/cat/main.zig b/example/cat/main.zig index 902712291..00455968b 100644 --- a/example/cat/main.zig +++ b/example/cat/main.zig @@ -3,9 +3,9 @@ const io = std.io; const mem = std.mem; const os = std.os; const warn = std.debug.warn; +const allocator = std.debug.global_allocator; pub fn main() -> %void { - const allocator = &std.debug.global_allocator; var args_it = os.args(); const exe = %return unwrapArg(??args_it.next(allocator)); var catted_anything = false; diff --git a/src/all_types.hpp b/src/all_types.hpp index 797897e42..0b4efd841 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1508,13 +1508,9 @@ struct CodeGen { bool linker_rdynamic; const char *linker_script; - // The function definitions this module includes. There must be a corresponding - // fn_protos entry. + // The function definitions this module includes. ZigList fn_defs; size_t fn_defs_index; - // The function prototypes this module includes. In the case of external declarations, - // there will not be a corresponding fn_defs entry. - ZigList fn_protos; ZigList global_vars; OutType out_type; diff --git a/src/analyze.cpp b/src/analyze.cpp index 7d46ebc90..343b1ecdb 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2121,8 +2121,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { } if (!fn_table_entry->type_entry->data.fn.is_generic) { - g->fn_protos.append(fn_table_entry); - if (fn_def_node) g->fn_defs.append(fn_table_entry); @@ -2162,7 +2160,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { fn_table_entry->body_node = source_node->data.test_decl.body; fn_table_entry->is_test = true; - g->fn_protos.append(fn_table_entry); g->fn_defs.append(fn_table_entry); g->test_fns.append(fn_table_entry); diff --git a/src/codegen.cpp b/src/codegen.cpp index 248dc7a38..17c0ffc65 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -494,6 +494,49 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { // use the ABI alignment, which is fine. } + if (!type_has_bits(fn_type->data.fn.fn_type_id.return_type)) { + // nothing to do + } else if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdPointer || + fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdFn) + { + addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); + } else if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type) && + calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc)) + { + addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); + addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); + } + + + // set parameter attributes + for (size_t param_i = 0; param_i < fn_type->data.fn.fn_type_id.param_count; param_i += 1) { + FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i]; + size_t gen_index = gen_info->gen_index; + bool is_byval = gen_info->is_byval; + + if (gen_index == SIZE_MAX) { + continue; + } + + FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[param_i]; + + TypeTableEntry *param_type = gen_info->type; + if (param_info->is_noalias) { + addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "noalias"); + } + if ((param_type->id == TypeTableEntryIdPointer && param_type->data.pointer.is_const) || is_byval) { + addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "readonly"); + } + if (param_type->id == TypeTableEntryIdPointer) { + addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull"); + } + // Note: byval is disabled on windows due to an LLVM bug: + // https://github.com/zig-lang/zig/issues/536 + if (is_byval && g->zig_target.os != ZigLLVM_Win32) { + addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval"); + } + } + return fn_table_entry->llvm_value; } @@ -4298,59 +4341,6 @@ static void do_code_gen(CodeGen *g) { var->value_ref = global_value; } - // Generate function prototypes - for (size_t fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) { - FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i); - - TypeTableEntry *fn_type = fn_table_entry->type_entry; - FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; - - LLVMValueRef fn_val = fn_llvm_value(g, fn_table_entry); - - if (!type_has_bits(fn_type->data.fn.fn_type_id.return_type)) { - // nothing to do - } else if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdPointer || - fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdFn) - { - addLLVMAttr(fn_val, 0, "nonnull"); - } else if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type) && - calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc)) - { - addLLVMArgAttr(fn_val, 0, "sret"); - addLLVMArgAttr(fn_val, 0, "nonnull"); - } - - - // set parameter attributes - for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) { - FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i]; - size_t gen_index = gen_info->gen_index; - bool is_byval = gen_info->is_byval; - - if (gen_index == SIZE_MAX) { - continue; - } - - FnTypeParamInfo *param_info = &fn_type_id->param_info[param_i]; - - TypeTableEntry *param_type = gen_info->type; - if (param_info->is_noalias) { - addLLVMArgAttr(fn_val, (unsigned)gen_index, "noalias"); - } - if ((param_type->id == TypeTableEntryIdPointer && param_type->data.pointer.is_const) || is_byval) { - addLLVMArgAttr(fn_val, (unsigned)gen_index, "readonly"); - } - if (param_type->id == TypeTableEntryIdPointer) { - addLLVMArgAttr(fn_val, (unsigned)gen_index, "nonnull"); - } - // Note: byval is disabled on windows due to an LLVM bug: - // https://github.com/zig-lang/zig/issues/536 - if (is_byval && g->zig_target.os != ZigLLVM_Win32) { - addLLVMArgAttr(fn_val, (unsigned)gen_index, "byval"); - } - } - } - // Generate function definitions. for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) { FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i); diff --git a/src/ir.cpp b/src/ir.cpp index 901ba47b7..fdaced680 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10584,7 +10584,6 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal impl_fn->analyzed_executable.source_node = call_instruction->base.source_node; impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec; - ira->codegen->fn_protos.append(impl_fn); ira->codegen->fn_defs.append(impl_fn); }