From 062a67fe75917940a86016a3681f5cb6268f74b3 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 25 Feb 2025 00:40:28 +0100 Subject: [PATCH] Updates to file:: and path::, Path is now passed an allocator. `path::traverse` function. mkdir / rmdir / chdir works directly with strings. Strings get file_basepath, path_dirname. Test suite runner now uses lib7. Bug when printing a parameter declaration error. Fix optional jumps in expression lists, #1942. --- .github/workflows/main.yml | 16 +- lib7/std/io/file.c3 | 12 +- lib7/std/io/path.c3 | 229 ++++++++++++------ nix/default.nix | 2 +- releasenotes.md | 1 + src/compiler/context.c | 4 +- src/compiler/llvm_codegen_expr.c | 9 +- test/src/test_suite_runner.c3 | 31 +-- .../expressions/incdec_overload.c3t | 172 ++++++------- .../test_suite7/errors/optional_expr_list.c3t | 60 +++++ .../expressions/incdec_overload.c3t | 174 ++++++------- 11 files changed, 410 insertions(+), 300 deletions(-) create mode 100644 test/test_suite7/errors/optional_expr_list.c3t diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 342bb3bf8..a9e3754a7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -95,7 +95,7 @@ jobs: - name: run compiler tests run: | cd test - ..\build\${{ matrix.build_type }}\c3c.exe compile-run -O1 src/test_suite_runner.c3 --enable-new-generics -- ..\build\${{ matrix.build_type }}\c3c.exe test_suite/ + ..\build\${{ matrix.build_type }}\c3c.exe compile-run -O1 src/test_suite_runner.c3 --stdlib ..\lib7 --enable-new-generics -- ..\build\${{ matrix.build_type }}\c3c.exe test_suite/ - name: Test python script run: | @@ -168,7 +168,7 @@ jobs: - name: run compiler tests run: | cd test - ../build/c3c.exe compile --target windows-x64 -O1 src/test_suite_runner.c3 --enable-new-generics + ../build/c3c.exe compile --target windows-x64 -O1 src/test_suite_runner.c3 --stdlib ../lib7 --enable-new-generics ./test_suite_runner.exe ../build/c3c.exe test_suite/ build-msys2-clang: @@ -220,7 +220,7 @@ jobs: - name: run compiler tests run: | cd test - ../build/c3c.exe compile-run -O1 src/test_suite_runner.c3 --enable-new-generics + ../build/c3c.exe compile-run -O1 --stdlib ../lib7 src/test_suite_runner.c3 --enable-new-generics build-linux: runs-on: ubuntu-22.04 @@ -381,7 +381,7 @@ jobs: - name: run compiler tests run: | cd test - ../build/c3c compile-run -O1 src/test_suite_runner.c3 --enable-new-generics -- ../build/c3c test_suite/ + ../build/c3c compile-run -O1 src/test_suite_runner.c3 --stdlib ../lib7 --enable-new-generics -- ../build/c3c test_suite/ - name: bundle_output if: matrix.llvm_version == env.LLVM_RELEASE_VERSION_LINUX @@ -502,7 +502,7 @@ jobs: - name: run compiler tests run: | cd test - ../build/c3c compile-run -O1 src/test_suite_runner.c3 --enable-new-generics -- ../build/c3c test_suite/ + ../build/c3c compile-run -O1 src/test_suite_runner.c3 --stdlib ../lib7 --enable-new-generics -- ../build/c3c test_suite/ - name: bundle_output if: matrix.llvm_version == env.LLVM_RELEASE_VERSION_UBUNTU20 @@ -606,7 +606,7 @@ jobs: - name: run compiler tests run: | cd test - ../build/c3c compile-run -O1 src/test_suite_runner.c3 --enable-new-generics -- ../build/c3c test_suite/ + ../build/c3c compile-run -O1 src/test_suite_runner.c3 --stdlib ../lib7 --enable-new-generics -- ../build/c3c test_suite/ build-mac: runs-on: macos-latest @@ -686,13 +686,13 @@ jobs: - name: run compiler tests run: | cd test - ../build/c3c compile -O1 src/test_suite_runner.c3 --enable-new-generics + ../build/c3c compile -O1 src/test_suite_runner.c3 --stdlib ../lib7 --enable-new-generics ./test_suite_runner ../build/c3c test_suite/ - name: run build test suite runner run: | cd test - ../build/c3c compile -O1 src/test_suite_runner.c3 --enable-new-generics + ../build/c3c compile -O1 src/test_suite_runner.c3 --stdlib ../lib7 --enable-new-generics - name: bundle_output if: matrix.llvm_version == env.LLVM_RELEASE_VERSION_MAC diff --git a/lib7/std/io/file.c3 b/lib7/std/io/file.c3 index 9dd4100e1..37361b3ea 100644 --- a/lib7/std/io/file.c3 +++ b/lib7/std/io/file.c3 @@ -21,7 +21,7 @@ fn File! open_path(Path path, String mode) fn bool exists(String file) => @pool() { - return path::exists(path::tnew(file)) ?? false; + return os::native_file_or_dir_exists(file); } fn File from_handle(CFile file) @@ -34,12 +34,20 @@ fn bool is_file(String path) return os::native_is_file(path); } +fn bool is_dir(String path) +{ + return os::native_is_dir(path); +} + fn usz! get_size(String path) { return os::native_file_size(path); } -fn void! delete(String filename) => os::native_remove(filename) @inline; +fn void! delete(String filename) +{ + return os::native_remove(filename) @inline; +} <* diff --git a/lib7/std/io/path.c3 b/lib7/std/io/path.c3 index 5c0055a27..15ca8e34f 100644 --- a/lib7/std/io/path.c3 +++ b/lib7/std/io/path.c3 @@ -2,7 +2,7 @@ module std::io::path; import std::collections::list, std::io::os; import std::os::win32; -const PathEnv DEFAULT_PATH_ENV = env::WIN32 ? PathEnv.WIN32 : PathEnv.POSIX; +const PathEnv DEFAULT_ENV = env::WIN32 ? PathEnv.WIN32 : PathEnv.POSIX; const char PREFERRED_SEPARATOR_WIN32 = '\\'; const char PREFERRED_SEPARATOR_POSIX = '/'; const char PREFERRED_SEPARATOR = env::WIN32 ? PREFERRED_SEPARATOR_WIN32 : PREFERRED_SEPARATOR_POSIX; @@ -21,6 +21,7 @@ struct PathImp (Printable) { String path_string; PathEnv env; + Allocator allocator; } enum PathEnv @@ -42,24 +43,35 @@ fn bool is_file(Path path) => os::native_is_file(path.str_view()); fn usz! file_size(Path path) => os::native_file_size(path.str_view()); fn bool exists(Path path) => os::native_file_or_dir_exists(path.str_view()); fn Path! tcwd() => cwd(tmem()) @inline; -fn void! chdir(Path path) => os::native_chdir(path) @inline; + +<* + @require @is_pathlike(path) : "Expected a Path or String to chdir" +*> +macro void! chdir(path) +{ + $if @typeis(path, String): + @pool() + { + return os::native_chdir(tnew(path)); + }; + $else + return os::native_chdir(path) @inline; + $endif +} + fn Path! temp_directory(Allocator allocator) => os::native_temp_directory(allocator); + fn void! delete(Path path) => os::native_remove(path.str_view()) @inline; -macro bool is_separator(char c, PathEnv path_env = DEFAULT_PATH_ENV) +macro bool @is_pathlike(#path) => @typeis(#path, String) || @typeis(#path, Path); + +macro bool is_separator(char c, PathEnv path_env = DEFAULT_ENV) { return c == '/' || (c == '\\' && path_env == PathEnv.WIN32); } -macro bool is_posix_separator(char c) -{ - return c == '/' || c == '\\'; -} - -macro bool is_win32_separator(char c) -{ - return c == '/' || c == '\\'; -} +macro bool is_posix_separator(char c) => c == '/'; +macro bool is_win32_separator(char c) => c == '/' || c == '\\'; fn PathList! ls(Allocator allocator, Path dir, bool no_dirs = false, bool no_symlinks = false, String mask = "") { @@ -81,35 +93,35 @@ enum MkdirPermissions Create a directory on a given path, optionally recursive. @param path `The path to create` + @require @is_pathlike(path) : "Expected a Path or String to chdir" @param recursive `If directories in between should be created if they're missing, defaults to false` @param permissions `The permissions to set on the directory` *> -fn bool! mkdir(Path path, bool recursive = false, MkdirPermissions permissions = NORMAL) +macro bool! mkdir(Path path, bool recursive = false, MkdirPermissions permissions = NORMAL) { - if (!path.path_string.len) return PathResult.INVALID_PATH?; - if (is_dir(path)) return false; - if (exists(path)) return IoError.FILE_NOT_DIR?; - - if (recursive) - { - if (try parent = path.parent()) mkdir(parent, true, permissions)!; - } - if (!is_dir(path.parent()) ?? false) return IoError.CANNOT_READ_DIR?; - - return os::native_mkdir(path, permissions); + $if @typeis(path, String): + @pool() { return _mkdir(tnew(path), recursive, permissions); }; + $else + return _mkdir(path, recursive, permissions); + $endif } + <* Tries to delete directory, which must be empty. @param path `The path to delete` + @require @is_pathlike(path) : "Expected a Path or String to chdir" @return `true if there was a directory to delete, false otherwise` @return! PathResult.INVALID_PATH `if the path was invalid` *> -fn bool! rmdir(Path path) +macro bool! rmdir(path) { - if (!path.path_string.len) return PathResult.INVALID_PATH?; - return os::native_rmdir(path); + $if @typeis(path, String): + @pool() { return _rmdir(tnew(path)); }; + $else + return _mkdir(path); + $endif } <* @@ -130,9 +142,9 @@ fn void! rmtree(Path path) @return! PathResult.INVALID_PATH `if the path was invalid` *> -fn Path! new(Allocator allocator, String path, PathEnv path_env = DEFAULT_PATH_ENV) +fn Path! new(Allocator allocator, String path, PathEnv path_env = DEFAULT_ENV) { - return { normalize(path.copy(allocator), path_env), path_env }; + return { normalize(path.copy(allocator), path_env), path_env, allocator }; } <* @@ -140,7 +152,7 @@ fn Path! new(Allocator allocator, String path, PathEnv path_env = DEFAULT_PATH_E @return! PathResult.INVALID_PATH `if the path was invalid` *> -fn Path! tnew(String path, PathEnv path_env = DEFAULT_PATH_ENV) +fn Path! tnew(String path, PathEnv path_env = DEFAULT_ENV) { return new(tmem(), path, path_env); } @@ -181,33 +193,37 @@ fn Path! Path.append(self, Allocator allocator, String filename) dstr.append(self.path_string); dstr.append(PREFERRED_SEPARATOR); dstr.append(filename); - return { normalize(dstr.copy_str(allocator), self.env), self.env }; + return new(allocator, dstr.str_view(), self.env); }; } fn Path! Path.tappend(self, String filename) => self.append(tmem(), filename); -fn usz Path.start_of_base_name(self) @local +fn usz! start_of_base_name(String str, PathEnv path_env) @local { - String path_str = self.path_string; - if (!path_str.len) return 0; - if (self.env == PathEnv.WIN32) + if (!str.len) return PathResult.INVALID_PATH?; + usz! start_slash = str.rindex_of_char('/'); + if (path_env != PathEnv.WIN32) return start_slash + 1 ?? 0; + if (try index = str.rindex_of_char('\\')) { - if (try index = path_str.rindex_of_char('\\')) - { - // c:\ style path, we're done! - if (path_str[0] != '\\') return index + 1; - // Handle \\server\foo - // Find the \ before "foo" - usz last_index = 2 + path_str[2..].index_of_char('\\')!!; - // If they don't match, we're done - assert(last_index <= index, "Invalid normalized, path %d vs %s in %s", last_index, index, path_str); - if (last_index != index) return index + 1; - // Otherwise just default to the volume length. - } - return volume_name_len(path_str, self.env)!!; + if (try start_slash && start_slash > index) return start_slash + 1; + // c:\ style path, we're done! + if (str[0] != '\\') return index + 1; + // Handle \\server\foo + // Find the \ before "foo" + usz last_index = 2 + str[2..].index_of_char('\\')!; + // If they don't match, we're done + if (last_index > index) return PathResult.INVALID_PATH?; + if (last_index != index) return index + 1; + // Otherwise just default to the volume length. } - return path_str.rindex_of_char('/') + 1 ?? 0; + return volume_name_len(str, path_env)!!; +} + + +fn bool! String.is_absolute_path(self) => @pool() +{ + return tnew(self).is_absolute(); } fn bool! Path.is_absolute(self) @@ -220,8 +236,13 @@ fn bool! Path.is_absolute(self) } +fn Path! String.to_absolute_path(self, Allocator allocator) => @pool(allocator) +{ + return tnew(self).absolute(allocator); +} + <* - @require self.env == DEFAULT_PATH_ENV : "This method is only available on native paths" + @require self.env == DEFAULT_ENV : "This method is only available on native paths" *> fn Path! Path.absolute(self, Allocator allocator) { @@ -236,34 +257,47 @@ fn Path! Path.absolute(self, Allocator allocator) return new(allocator, cwd, self.env); }; } - $if DEFAULT_PATH_ENV == WIN32: + $if DEFAULT_ENV == WIN32: @pool(allocator) { const usz BUFFER_LEN = 4096; WString buffer = (WString)mem::temp_alloc_array(Char16, BUFFER_LEN); buffer = win32::_wfullpath(buffer, path_str.to_wstring_tcopy()!, BUFFER_LEN); if (!buffer) return PathResult.INVALID_PATH?; - return { string::new_from_wstring(allocator, buffer), WIN32 }; + return { string::new_from_wstring(allocator, buffer), WIN32, allocator }; }; $else String cwd = os::getcwd(tmem())!; - return (Path){ cwd, self.env }.append(allocator, path_str)!; + return (Path){ cwd, self.env, tmem() }.append(allocator, path_str)!; $endif } +fn String! String.file_basename(self, Allocator allocator) => @pool(allocator) +{ + return tnew(self).basename().copy(allocator); +} + +fn String! String.file_tbasename(self) => self.file_basename(tmem()); + fn String Path.basename(self) { - usz basename_start = self.start_of_base_name(); + usz basename_start = start_of_base_name(self.path_string, self.env)!!; String path_str = self.path_string; if (basename_start == path_str.len) return ""; return path_str[basename_start..]; } +fn String! String.path_tdirname(self) => self.path_dirname(tmem()); + +fn String! String.path_dirname(self, Allocator allocator) => @pool(allocator) +{ + return tnew(self).dirname().copy(allocator); +} fn String Path.dirname(self) { - usz basename_start = self.start_of_base_name(); String path_str = self.path_string; + usz basename_start = start_of_base_name(path_str, self.env)!!; if (basename_start == 0) return "."; usz start = volume_name_len(path_str, self.env)!!; if (basename_start <= start + 1) @@ -277,6 +311,7 @@ fn String Path.dirname(self) return path_str[:basename_start - 1]; } + <* Test if the path has the given extension, so given the path /foo/bar.c3 this would be true matching the extension "c3" @@ -310,6 +345,16 @@ fn String Path.volume_name(self) return self.path_string[:len]; } +fn Path! String.to_path(self, Allocator allocator) +{ + return new(allocator, self); +} + +fn Path! String.to_tpath(self) +{ + return new(tmem(), self); +} + fn usz! volume_name_len(String path, PathEnv path_env) @local { usz len = path.len; @@ -360,13 +405,13 @@ fn Path! Path.parent(self) { if (is_separator(c, self.env)) { - return { self.path_string[:i], self.env }; + return { self.path_string[:i], self.env, null }; } } return PathResult.NO_PARENT?; } -fn String! normalize(String path_str, PathEnv path_env = DEFAULT_PATH_ENV) +fn String! normalize(String path_str, PathEnv path_env = DEFAULT_ENV) { if (!path_str.len) return path_str; usz path_start = volume_name_len(path_str, path_env)!; @@ -517,7 +562,7 @@ def PathWalker = fn bool! (Path, bool is_dir, void*); <* Walk the path recursively. PathWalker is run on every file and directory found. Return true to abort the walk. - @require self.env == DEFAULT_PATH_ENV : "This method is only available on native paths" + @require self.env == DEFAULT_ENV : "This method is only available on native paths" *> fn bool! Path.walk(self, PathWalker w, void* data) { @@ -538,6 +583,35 @@ fn bool! Path.walk(self, PathWalker w, void* data) return false; } +def TraverseCallback = fn bool! (Path, bool is_dir, any data); + +<* + Walk the path recursively. TraverseCallback is run for every file and + directory found. Return true to abort the walk. + @require path.env == DEFAULT_ENV : "This method is only available on native paths" +*> +fn bool! traverse(Path path, TraverseCallback callback, any data) +{ + const PATH_MAX = 512; + @stack_mem(PATH_MAX; Allocator allocator) + { + Path abs = path.absolute(allocator)!; + PathList files = ls(allocator, abs)!; + foreach (f : files) + { + if (f.str_view() == "." || f.str_view() == "..") continue; + @stack_mem(128; Allocator smem) + { + f = abs.append(smem, f.str_view())!; + bool is_directory = is_dir(f); + if (callback(f, is_directory, data)!) return true; + if (is_directory && traverse(f, callback, data)!) return true; + }; + } + }; + return false; +} + fn String Path.str_view(self) @inline { return self.path_string; @@ -549,26 +623,19 @@ fn bool Path.has_suffix(self, String str) return self.str_view().ends_with(str); } -fn void Path.free_with_allocator(self, Allocator allocator) -{ - allocator::free(allocator, self.path_string.ptr); -} - +<* + @require self.allocator != null : "This Path should never be freed" +*> fn void Path.free(self) { - free(self.path_string.ptr); + allocator::free(self.allocator, self.path_string.ptr); } - fn usz! Path.to_format(&self, Formatter* formatter) @dynamic { return formatter.print(self.str_view()); } -fn String Path.to_new_string(&self, Allocator allocator = allocator::heap()) @dynamic -{ - return self.str_view().copy(allocator); -} const bool[256] RESERVED_PATH_CHAR_POSIX = { [0] = true, @@ -592,9 +659,29 @@ macro bool is_reserved_win32_path_char(char c) return RESERVED_PATH_CHAR_WIN32[c]; } -macro bool is_reserved_path_char(char c, PathEnv path_env = DEFAULT_PATH_ENV) +macro bool is_reserved_path_char(char c, PathEnv path_env = DEFAULT_ENV) { return path_env == PathEnv.WIN32 ? RESERVED_PATH_CHAR_WIN32[c] : RESERVED_PATH_CHAR_POSIX[c]; -} \ No newline at end of file +} +fn bool! _mkdir(Path path, bool recursive = false, MkdirPermissions permissions = NORMAL) @private +{ + if (!path.path_string.len) return PathResult.INVALID_PATH?; + if (is_dir(path)) return false; + if (exists(path)) return IoError.FILE_NOT_DIR?; + + if (recursive) + { + if (try parent = path.parent()) mkdir(parent, true, permissions)!; + } + if (!is_dir(path.parent()) ?? false) return IoError.CANNOT_READ_DIR?; + + return os::native_mkdir(path, permissions); +} + +fn bool! _rmdir(Path path) @private +{ + if (!path.path_string.len) return PathResult.INVALID_PATH?; + return os::native_rmdir(path); +} diff --git a/nix/default.nix b/nix/default.nix index c7dc61f9d..47b30b181 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -61,7 +61,7 @@ in llvmPackages.stdenv.mkDerivation (finalAttrs: { checkPhase = '' runHook preCheck ( cd ../resources/testproject; ../../build/c3c build --trust=full ) - ( cd ../test; ../build/c3c compile-run -O1 src/test_suite_runner.c3 --enable-new-generics -- ../build/c3c test_suite ) + ( cd ../test; ../build/c3c compile-run -O1 src/test_suite_runner.c3 --stdlib ../lib7 --enable-new-generics -- ../build/c3c test_suite ) runHook postCheck ''; diff --git a/releasenotes.md b/releasenotes.md index 9f13d406d..853509b15 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -23,6 +23,7 @@ - Aliases are now correctly handled as if they were variables/functions in regards to namespacing and accept `@builtin`. - Correctly handle in/out when interacting with inout. - Don't delete .o files not produced by the compiler. +- Fix optional jumps in expression lists, #1942. ### Stdlib changes diff --git a/src/compiler/context.c b/src/compiler/context.c index 7ffe0f705..104f2f23f 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -30,7 +30,7 @@ static inline bool create_module_or_check_name(CompilationUnit *unit, Path *modu if (!module->is_generic) goto DONE; if (vec_size(parameters) != vec_size(module->parameters)) { - PRINT_ERROR_AT(module_name, "The parameter declarations of the generic module '%s' don't match.", module->name); + PRINT_ERROR_AT(module_name, "The parameter declarations of the generic module '%s' don't match.", module_name->module); SEMA_NOTE(module->name, "A different definition can be found here."); return false; } @@ -39,7 +39,7 @@ static inline bool create_module_or_check_name(CompilationUnit *unit, Path *modu bool is_type = str_is_type(name); if (is_type != str_is_type(module->parameters[idx])) { - PRINT_ERROR_AT(module_name, "The parameter declarations of the generic module '%s' don't match.", module->name); + PRINT_ERROR_AT(module_name, "The parameter declarations of the generic module '%s' don't match.", module_name->module); SEMA_NOTE(module->name, "The other definition is here."); return false; } diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 91ad9767b..497d6e4a2 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -5876,10 +5876,15 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr static inline void llvm_emit_expression_list_expr(GenContext *c, BEValue *be_value, Expr *expr) { - FOREACH(Expr *, e, expr->expression_list) + Expr **list = expr->expression_list; + unsigned count = vec_size(list); + assert(count); + unsigned last = count - 1; + for (unsigned i = 0; i < last; i++) { - llvm_emit_expr(c, be_value, e); + llvm_emit_ignored_expr(c, list[i]); } + llvm_emit_expr(c, be_value, list[last]); } static inline void llvm_emit_return_block(GenContext *c, BEValue *be_value, Type *type, AstId current, BlockExit **block_exit) diff --git a/test/src/test_suite_runner.c3 b/test/src/test_suite_runner.c3 index 39e795167..ecf5ffd1e 100644 --- a/test/src/test_suite_runner.c3 +++ b/test/src/test_suite_runner.c3 @@ -21,14 +21,14 @@ fn void main(String[] args) print_to_file = !io::stdout().isatty(); // Retain our current path. - start_cwd = path::temp_cwd()!!; + start_cwd = path::tcwd()!!; // Create our test path, note that this prevents us from doing tests in parallell - test_dir = start_cwd.temp_append("_c3test_")!!; + test_dir = start_cwd.tappend("_c3test_")!!; defer (void)path::rmtree(test_dir); // Find the compiler - Path! path = start_cwd.temp_append(args[1]); + Path! path = start_cwd.tappend(args[1]); if (catch path) arg_error_exit(appname, "Invalid compiler path: %s", args[1]); // Is it a valid file? if (!path::is_file(path)) @@ -58,7 +58,7 @@ fn void main(String[] args) { error_exit(appname, "Stdlib directory '%s' cannot be found.", stdlib); } - stdlib = start_cwd.temp_append(stdlib).str_view()!!; + stdlib = start_cwd.tappend(stdlib).str_view()!!; default: arg_error_exit(appname, "Unknown option '%s'.", args[i]); } @@ -66,7 +66,7 @@ fn void main(String[] args) if (only_skipped && args[3] != "-s" && args[3] != "--skipped") usage(appname); // Get the directory or file to test - Path! file = path::temp_new(args[2]); + Path! file = args[2].to_tpath(); if (catch file) arg_error_exit(appname, "Invalid path: '%s'.", args[2]); // Now just run all tests recursively. @@ -129,17 +129,14 @@ fn void RunFile.add_line(&self, String line) fn RunFile*! create_input_file(String filename) { - File file = file::open_path(test_dir.temp_append(filename), "wb")!; + File file = file::open_path(test_dir.tappend(filename), "wb")!; RunFile *run_file = mem::temp_new(RunFile, { .name = filename, .file = file, .is_output = false }); - run_file.warnings.temp_init(); - run_file.errors.temp_init(); return run_file; } fn RunFile*! create_output_file(String filename) { RunFile *run_file = mem::temp_new(RunFile, { .name = filename, .is_output = true }); - run_file.expected_lines.temp_init(); return run_file; } @@ -168,13 +165,13 @@ fn bool check_line(RunSettings* settings, String type, String file, String line_ int line = line_str.to_int()!!; // Get the base name - String basename = path::temp_new(file).basename()!!; + String basename = file.file_tbasename()!!; // Loop through our input files (usually only 1!) foreach (f : settings.input_files) { if (f.name != basename) continue; - List{Error}* list; + List {Error}* list; switch (type) { case "Error": @@ -232,7 +229,7 @@ fn bool parse_result(DString out, RunSettings settings) io::printn("FAILED\n\n Unexpected compilation errors:"); io::printn(" ------------------------------"); } - io::printf(" %d. %s at %s:%s: ", ++errors, parts[0], path::temp_new(parts[1]).basename()!!, parts[2]); + io::printf(" %d. %s at %s:%s: ", ++errors, parts[0], parts[1].file_tbasename()!!, parts[2]); io::printfn(`"%s"`, parts[4]); success = false; } @@ -389,9 +386,6 @@ fn void test_file(Path file_path) } defer (void)f.close(); RunSettings settings; - settings.opts.temp_init(); - settings.input_files.temp_init(); - settings.output_files.temp_init(); settings.current_file = create_input_file(file_path.basename()[..^(single ? 4 : 5)].tconcat(".c3"))!!; settings.input_files.push(settings.current_file); int line_no = 1; @@ -413,7 +407,6 @@ fn void test_file(Path file_path) // Construct the compile line List{String} cmdline; - cmdline.temp_init(); cmdline.push(compiler_path.str_view()); cmdline.push("compile-only"); cmdline.push("--test"); @@ -448,7 +441,7 @@ fn void test_file(Path file_path) SubProcess compilation = process::create(cmdline.array_view(), { .search_user_path, .no_window, .inherit_environment })!!; defer compilation.destroy(); CInt result = compilation.join()!!; - DString out = dstring::temp_new(); + DString out; io::copy_to(&&compilation.stderr(), &out)!!; if (result != 0 && result != 1) { @@ -501,12 +494,12 @@ fn void test_file(Path file_path) fn void! test_path(Path file_path) { (void)path::chdir(start_cwd); - foreach (file : path::temp_ls(file_path)!!) + foreach (file : path::ls(tmem(), file_path)!!) { @pool() { (void)path::chdir(start_cwd); - file = file_path.temp_append(file.str_view())!; + file = file_path.tappend(file.str_view())!; switch { case path::is_dir(file): diff --git a/test/test_suite/expressions/incdec_overload.c3t b/test/test_suite/expressions/incdec_overload.c3t index fefc8c27b..6d066eb8f 100644 --- a/test/test_suite/expressions/incdec_overload.c3t +++ b/test/test_suite/expressions/incdec_overload.c3t @@ -25,11 +25,11 @@ entry: %retparam = alloca i32, align 4 %.anon1 = alloca i32, align 4 %anon.f2 = alloca i64, align 8 - %.anon18 = alloca i32, align 4 - %anon.f19 = alloca i64, align 8 - %retparam20 = alloca i32, align 4 - %.anon27 = alloca i32, align 4 - %anon.f28 = alloca i64, align 8 + %.anon15 = alloca i32, align 4 + %anon.f16 = alloca i64, align 8 + %retparam17 = alloca i32, align 4 + %.anon22 = alloca i32, align 4 + %anon.f23 = alloca i64, align 8 %0 = call i8 @"std_collections_map$int$int$.HashMap.set"(ptr @test.m, i32 3, i32 100) %1 = call i64 @"std_collections_map$int$int$.HashMap.get"(ptr %retparam, ptr @test.m, i32 3) %not_err = icmp eq i64 %1, 0 @@ -38,7 +38,7 @@ entry: assign_optional: ; preds = %entry store i64 %1, ptr %anon.f, align 8 - br label %optional_assign_jump + br label %after_assign after_check: ; preds = %entry %3 = load i32, ptr %retparam, align 4 @@ -46,12 +46,7 @@ after_check: ; preds = %entry store i64 0, ptr %anon.f, align 8 br label %after_assign -optional_assign_jump: ; preds = %assign_optional - %reload_err = load i64, ptr %anon.f, align 8 - store i64 %reload_err, ptr %x.f, align 8 - br label %after_assign17 - -after_assign: ; preds = %after_check +after_assign: ; preds = %after_check, %assign_optional %optval = load i64, ptr %anon.f, align 8 %not_err3 = icmp eq i64 %optval, 0 %4 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) @@ -59,7 +54,7 @@ after_assign: ; preds = %after_check assign_optional4: ; preds = %after_assign store i64 %optval, ptr %anon.f2, align 8 - br label %optional_assign_jump6 + br label %after_assign6 after_check5: ; preds = %after_assign %5 = load i32, ptr %.anon, align 4 @@ -67,113 +62,96 @@ after_check5: ; preds = %after_assign store i32 %sub, ptr %.anon, align 4 store i32 %5, ptr %.anon1, align 4 store i64 0, ptr %anon.f2, align 8 - br label %after_assign8 + br label %after_assign6 -optional_assign_jump6: ; preds = %assign_optional4 - %reload_err7 = load i64, ptr %anon.f2, align 8 - store i64 %reload_err7, ptr %x.f, align 8 - br label %after_assign17 +after_assign6: ; preds = %after_check5, %assign_optional4 + %optval7 = load i64, ptr %anon.f, align 8 + %not_err8 = icmp eq i64 %optval7, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err8, i1 true) + br i1 %6, label %after_check9, label %voiderr -after_assign8: ; preds = %after_check5 - %optval9 = load i64, ptr %anon.f, align 8 - %not_err10 = icmp eq i64 %optval9, 0 - %6 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) - br i1 %6, label %after_check12, label %assign_optional11 - -assign_optional11: ; preds = %after_assign8 - store i64 %optval9, ptr %x.f, align 8 - br label %after_assign17 - -after_check12: ; preds = %after_assign8 +after_check9: ; preds = %after_assign6 %7 = load i32, ptr %.anon, align 4 %8 = call i8 @"std_collections_map$int$int$.HashMap.set"(ptr @test.m, i32 3, i32 %7) - %optval13 = load i64, ptr %anon.f2, align 8 - %not_err14 = icmp eq i64 %optval13, 0 - %9 = call i1 @llvm.expect.i1(i1 %not_err14, i1 true) - br i1 %9, label %after_check16, label %assign_optional15 + br label %voiderr -assign_optional15: ; preds = %after_check12 - store i64 %optval13, ptr %x.f, align 8 - br label %after_assign17 +voiderr: ; preds = %after_check9, %after_assign6 + %optval10 = load i64, ptr %anon.f2, align 8 + %not_err11 = icmp eq i64 %optval10, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %9, label %after_check13, label %assign_optional12 -after_check16: ; preds = %after_check12 +assign_optional12: ; preds = %voiderr + store i64 %optval10, ptr %x.f, align 8 + br label %after_assign14 + +after_check13: ; preds = %voiderr %10 = load i32, ptr %.anon1, align 4 store i32 %10, ptr %x, align 4 store i64 0, ptr %x.f, align 8 - br label %after_assign17 + br label %after_assign14 -after_assign17: ; preds = %after_check16, %assign_optional15, %assign_optional11, %optional_assign_jump6, %optional_assign_jump - %11 = call i64 @"std_collections_map$int$int$.HashMap.get"(ptr %retparam20, ptr @test.m, i32 3) - %not_err21 = icmp eq i64 %11, 0 - %12 = call i1 @llvm.expect.i1(i1 %not_err21, i1 true) - br i1 %12, label %after_check23, label %assign_optional22 +after_assign14: ; preds = %after_check13, %assign_optional12 + %11 = call i64 @"std_collections_map$int$int$.HashMap.get"(ptr %retparam17, ptr @test.m, i32 3) + %not_err18 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err18, i1 true) + br i1 %12, label %after_check20, label %assign_optional19 -assign_optional22: ; preds = %after_assign17 - store i64 %11, ptr %anon.f19, align 8 - br label %optional_assign_jump24 +assign_optional19: ; preds = %after_assign14 + store i64 %11, ptr %anon.f16, align 8 + br label %after_assign21 -after_check23: ; preds = %after_assign17 - %13 = load i32, ptr %retparam20, align 4 - store i32 %13, ptr %.anon18, align 4 - store i64 0, ptr %anon.f19, align 8 - br label %after_assign26 +after_check20: ; preds = %after_assign14 + %13 = load i32, ptr %retparam17, align 4 + store i32 %13, ptr %.anon15, align 4 + store i64 0, ptr %anon.f16, align 8 + br label %after_assign21 -optional_assign_jump24: ; preds = %assign_optional22 - %reload_err25 = load i64, ptr %anon.f19, align 8 - store i64 %reload_err25, ptr %x.f, align 8 - br label %after_assign44 +after_assign21: ; preds = %after_check20, %assign_optional19 + %optval24 = load i64, ptr %anon.f16, align 8 + %not_err25 = icmp eq i64 %optval24, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err25, i1 true) + br i1 %14, label %after_check27, label %assign_optional26 -after_assign26: ; preds = %after_check23 - %optval29 = load i64, ptr %anon.f19, align 8 - %not_err30 = icmp eq i64 %optval29, 0 - %14 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) - br i1 %14, label %after_check32, label %assign_optional31 +assign_optional26: ; preds = %after_assign21 + store i64 %optval24, ptr %anon.f23, align 8 + br label %after_assign28 -assign_optional31: ; preds = %after_assign26 - store i64 %optval29, ptr %anon.f28, align 8 - br label %optional_assign_jump33 - -after_check32: ; preds = %after_assign26 - %15 = load i32, ptr %.anon18, align 4 +after_check27: ; preds = %after_assign21 + %15 = load i32, ptr %.anon15, align 4 %add = add i32 %15, 1 - store i32 %add, ptr %.anon18, align 4 - store i32 %add, ptr %.anon27, align 4 - store i64 0, ptr %anon.f28, align 8 - br label %after_assign35 + store i32 %add, ptr %.anon15, align 4 + store i32 %add, ptr %.anon22, align 4 + store i64 0, ptr %anon.f23, align 8 + br label %after_assign28 -optional_assign_jump33: ; preds = %assign_optional31 - %reload_err34 = load i64, ptr %anon.f28, align 8 - store i64 %reload_err34, ptr %x.f, align 8 - br label %after_assign44 +after_assign28: ; preds = %after_check27, %assign_optional26 + %optval29 = load i64, ptr %anon.f16, align 8 + %not_err30 = icmp eq i64 %optval29, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) + br i1 %16, label %after_check31, label %voiderr32 -after_assign35: ; preds = %after_check32 - %optval36 = load i64, ptr %anon.f19, align 8 - %not_err37 = icmp eq i64 %optval36, 0 - %16 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) - br i1 %16, label %after_check39, label %assign_optional38 - -assign_optional38: ; preds = %after_assign35 - store i64 %optval36, ptr %x.f, align 8 - br label %after_assign44 - -after_check39: ; preds = %after_assign35 - %17 = load i32, ptr %.anon18, align 4 +after_check31: ; preds = %after_assign28 + %17 = load i32, ptr %.anon15, align 4 %18 = call i8 @"std_collections_map$int$int$.HashMap.set"(ptr @test.m, i32 3, i32 %17) - %optval40 = load i64, ptr %anon.f28, align 8 - %not_err41 = icmp eq i64 %optval40, 0 - %19 = call i1 @llvm.expect.i1(i1 %not_err41, i1 true) - br i1 %19, label %after_check43, label %assign_optional42 + br label %voiderr32 -assign_optional42: ; preds = %after_check39 - store i64 %optval40, ptr %x.f, align 8 - br label %after_assign44 +voiderr32: ; preds = %after_check31, %after_assign28 + %optval33 = load i64, ptr %anon.f23, align 8 + %not_err34 = icmp eq i64 %optval33, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err34, i1 true) + br i1 %19, label %after_check36, label %assign_optional35 -after_check43: ; preds = %after_check39 - %20 = load i32, ptr %.anon27, align 4 +assign_optional35: ; preds = %voiderr32 + store i64 %optval33, ptr %x.f, align 8 + br label %after_assign37 + +after_check36: ; preds = %voiderr32 + %20 = load i32, ptr %.anon22, align 4 store i32 %20, ptr %x, align 4 store i64 0, ptr %x.f, align 8 - br label %after_assign44 + br label %after_assign37 -after_assign44: ; preds = %after_check43, %assign_optional42, %assign_optional38, %optional_assign_jump33, %optional_assign_jump24 +after_assign37: ; preds = %after_check36, %assign_optional35 ret void } diff --git a/test/test_suite7/errors/optional_expr_list.c3t b/test/test_suite7/errors/optional_expr_list.c3t new file mode 100644 index 000000000..40fe7516f --- /dev/null +++ b/test/test_suite7/errors/optional_expr_list.c3t @@ -0,0 +1,60 @@ +// #target: macos-x64 +module test; + +fn void main() +{ + int! n; + for (n += 1, 1 + 1; false;); +} + +/* #expect: test.ll + + +; ModuleID = 'test' +source_filename = "test" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.13.0" + +; Function Attrs: nounwind uwtable +define void @test.main() #0 { +entry: + %n = alloca i32, align 4 + %n.f = alloca i64, align 8 + store i64 0, ptr %n.f, align 8 + store i32 0, ptr %n, align 4 + %optval = load i64, ptr %n.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %voiderr + +after_check: ; preds = %entry + %1 = load i32, ptr %n, align 4 + %add = add i32 %1, 1 + store i32 %add, ptr %n, align 4 + br label %voiderr + +voiderr: ; preds = %after_check, %entry + ret void +} + +; Function Attrs: nounwind uwtable +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare i1 @llvm.expect.i1(i1, i1) #1 + +attributes #0 = { nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { nocallback nofree nosync nounwind willreturn memory(none) } + +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5} + +!0 = !{i32 2, !"Dwarf Version", i32 4} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = !{i32 2, !"wchar_size", i32 4} +!3 = !{i32 4, !"PIC Level", i32 2} +!4 = !{i32 1, !"uwtable", i32 2} +!5 = !{i32 2, !"frame-pointer", i32 2} diff --git a/test/test_suite7/expressions/incdec_overload.c3t b/test/test_suite7/expressions/incdec_overload.c3t index fefc8c27b..1ebc40b92 100644 --- a/test/test_suite7/expressions/incdec_overload.c3t +++ b/test/test_suite7/expressions/incdec_overload.c3t @@ -2,7 +2,7 @@ module test; import std; -def Abc = HashMap(); +def Abc = HashMap{int, int}; Abc m; fn void main() { @@ -25,11 +25,11 @@ entry: %retparam = alloca i32, align 4 %.anon1 = alloca i32, align 4 %anon.f2 = alloca i64, align 8 - %.anon18 = alloca i32, align 4 - %anon.f19 = alloca i64, align 8 - %retparam20 = alloca i32, align 4 - %.anon27 = alloca i32, align 4 - %anon.f28 = alloca i64, align 8 + %.anon15 = alloca i32, align 4 + %anon.f16 = alloca i64, align 8 + %retparam17 = alloca i32, align 4 + %.anon22 = alloca i32, align 4 + %anon.f23 = alloca i64, align 8 %0 = call i8 @"std_collections_map$int$int$.HashMap.set"(ptr @test.m, i32 3, i32 100) %1 = call i64 @"std_collections_map$int$int$.HashMap.get"(ptr %retparam, ptr @test.m, i32 3) %not_err = icmp eq i64 %1, 0 @@ -38,7 +38,7 @@ entry: assign_optional: ; preds = %entry store i64 %1, ptr %anon.f, align 8 - br label %optional_assign_jump + br label %after_assign after_check: ; preds = %entry %3 = load i32, ptr %retparam, align 4 @@ -46,12 +46,7 @@ after_check: ; preds = %entry store i64 0, ptr %anon.f, align 8 br label %after_assign -optional_assign_jump: ; preds = %assign_optional - %reload_err = load i64, ptr %anon.f, align 8 - store i64 %reload_err, ptr %x.f, align 8 - br label %after_assign17 - -after_assign: ; preds = %after_check +after_assign: ; preds = %after_check, %assign_optional %optval = load i64, ptr %anon.f, align 8 %not_err3 = icmp eq i64 %optval, 0 %4 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) @@ -59,7 +54,7 @@ after_assign: ; preds = %after_check assign_optional4: ; preds = %after_assign store i64 %optval, ptr %anon.f2, align 8 - br label %optional_assign_jump6 + br label %after_assign6 after_check5: ; preds = %after_assign %5 = load i32, ptr %.anon, align 4 @@ -67,113 +62,96 @@ after_check5: ; preds = %after_assign store i32 %sub, ptr %.anon, align 4 store i32 %5, ptr %.anon1, align 4 store i64 0, ptr %anon.f2, align 8 - br label %after_assign8 + br label %after_assign6 -optional_assign_jump6: ; preds = %assign_optional4 - %reload_err7 = load i64, ptr %anon.f2, align 8 - store i64 %reload_err7, ptr %x.f, align 8 - br label %after_assign17 +after_assign6: ; preds = %after_check5, %assign_optional4 + %optval7 = load i64, ptr %anon.f, align 8 + %not_err8 = icmp eq i64 %optval7, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err8, i1 true) + br i1 %6, label %after_check9, label %voiderr -after_assign8: ; preds = %after_check5 - %optval9 = load i64, ptr %anon.f, align 8 - %not_err10 = icmp eq i64 %optval9, 0 - %6 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) - br i1 %6, label %after_check12, label %assign_optional11 - -assign_optional11: ; preds = %after_assign8 - store i64 %optval9, ptr %x.f, align 8 - br label %after_assign17 - -after_check12: ; preds = %after_assign8 +after_check9: ; preds = %after_assign6 %7 = load i32, ptr %.anon, align 4 %8 = call i8 @"std_collections_map$int$int$.HashMap.set"(ptr @test.m, i32 3, i32 %7) - %optval13 = load i64, ptr %anon.f2, align 8 - %not_err14 = icmp eq i64 %optval13, 0 - %9 = call i1 @llvm.expect.i1(i1 %not_err14, i1 true) - br i1 %9, label %after_check16, label %assign_optional15 + br label %voiderr -assign_optional15: ; preds = %after_check12 - store i64 %optval13, ptr %x.f, align 8 - br label %after_assign17 +voiderr: ; preds = %after_check9, %after_assign6 + %optval10 = load i64, ptr %anon.f2, align 8 + %not_err11 = icmp eq i64 %optval10, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %9, label %after_check13, label %assign_optional12 -after_check16: ; preds = %after_check12 +assign_optional12: ; preds = %voiderr + store i64 %optval10, ptr %x.f, align 8 + br label %after_assign14 + +after_check13: ; preds = %voiderr %10 = load i32, ptr %.anon1, align 4 store i32 %10, ptr %x, align 4 store i64 0, ptr %x.f, align 8 - br label %after_assign17 + br label %after_assign14 -after_assign17: ; preds = %after_check16, %assign_optional15, %assign_optional11, %optional_assign_jump6, %optional_assign_jump - %11 = call i64 @"std_collections_map$int$int$.HashMap.get"(ptr %retparam20, ptr @test.m, i32 3) - %not_err21 = icmp eq i64 %11, 0 - %12 = call i1 @llvm.expect.i1(i1 %not_err21, i1 true) - br i1 %12, label %after_check23, label %assign_optional22 +after_assign14: ; preds = %after_check13, %assign_optional12 + %11 = call i64 @"std_collections_map$int$int$.HashMap.get"(ptr %retparam17, ptr @test.m, i32 3) + %not_err18 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err18, i1 true) + br i1 %12, label %after_check20, label %assign_optional19 -assign_optional22: ; preds = %after_assign17 - store i64 %11, ptr %anon.f19, align 8 - br label %optional_assign_jump24 +assign_optional19: ; preds = %after_assign14 + store i64 %11, ptr %anon.f16, align 8 + br label %after_assign21 -after_check23: ; preds = %after_assign17 - %13 = load i32, ptr %retparam20, align 4 - store i32 %13, ptr %.anon18, align 4 - store i64 0, ptr %anon.f19, align 8 - br label %after_assign26 +after_check20: ; preds = %after_assign14 + %13 = load i32, ptr %retparam17, align 4 + store i32 %13, ptr %.anon15, align 4 + store i64 0, ptr %anon.f16, align 8 + br label %after_assign21 -optional_assign_jump24: ; preds = %assign_optional22 - %reload_err25 = load i64, ptr %anon.f19, align 8 - store i64 %reload_err25, ptr %x.f, align 8 - br label %after_assign44 +after_assign21: ; preds = %after_check20, %assign_optional19 + %optval24 = load i64, ptr %anon.f16, align 8 + %not_err25 = icmp eq i64 %optval24, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err25, i1 true) + br i1 %14, label %after_check27, label %assign_optional26 -after_assign26: ; preds = %after_check23 - %optval29 = load i64, ptr %anon.f19, align 8 - %not_err30 = icmp eq i64 %optval29, 0 - %14 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) - br i1 %14, label %after_check32, label %assign_optional31 +assign_optional26: ; preds = %after_assign21 + store i64 %optval24, ptr %anon.f23, align 8 + br label %after_assign28 -assign_optional31: ; preds = %after_assign26 - store i64 %optval29, ptr %anon.f28, align 8 - br label %optional_assign_jump33 - -after_check32: ; preds = %after_assign26 - %15 = load i32, ptr %.anon18, align 4 +after_check27: ; preds = %after_assign21 + %15 = load i32, ptr %.anon15, align 4 %add = add i32 %15, 1 - store i32 %add, ptr %.anon18, align 4 - store i32 %add, ptr %.anon27, align 4 - store i64 0, ptr %anon.f28, align 8 - br label %after_assign35 + store i32 %add, ptr %.anon15, align 4 + store i32 %add, ptr %.anon22, align 4 + store i64 0, ptr %anon.f23, align 8 + br label %after_assign28 -optional_assign_jump33: ; preds = %assign_optional31 - %reload_err34 = load i64, ptr %anon.f28, align 8 - store i64 %reload_err34, ptr %x.f, align 8 - br label %after_assign44 +after_assign28: ; preds = %after_check27, %assign_optional26 + %optval29 = load i64, ptr %anon.f16, align 8 + %not_err30 = icmp eq i64 %optval29, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) + br i1 %16, label %after_check31, label %voiderr32 -after_assign35: ; preds = %after_check32 - %optval36 = load i64, ptr %anon.f19, align 8 - %not_err37 = icmp eq i64 %optval36, 0 - %16 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) - br i1 %16, label %after_check39, label %assign_optional38 - -assign_optional38: ; preds = %after_assign35 - store i64 %optval36, ptr %x.f, align 8 - br label %after_assign44 - -after_check39: ; preds = %after_assign35 - %17 = load i32, ptr %.anon18, align 4 +after_check31: ; preds = %after_assign28 + %17 = load i32, ptr %.anon15, align 4 %18 = call i8 @"std_collections_map$int$int$.HashMap.set"(ptr @test.m, i32 3, i32 %17) - %optval40 = load i64, ptr %anon.f28, align 8 - %not_err41 = icmp eq i64 %optval40, 0 - %19 = call i1 @llvm.expect.i1(i1 %not_err41, i1 true) - br i1 %19, label %after_check43, label %assign_optional42 + br label %voiderr32 -assign_optional42: ; preds = %after_check39 - store i64 %optval40, ptr %x.f, align 8 - br label %after_assign44 +voiderr32: ; preds = %after_check31, %after_assign28 + %optval33 = load i64, ptr %anon.f23, align 8 + %not_err34 = icmp eq i64 %optval33, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err34, i1 true) + br i1 %19, label %after_check36, label %assign_optional35 -after_check43: ; preds = %after_check39 - %20 = load i32, ptr %.anon27, align 4 +assign_optional35: ; preds = %voiderr32 + store i64 %optval33, ptr %x.f, align 8 + br label %after_assign37 + +after_check36: ; preds = %voiderr32 + %20 = load i32, ptr %.anon22, align 4 store i32 %20, ptr %x, align 4 store i64 0, ptr %x.f, align 8 - br label %after_assign44 + br label %after_assign37 -after_assign44: ; preds = %after_check43, %assign_optional42, %assign_optional38, %optional_assign_jump33, %optional_assign_jump24 +after_assign37: ; preds = %after_check36, %assign_optional35 ret void }