diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 2e7501b66..55d446c05 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -15,6 +15,7 @@ struct BuildContext { String command; + String out_filepath; String opt_flags; String llc_flags; String link_flags; diff --git a/src/gb/gb.h b/src/gb/gb.h index 0bf890948..c9db17a2a 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -6547,7 +6547,7 @@ gbString gb_string_make_length(gbAllocator a, void const *init_str, isize num_by header->allocator = a; header->length = num_bytes; header->capacity = num_bytes; - if (num_bytes && init_str) { + if (num_bytes > 0 && init_str) { gb_memcopy(str, init_str, num_bytes); } str[num_bytes] = '\0'; diff --git a/src/ir.cpp b/src/ir.cpp index 9613f7192..8622659e6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1655,7 +1655,7 @@ irValue *ir_find_or_generate_context_ptr(irProcedure *proc) { proc->curr_block = proc->blocks[0]; defer (proc->curr_block = tmp_block); - + irValue *c = ir_add_local_generated(proc, t_context); array_add(&proc->context_stack, c); ir_emit_store(proc, c, ir_emit_load(proc, proc->module->global_default_context)); @@ -7772,12 +7772,23 @@ bool ir_gen_init(irGen *s, Checker *c) { // s->module.generate_debug_info = false; String init_fullpath = c->parser->init_fullpath; - // TODO(bill): generate appropriate output name - int pos = cast(int)string_extension_position(init_fullpath); - int dir_pos = cast(int)string_extension_position(init_fullpath); - s->output_name = filename_from_path(init_fullpath); - s->output_base = make_string(init_fullpath.text, pos); - gbFileError err = gb_file_create(&s->output_file, gb_bprintf("%.*s.ll", LIT(s->output_base))); + + if (build_context.out_filepath.len == 0) { + s->output_name = filename_from_path(init_fullpath); + s->output_base = s->output_name; + } else { + s->output_name = build_context.out_filepath; + isize pos = string_extension_position(s->output_name); + if (pos < 0) { + s->output_base = s->output_name; + } else { + s->output_base = substring(s->output_name, 0, pos); + } + } + + gbString output_file_path = gb_string_make_length(heap_allocator(), s->output_base.text, s->output_base.len); + output_file_path = gb_string_appendc(output_file_path, ".ll"); + gbFileError err = gb_file_create(&s->output_file, output_file_path); if (err != gbFileError_None) { return false; } diff --git a/src/main.cpp b/src/main.cpp index 06f17fc92..d9249b40e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -202,6 +202,7 @@ bool string_is_valid_identifier(String str) { enum BuildFlagKind { BuildFlag_Invalid, + BuildFlag_OutFile, BuildFlag_OptimizationLevel, BuildFlag_ShowTimings, BuildFlag_ThreadCount, @@ -241,6 +242,7 @@ void add_flag(Array *build_flags, BuildFlagKind kind, String name, Bu bool parse_build_flags(Array args) { Array build_flags = {}; array_init(&build_flags, heap_allocator(), BuildFlag_COUNT); + add_flag(&build_flags, BuildFlag_OutFile, str_lit("out"), BuildFlagParam_String); add_flag(&build_flags, BuildFlag_OptimizationLevel, str_lit("opt"), BuildFlagParam_Integer); add_flag(&build_flags, BuildFlag_ShowTimings, str_lit("show-timings"), BuildFlagParam_None); add_flag(&build_flags, BuildFlag_ThreadCount, str_lit("thread-count"), BuildFlagParam_Integer); @@ -320,10 +322,17 @@ bool parse_build_flags(Array args) { case BuildFlagParam_Float: value = exact_value_float_from_string(param); break; - case BuildFlagParam_String: + case BuildFlagParam_String: { value = exact_value_string(param); + if (value.kind == ExactValue_String) { + String s = value.value_string; + if (s.len > 1 && s[0] == '"' && s[s.len-1] == '"') { + value.value_string = substring(s, 1, s.len-1); + } + } break; } + } } if (ok) { switch (bf.param_kind) { @@ -365,6 +374,24 @@ bool parse_build_flags(Array args) { } if (ok) switch (bf.kind) { + case BuildFlag_OutFile: { + GB_ASSERT(value.kind == ExactValue_String); + String path = value.value_string; + path = string_trim_whitespace(path); + if (is_import_path_valid(path)) { + #if defined(GB_SYSTEM_WINDOWS) + String ext = path_extension(path); + if (ext == ".exe") { + path = substring(path, 0, string_extension_position(path)); + } + #endif + build_context.out_filepath = path; + } else { + gb_printf_err("Invalid -out path, got %.*s\n", LIT(path)); + bad_flags = true; + } + break; + } case BuildFlag_OptimizationLevel: GB_ASSERT(value.kind == ExactValue_Integer); build_context.optimization_level = cast(i32)value.value_integer; @@ -377,7 +404,7 @@ bool parse_build_flags(Array args) { GB_ASSERT(value.kind == ExactValue_Integer); isize count = cast(isize)value.value_integer; if (count <= 0) { - gb_printf_err("%.*s expected a positive non-zero number, got %.*s", LIT(name), LIT(param)); + gb_printf_err("%.*s expected a positive non-zero number, got %.*s\n", LIT(name), LIT(param)); build_context.thread_count = 0; } else { build_context.thread_count = count; diff --git a/src/string.cpp b/src/string.cpp index 822a386d7..333e1aa05 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -84,7 +84,7 @@ gb_inline String make_string_c(char *text) { String substring(String s, isize lo, isize hi) { isize max = s.len; - GB_ASSERT(lo <= hi && hi <= max); + GB_ASSERT_MSG(lo <= hi && hi <= max, "%td..%td..%td", lo, hi, max); return make_string(s.text+lo, hi-lo); } @@ -211,6 +211,15 @@ gb_inline isize string_extension_position(String str) { return dot_pos; } +String path_extension(String str) { + isize pos = string_extension_position(str); + if (pos < 0) { + return make_string(nullptr, 0); + } + return substring(str, pos, str.len); +} + + String string_trim_whitespace(String str) { while (str.len > 0 && rune_is_whitespace(str[str.len-1])) { str.len--; @@ -239,17 +248,16 @@ bool string_contains_char(String s, u8 c) { String filename_from_path(String s) { isize i = string_extension_position(s); + s = substring(s, 0, i); if (i > 0) { isize j = 0; - s.len = i; - for (j = i-1; j >= 0; j--) { + for (j = s.len-1; j >= 0; j--) { if (s[j] == '/' || s[j] == '\\') { break; } } - s.text += j+1; - s.len = i-j-1; + return substring(s, j+1, s.len); } return make_string(nullptr, 0); }