diff --git a/lib/std/core/str.c3 b/lib/std/core/str.c3 index d99fd396e..0084db41d 100644 --- a/lib/std/core/str.c3 +++ b/lib/std/core/str.c3 @@ -162,7 +162,7 @@ fn char[][] split(char[] s, char[] needle, Allocator* allocator = mem::current_a if (try index) { res = s[:index]; - s = s[index + 1..]; + s = s[index + needle.len..]; } else { @@ -192,7 +192,7 @@ fn usz! index_of(char[] s, char[] needle) { if (!match) index_start = i; match++; - if (match == needed) return i; + if (match == needed) return index_start; search = needle[match]; continue; } @@ -214,6 +214,15 @@ fn ZString copy_zstring(char[] s, Allocator* allocator = mem::current_allocator( return (ZString)str; } +fn char[] copyz(char[] s, Allocator* allocator = mem::current_allocator()) +{ + usz len = s.len; + char* str = allocator.alloc(len + 1)!!; + mem::copy(str, s.ptr, len); + str[len] = 0; + return str[:len]; +} + fn ZString tcopy_zstring(char[] s) { return copy_zstring(s, mem::temp_allocator()); @@ -317,10 +326,15 @@ fn char[] concat(char[] s1, char[] s2) return str[..full_len]; } -fn usz ZString.len(ZString *str) +fn char[] ZString.as_str(ZString str) +{ + return ((char*)str)[:str.len()]; +} + +fn usz ZString.len(ZString str) { usz len = 0; - char* ptr = (char*)*str; + char* ptr = (char*)str; while (char c = ptr++[0]) { if (c & 0xC0 != 0x80) len++; diff --git a/lib/std/io/dir.c3 b/lib/std/io/dir.c3 index 82bf287d9..c75fb0a94 100644 --- a/lib/std/io/dir.c3 +++ b/lib/std/io/dir.c3 @@ -1,5 +1,5 @@ module std::io::dir; - +import std::io::os; // In progress. define Path = distinct char[]; @@ -11,6 +11,16 @@ fault PathResult INVALID_PATH } +fn char[]! getcwd(Allocator* allocator = mem::default_allocator()) +{ + return os::getcwd(allocator); +} + +fn char[]! tgetcwd() +{ + return getcwd(mem::temp_allocator()) @inline; +} + macro bool is_separator(char c) { $if (USE_WIN32_FILESYSTEM): diff --git a/lib/std/io/os/getcwd.c3 b/lib/std/io/os/getcwd.c3 new file mode 100644 index 000000000..6a38da8a4 --- /dev/null +++ b/lib/std/io/os/getcwd.c3 @@ -0,0 +1,47 @@ +module std::io::os; +import libc; + +$if (env::OS_TYPE == OsType.WIN32): + +extern fn Char16* _wgetcwd(Char16* buffer, int maxlen); +extern fn usz wcslen(Char16* str); + +macro char[]! getcwd(Allocator* allocator = mem::default_allocator()) +{ + const DEFAULT_BUFFER = 256; + Char16[DEFAULT_BUFFER] buffer; + Char16 *res = _wgetcwd(&buffer, DEFAULT_BUFFER); + bool free = false; + defer if (free) libc::free(res); + if (!res) + { + if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR!; + res = _wgetcwd(null, 0); + free = true; + } + Char16[] str16 = res[:wcslen(res)]; + return str::utf16to8(str16, allocator); +} + +$else: + +extern fn ZString _getcwd(char* pwd, usz len) @extname("getcwd"); +macro char[]! getcwd(Allocator* allocator = mem::default_allocator()) +{ + const usz DEFAULT_BUFFER = 256; + char[DEFAULT_BUFFER] buffer; + ZString res = _getcwd(&buffer, DEFAULT_BUFFER); + bool free = false; + if (!res) + { + // Improve error + if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR!; + res = _getcwd(null, 0); + free = true; + } + defer if (free) libc::free((void*)res); + char[] copy = str::copyz(res.as_str(), allocator); + return copy; +} + +$endif; \ No newline at end of file diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 62d682d5b..dcec81f8a 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -3939,8 +3939,7 @@ static inline void llvm_emit_force_unwrap_expr(GenContext *c, BEValue *be_value, { // TODO, we should add info about the error. SourceSpan loc = expr->span; - File *file = source_file_by_id(loc.file_id); - llvm_emit_panic(c, "Runtime error force unwrap!", file->name, c->cur_func.name, loc.row ? loc.row : 1); + llvm_emit_panic(c, "Runtime error force unwrap!", loc); LLVMBuildUnreachable(c->builder); c->current_block = NULL; c->current_block_is_target = false; @@ -5755,8 +5754,7 @@ static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *ex llvm_emit_cond_br(c, &check, exit, next); llvm_emit_block(c, next); } - File *file = source_file_by_id(expr->span.file_id); - llvm_emit_panic(c, "Attempted to access 'inner' on non composite type", file->name, c->cur_func.name, expr->span.row); + llvm_emit_panic(c, "Attempted to access 'inner' on non composite type", expr->span); c->current_block = NULL; c->current_block_is_target = false; LLVMBuildUnreachable(c->builder); @@ -5788,8 +5786,7 @@ static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *ex llvm_emit_cond_br(c, &check, exit, next); llvm_emit_block(c, next); } - File *file = source_file_by_id(expr->span.file_id); - llvm_emit_panic(c, "Attempted to access 'names' on non enum/fault type.", file->name, c->cur_func.name, expr->span.row); + llvm_emit_panic(c, "Attempted to access 'names' on non enum/fault type.", expr->span); c->current_block = NULL; c->current_block_is_target = false; LLVMBuildUnreachable(c->builder); @@ -5825,8 +5822,7 @@ static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *ex llvm_emit_cond_br(c, &check, exit, next); llvm_emit_block(c, next); } - File *file = source_file_by_id(expr->span.file_id); - llvm_emit_panic(c, "Attempted to access 'len' on non array type", file->name, c->cur_func.name, expr->span.row); + llvm_emit_panic(c, "Attempted to access 'len' on non array type", expr->span); c->current_block = NULL; c->current_block_is_target = false; LLVMBuildUnreachable(c->builder); diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 9ed9dadf5..d77dc099d 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -472,6 +472,7 @@ void llvm_emit_body(GenContext *c, LLVMValueRef function, const char *module_nam if (emit_debug) { llvm_debug_scope_push(c, c->debug.function); + EMIT_LOC(c, body); if (c->debug.enable_stacktrace) { LLVMTypeRef slot_type = c->debug.stack_type; diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 96db89d81..e04d4c9d9 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -437,7 +437,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr); void llvm_emit_stmt(GenContext *c, Ast *ast); void llvm_emit_panic_on_true(GenContext *c, LLVMValueRef value, const char *panic_name, SourceSpan loc); void llvm_emit_panic_if_true(GenContext *c, BEValue *value, const char *panic_name, SourceSpan loc); -void llvm_emit_panic(GenContext *c, const char *message, const char *file, const char *func, unsigned line); +void llvm_emit_panic(GenContext *c, const char *message, SourceSpan loc); void llvm_emit_subarray_len(GenContext *context, BEValue *subarray, BEValue *len); void llvm_emit_subarray_pointer(GenContext *context, BEValue *subarray, BEValue *pointer); void llvm_emit_compound_stmt(GenContext *c, Ast *ast); diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index 67ccaa84b..b076408ea 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -254,7 +254,9 @@ static inline void llvm_emit_block_exit_return(GenContext *c, Ast *ast) POP_OPT(); - llvm_emit_statement_chain(c, ast->return_stmt.cleanup); + AstId cleanup = ast->return_stmt.cleanup; + AstId err_cleanup = err_cleanup_block && cleanup ? astid(copy_ast_defer(astptr(cleanup))) : 0; + llvm_emit_statement_chain(c, cleanup); if (exit->block_return_out && return_value.value) { llvm_store_to_ptr_aligned(c, exit->block_return_out, &return_value, type_alloca_alignment(return_value.type)); @@ -264,7 +266,7 @@ static inline void llvm_emit_block_exit_return(GenContext *c, Ast *ast) { llvm_emit_br(c, exit->block_return_exit); llvm_emit_block(c, err_cleanup_block); - llvm_emit_statement_chain(c, ast->return_stmt.cleanup); + llvm_emit_statement_chain(c, err_cleanup); llvm_emit_jmp(c, exit->block_failable_exit); } else @@ -465,9 +467,8 @@ void llvm_emit_for_stmt(GenContext *c, Ast *ast) if (loop == LOOP_INFINITE) { SourceSpan loc = ast->span; - File *file = source_file_by_id(loc.file_id); - llvm_emit_panic(c, "Infinite loop found", file->name, c->cur_func.name, loc.row ? loc.row : 1); + llvm_emit_panic(c, "Infinite loop found", loc); LLVMBuildUnreachable(c->builder); LLVMBasicBlockRef block = llvm_basic_block_new(c, "unreachable_block"); c->current_block = NULL; @@ -1000,8 +1001,7 @@ static inline void llvm_emit_assert_stmt(GenContext *c, Ast *ast) { error = "Assert violation"; } - File *file = source_file_by_id(loc.file_id); - llvm_emit_panic(c, error, file->name, c->cur_func.name, loc.row ? loc.row : 1); + llvm_emit_panic(c, error, loc); llvm_emit_br(c, on_ok); llvm_emit_block(c, on_ok); } @@ -1274,13 +1274,16 @@ LLVMValueRef llvm_emit_zstring_named(GenContext *c, const char *str, const char } -void llvm_emit_panic(GenContext *c, const char *message, const char *file, const char *func, unsigned line) +void llvm_emit_panic(GenContext *c, const char *message, SourceSpan loc) { + File *file = source_file_by_id(loc.file_id); + + if (c->debug.builder) llvm_emit_debug_location(c, loc); if (c->debug.stack_slot_row) { llvm_store_to_ptr_raw_aligned(c, c->debug.stack_slot_row, - llvm_const_int(c, type_uint, line), + llvm_const_int(c, type_uint, loc.row ? loc.row : 1), type_abi_alignment(type_uint)); } @@ -1293,9 +1296,9 @@ void llvm_emit_panic(GenContext *c, const char *message, const char *file, const LLVMValueRef args[4] = { llvm_emit_string_const(c, message, ".panic_msg"), - llvm_emit_string_const(c, file, ".file"), - llvm_emit_string_const(c, func, ".func"), - llvm_const_int(c, type_uint, line) + llvm_emit_string_const(c, file->name, ".file"), + llvm_emit_string_const(c, c->cur_func.name, ".func"), + llvm_const_int(c, type_uint, loc.row) }; FunctionPrototype *prototype = panic_var->type->canonical->pointer->function.prototype; LLVMValueRef actual_args[16]; @@ -1314,6 +1317,7 @@ void llvm_emit_panic(GenContext *c, const char *message, const char *file, const llvm_value_rvalue(c, &val); BEValue res; + if (c->debug.builder) llvm_emit_debug_location(c, loc); llvm_emit_raw_call(c, &res, prototype, llvm_func_type(c, prototype), val.value, actual_args, count, 0, NULL, false, NULL); } @@ -1330,22 +1334,20 @@ void llvm_emit_panic_if_true(GenContext *c, BEValue *value, const char *panic_na assert(llvm_value_is_bool(value)); llvm_emit_cond_br(c, value, panic_block, ok_block); llvm_emit_block(c, panic_block); - File *file = source_file_by_id(loc.file_id); - llvm_emit_panic(c, panic_name, file->name, c->cur_func.name, loc.row); + llvm_emit_panic(c, panic_name, loc); llvm_emit_br(c, ok_block); llvm_emit_block(c, ok_block); } void llvm_emit_panic_on_true(GenContext *c, LLVMValueRef value, const char *panic_name, SourceSpan loc) { - File *file = source_file_by_id(loc.file_id); LLVMBasicBlockRef panic_block = llvm_basic_block_new(c, "panic"); LLVMBasicBlockRef ok_block = llvm_basic_block_new(c, "checkok"); BEValue be_value; llvm_value_set_bool(&be_value, value); llvm_emit_cond_br(c, &be_value, panic_block, ok_block); llvm_emit_block(c, panic_block); - llvm_emit_panic(c, panic_name, file->name, c->cur_func.name, loc.row ? loc.row : 1); + llvm_emit_panic(c, panic_name, loc); llvm_emit_br(c, ok_block); llvm_emit_block(c, ok_block); } diff --git a/src/version.h b/src/version.h index 3a224ce1c..15ba9818f 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.3.115" \ No newline at end of file +#define COMPILER_VERSION "0.3.116" \ No newline at end of file