diff --git a/src/build/builder.c b/src/build/builder.c index 3555b396f..422824eb2 100644 --- a/src/build/builder.c +++ b/src/build/builder.c @@ -9,19 +9,7 @@ void load_library_files(void) {} void load_files(void) {} -void compile_files(BuildTarget *target); -void build(const char *optional_target) -{ - // Locate the project.toml - file_find_top_dir(); - // Parse it - Project *project = project_load(); - BuildTarget *target = project_select_target(project, optional_target); - - load_library_files(); - compile_files(target); -} static void update_build_target_from_options(BuildTarget *target, BuildOptions *options) { @@ -143,6 +131,7 @@ void init_default_build_target(BuildTarget *target, BuildOptions *options, const void init_build_target(BuildTarget *target, BuildOptions *options) { + *target = (BuildTarget) { 0 }; // Locate the project.toml file_find_top_dir(); // Parse it diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 9b22f573a..4baa1ae6d 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -7,6 +7,7 @@ #include Compiler compiler; +BuildTarget active_target; Vmem ast_arena; Vmem expr_arena; @@ -44,12 +45,12 @@ void compiler_init(const char *std_lib_dir) } } -static void compiler_lex(BuildTarget *target) +static void compiler_lex(void) { - VECEACH(target->sources, i) + VECEACH(compiler.sources, i) { bool loaded = false; - File *file = source_file_load(target->sources[i], &loaded); + File *file = source_file_load(compiler.sources[i], &loaded); if (loaded) continue; Lexer lexer; lexer_init_with_file(&lexer, file); @@ -65,40 +66,40 @@ static void compiler_lex(BuildTarget *target) exit(EXIT_SUCCESS); } -void compiler_parse(BuildTarget *target) +void compiler_parse(void) { - VECEACH(target->sources, i) + VECEACH(compiler.sources, i) { bool loaded = false; - File *file = source_file_load(target->sources[i], &loaded); + File *file = source_file_load(compiler.sources[i], &loaded); if (loaded) continue; - diag_setup(target->test_output); - Context *context = context_create(file, target); + diag_setup(active_target.test_output); + Context *context = context_create(file); parse_file(context); context_print_ast(context, stdout); } exit(EXIT_SUCCESS); } -void compiler_compile(BuildTarget *target) +void compiler_compile(void) { Context **contexts = NULL; - diag_setup(target->test_output); + diag_setup(active_target.test_output); if (compiler.lib_dir) { - vec_add(target->sources, strformat("%s/std/runtime.c3", compiler.lib_dir)); - vec_add(target->sources, strformat("%s/std/builtin.c3", compiler.lib_dir)); - vec_add(target->sources, strformat("%s/std/io.c3", compiler.lib_dir)); - vec_add(target->sources, strformat("%s/std/mem.c3", compiler.lib_dir)); - vec_add(target->sources, strformat("%s/std/array.c3", compiler.lib_dir)); - vec_add(target->sources, strformat("%s/std/math.c3", compiler.lib_dir)); + vec_add(compiler.sources, strformat("%s/std/runtime.c3", compiler.lib_dir)); + vec_add(compiler.sources, strformat("%s/std/builtin.c3", compiler.lib_dir)); + vec_add(compiler.sources, strformat("%s/std/io.c3", compiler.lib_dir)); + vec_add(compiler.sources, strformat("%s/std/mem.c3", compiler.lib_dir)); + vec_add(compiler.sources, strformat("%s/std/array.c3", compiler.lib_dir)); + vec_add(compiler.sources, strformat("%s/std/math.c3", compiler.lib_dir)); } - VECEACH(target->sources, i) + VECEACH(compiler.sources, i) { bool loaded = false; - File *file = source_file_load(target->sources[i], &loaded); + File *file = source_file_load(compiler.sources[i], &loaded); if (loaded) continue; - Context *context = context_create(file, target); + Context *context = context_create(file); vec_add(contexts, context); parse_file(context); } @@ -144,7 +145,7 @@ void compiler_compile(BuildTarget *target) } if (diagnostics.errors > 0) exit(EXIT_FAILURE); - if (target->output_headers) + if (active_target.output_headers) { for (unsigned i = 0; i < source_count; i++) { @@ -183,7 +184,7 @@ void compiler_compile(BuildTarget *target) print_arena_status(); - bool create_exe = !target->test_output && (target->type == TARGET_TYPE_EXECUTABLE || target->type == TARGET_TYPE_TEST); + bool create_exe = !active_target.test_output && (active_target.type == TARGET_TYPE_EXECUTABLE || active_target.type == TARGET_TYPE_TEST); const char **obj_files = NULL; @@ -196,21 +197,21 @@ void compiler_compile(BuildTarget *target) if (create_exe) { - if (target->arch_os_target == ARCH_OS_TARGET_DEFAULT) + if (active_target.arch_os_target == ARCH_OS_TARGET_DEFAULT) { - platform_linker(target->name, obj_files, source_count); + platform_linker(active_target.name, obj_files, source_count); } else { - if (!obj_format_linking_supported(platform_target.object_format) || !linker(target->name, obj_files, source_count)) + if (!obj_format_linking_supported(platform_target.object_format) || !linker(active_target.name, obj_files, source_count)) { printf("No linking is performed due to missing linker support."); - target->run_after_compile = false; + active_target.run_after_compile = false; } } - if (target->run_after_compile) + if (active_target.run_after_compile) { - system(strformat("./%s", target->name)); + system(strformat("./%s", active_target.name)); } } @@ -257,25 +258,37 @@ static void target_expand_source_names(BuildTarget *target) target->sources = files; } -void compile_files(BuildTarget *target) +void compile_target(BuildOptions *options) { - symtab_init(target->symtab_size ? target->symtab_size : 64 * 1024); - assert(target); - target_expand_source_names(target); - target_setup(target); + init_default_build_target(&active_target, options, "foo.out"); + compile(); +} - if (!vec_size(target->sources)) error_exit("No files to compile."); - if (target->lex_only) +void compile_file_list(BuildOptions *options) +{ + init_build_target(&active_target, options); + compile(); +} + +void compile() +{ + compiler.sources = active_target.sources; + symtab_init(active_target.symtab_size ? active_target.symtab_size : 64 * 1024); + target_expand_source_names(&active_target); + target_setup(&active_target); + + if (!vec_size(active_target.sources)) error_exit("No files to compile."); + if (active_target.lex_only) { - compiler_lex(target); + compiler_lex(); return; } - if (target->parse_only) + if (active_target.parse_only) { - compiler_parse(target); + compiler_parse(); return; } - compiler_compile(target); + compiler_compile(); } diff --git a/src/compiler/compiler.h b/src/compiler/compiler.h index 4f1b1fc7f..1f5c3c45d 100644 --- a/src/compiler/compiler.h +++ b/src/compiler/compiler.h @@ -7,7 +7,9 @@ // a copy of which can be found in the LICENSE file. void compiler_init(const char *std_lib_dir); -void compile_files(BuildTarget *target); +void compile(); +void compile_target(BuildOptions *options); +void compile_file_list(BuildOptions *options); void init_build_target(BuildTarget *build_target, BuildOptions *build_options); void init_default_build_target(BuildTarget *target, BuildOptions *options, const char *name); void symtab_init(uint32_t max_size); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index abd0a5e2e..385ac515a 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1212,7 +1212,6 @@ typedef struct typedef struct _Context { - BuildTarget *target; Path *module_name; TokenId* module_parameters; File* file; @@ -1287,6 +1286,7 @@ typedef struct STable qualified_symbols; Type **type; const char *lib_dir; + const char **sources; } Compiler; typedef enum @@ -1377,6 +1377,7 @@ typedef struct ABIArgInfo_ } ABIArgInfo; extern Compiler compiler; +extern BuildTarget active_target; extern Ast *poisoned_ast; extern Decl *poisoned_decl; extern Expr *poisoned_expr; @@ -1493,7 +1494,7 @@ Decl *compiler_find_symbol(const char *name); Module *compiler_find_or_create_module(Path *module_name); void compiler_register_public_symbol(Decl *decl); -Context *context_create(File *file, BuildTarget *target); +Context *context_create(File *file); void context_register_global_decl(Context *context, Decl *decl); void context_register_external_symbol(Context *context, Decl *decl); bool context_add_import(Context *context, Path *path, Token symbol, Token alias); diff --git a/src/compiler/context.c b/src/compiler/context.c index d213f7f46..976b27bd2 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -5,11 +5,10 @@ #include "compiler_internal.h" -Context *context_create(File *file, BuildTarget *target) +Context *context_create(File *file) { Context *context = CALLOCS(Context); context->file = file; - context->target = target; stable_init(&context->local_symbols, 256); stable_init(&context->external_symbols, 256); stable_init(&context->scratch_table, 32); diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 10d71de4b..7f0842a90 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -40,7 +40,6 @@ static void gencontext_init(GenContext *context, Context *ast_context) { memset(context, 0, sizeof(GenContext)); context->context = LLVMContextCreate(); - context->build_target = ast_context->target; context->bool_type = LLVMInt1TypeInContext(context->context); context->byte_type = LLVMInt8TypeInContext(context->context); LLVMContextSetDiagnosticHandler(context->context, &diagnostics_handler, context); @@ -484,13 +483,13 @@ void llvm_emit_local_var_alloca(GenContext *c, Decl *decl) * Values here taken from LLVM. * @return return the inlining threshold given the build options. */ -static int get_inlining_threshold(BuildTarget *target) +static int get_inlining_threshold() { - if (target->optimization_level == OPTIMIZATION_AGGRESSIVE) + if (active_target.optimization_level == OPTIMIZATION_AGGRESSIVE) { return 250; } - switch (target->size_optimization_level) + switch (active_target.size_optimization_level) { case SIZE_OPTIMIZATION_TINY: return 5; @@ -888,10 +887,10 @@ const char *llvm_codegen(void *context) LLVMModuleRef module = c->module; // Starting from here we could potentially thread this: LLVMPassManagerBuilderRef pass_manager_builder = LLVMPassManagerBuilderCreate(); - LLVMPassManagerBuilderSetOptLevel(pass_manager_builder, c->build_target->optimization_level); - LLVMPassManagerBuilderSetSizeLevel(pass_manager_builder, c->build_target->size_optimization_level); - LLVMPassManagerBuilderSetDisableUnrollLoops(pass_manager_builder, c->build_target->optimization_level == OPTIMIZATION_NONE); - LLVMPassManagerBuilderUseInlinerWithThreshold(pass_manager_builder, get_inlining_threshold(c->build_target)); + LLVMPassManagerBuilderSetOptLevel(pass_manager_builder, active_target.optimization_level); + LLVMPassManagerBuilderSetSizeLevel(pass_manager_builder, active_target.size_optimization_level); + LLVMPassManagerBuilderSetDisableUnrollLoops(pass_manager_builder, active_target.optimization_level == OPTIMIZATION_NONE); + LLVMPassManagerBuilderUseInlinerWithThreshold(pass_manager_builder, get_inlining_threshold()); LLVMPassManagerRef pass_manager = LLVMCreatePassManager(); LLVMPassManagerRef function_pass_manager = LLVMCreateFunctionPassManagerForModule(module); LLVMAddAnalysisPasses(target_machine(), function_pass_manager); @@ -921,14 +920,14 @@ const char *llvm_codegen(void *context) LLVMDisposePassManager(pass_manager); // Serialize the LLVM IR, if requested, also verify the IR in this case - if (c->build_target->emit_llvm) + if (active_target.emit_llvm) { gencontext_print_llvm_ir(c); gencontext_verify_ir(c); } const char *object_name = NULL; - if (c->build_target->emit_object_files) + if (active_target.emit_object_files) { gencontext_emit_object_file(c); object_name = c->object_filename; diff --git a/src/compiler/llvm_codegen_debug_info.c b/src/compiler/llvm_codegen_debug_info.c index 39c6b413b..08f638d2b 100644 --- a/src/compiler/llvm_codegen_debug_info.c +++ b/src/compiler/llvm_codegen_debug_info.c @@ -123,7 +123,7 @@ void llvm_emit_debug_function(GenContext *c, Decl *decl) true, loc->line, flags, - c->build_target->optimization_level != OPTIMIZATION_NONE); + active_target.optimization_level != OPTIMIZATION_NONE); LLVMSetSubprogram(decl->backend_ref, c->debug.function); } @@ -139,7 +139,7 @@ void llvm_emit_debug_local_var(GenContext *c, Decl *decl) c->debug.file, location->line, llvm_get_debug_type(c, decl->type), - c->build_target->optimization_level != OPTIMIZATION_NONE, + active_target.optimization_level != OPTIMIZATION_NONE, LLVMDIFlagZero, decl->alignment); decl->var.backend_debug_ref = var; diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 9dd0ac9b8..1f6d4f0ac 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -36,7 +36,7 @@ LLVMValueRef llvm_emit_const_padding(GenContext *c, ByteSize size) static inline LLVMValueRef llvm_emit_add_int(GenContext *c, Type *type, LLVMValueRef left, LLVMValueRef right) { - if (c->build_target->feature.trap_on_wrap) + if (active_target.feature.trap_on_wrap) { LLVMTypeRef type_to_use = llvm_get_type(c, type->canonical); LLVMValueRef args[2] = { left, right }; @@ -98,7 +98,7 @@ void llvm_emit_convert_value_from_coerced(GenContext *context, BEValue *result, static inline LLVMValueRef llvm_emit_sub_int(GenContext *c, Type *type, LLVMValueRef left, LLVMValueRef right) { - if (c->build_target->feature.trap_on_wrap) + if (active_target.feature.trap_on_wrap) { LLVMTypeRef type_to_use = llvm_get_type(c, type); LLVMValueRef args[2] = { left, right }; @@ -190,7 +190,7 @@ static inline LLVMValueRef llvm_emit_subscript_addr_with_base_new(GenContext *c, return LLVMBuildInBoundsGEP(c->builder, parent->value, &index->value, 1, "ptridx"); case TYPE_ARRAY: { - if (c->build_target->feature.safe_mode) + if (active_target.feature.safe_mode) { llvm_emit_array_bounds_check(c, index, llvm_const_int(c, index->type, type->array.len)); } @@ -205,7 +205,7 @@ static inline LLVMValueRef llvm_emit_subscript_addr_with_base_new(GenContext *c, } case TYPE_SUBARRAY: { - if (c->build_target->feature.safe_mode) + if (active_target.feature.safe_mode) { // TODO insert trap on overflow. } @@ -1084,7 +1084,7 @@ static void gencontext_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr assert(!type_is_unsigned(type)); llvm_emit_expr(c, value, expr->unary_expr.expr); llvm_value_rvalue(c, value); - if (c->build_target->feature.trap_on_wrap) + if (active_target.feature.trap_on_wrap) { LLVMValueRef zero = llvm_get_zero(c, expr->unary_expr.expr->type); LLVMTypeRef type_to_use = llvm_get_type(c, type->canonical); @@ -1181,7 +1181,7 @@ static void llvm_emit_len(GenContext *c, BEValue *be_value, Expr *expr) static void llvm_emit_trap_negative(GenContext *c, Expr *expr, LLVMValueRef value, const char *error) { - if (!c->build_target->feature.safe_mode) return; + if (!active_target.feature.safe_mode) return; if (type_is_integer_unsigned(expr->type->canonical)) return; LLVMValueRef zero = llvm_const_int(c, expr->type, 0); @@ -1191,7 +1191,7 @@ static void llvm_emit_trap_negative(GenContext *c, Expr *expr, LLVMValueRef valu static void llvm_emit_trap_zero(GenContext *c, Type *type, LLVMValueRef value, const char *error) { - if (!c->build_target->feature.safe_mode) return; + if (!active_target.feature.safe_mode) return; LLVMValueRef zero = llvm_get_zero(c, type); LLVMValueRef ok = type_is_any_integer(type) ? LLVMBuildICmp(c->builder, LLVMIntEQ, value, zero, "zero") : LLVMBuildFCmp(c->builder, LLVMRealUEQ, value, zero, "zero"); @@ -1201,7 +1201,7 @@ static void llvm_emit_trap_zero(GenContext *c, Type *type, LLVMValueRef value, c static void llvm_emit_trap_invalid_shift(GenContext *c, LLVMValueRef value, Type *type, const char *error) { - if (!c->build_target->feature.safe_mode) return; + if (!active_target.feature.safe_mode) return; unsigned type_bit_size = type_size(type) * 8; LLVMValueRef max = llvm_const_int(c, type, type_bit_size); if (type_is_unsigned(type)) @@ -1261,7 +1261,7 @@ llvm_emit_slice_values(GenContext *c, Expr *slice, Type **parent_type_ref, LLVMV llvm_value_rvalue(c, &start_index); LLVMValueRef len; - if (!end || slice->slice_expr.start_from_back || slice->slice_expr.end_from_back || c->build_target->feature.safe_mode) + if (!end || slice->slice_expr.start_from_back || slice->slice_expr.end_from_back || active_target.feature.safe_mode) { switch (parent_type->type_kind) { @@ -1289,7 +1289,7 @@ llvm_emit_slice_values(GenContext *c, Expr *slice, Type **parent_type_ref, LLVMV } // Check that index does not extend beyond the length. - if (parent_type->type_kind != TYPE_POINTER && c->build_target->feature.safe_mode) + if (parent_type->type_kind != TYPE_POINTER && active_target.feature.safe_mode) { LLVMValueRef exceeds_size = llvm_emit_int_comparison(c, @@ -1325,7 +1325,7 @@ llvm_emit_slice_values(GenContext *c, Expr *slice, Type **parent_type_ref, LLVMV } // This will trap any bad negative index, so we're fine. - if (c->build_target->feature.safe_mode) + if (active_target.feature.safe_mode) { LLVMValueRef excess = llvm_emit_int_comparison(c, start_type, @@ -1695,7 +1695,7 @@ static inline LLVMValueRef llvm_fixup_shift_rhs(GenContext *c, LLVMValueRef left static inline LLVMValueRef llvm_emit_mult_int(GenContext *c, Type *type, LLVMValueRef left, LLVMValueRef right) { - if (c->build_target->feature.trap_on_wrap) + if (active_target.feature.trap_on_wrap) { LLVMTypeRef type_to_use = llvm_get_type(c, type); LLVMValueRef args[2] = { left, right }; diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 4be9ff1c6..aef5754ea 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -97,7 +97,6 @@ typedef struct bool current_block_is_target : 1; bool did_call_stack_save : 1; LLVMTypeRef type_data_definitions[TYPE_KINDS]; - BuildTarget *build_target; } GenContext; // LLVM Intrinsics diff --git a/src/compiler/llvm_codegen_module.c b/src/compiler/llvm_codegen_module.c index 3fd6b68fc..15984d306 100644 --- a/src/compiler/llvm_codegen_module.c +++ b/src/compiler/llvm_codegen_module.c @@ -19,21 +19,21 @@ void gencontext_begin_module(GenContext *c) LLVMSetSourceFileName(c->module, full_path, strlen(c->ast_context->file->full_path)); LLVMTypeRef options_type = LLVMInt8TypeInContext(c->context); - if (c->build_target->pic == PIC_BIG || c->build_target->pic == PIC_SMALL) + if (active_target.pic == PIC_BIG || active_target.pic == PIC_SMALL) { static const char *pic_level = "PIC Level"; - LLVMMetadataRef setting = LLVMValueAsMetadata(LLVMConstInt(options_type, c->build_target->pic, false)); + LLVMMetadataRef setting = LLVMValueAsMetadata(LLVMConstInt(options_type, active_target.pic, false)); LLVMAddModuleFlag(c->module, LLVMModuleFlagBehaviorOverride, pic_level, strlen(pic_level), setting); } - if (c->build_target->pie == PIE_BIG || c->build_target->pie == PIE_SMALL) + if (active_target.pie == PIE_BIG || active_target.pie == PIE_SMALL) { static const char *pie_level = "PIE Level"; - LLVMMetadataRef setting = LLVMValueAsMetadata(LLVMConstInt(options_type, c->build_target->pie, false)); + LLVMMetadataRef setting = LLVMValueAsMetadata(LLVMConstInt(options_type, active_target.pie, false)); LLVMAddModuleFlag(c->module, LLVMModuleFlagBehaviorOverride, pie_level, strlen(pie_level), setting); } LLVMSetTarget(c->module, platform_target.target_triple); - if (c->build_target->debug_info != DEBUG_INFO_NONE) + if (active_target.debug_info != DEBUG_INFO_NONE) { const char *filename = c->ast_context->file->name; const char *dir_path = c->ast_context->file->dir_path; @@ -42,10 +42,10 @@ void gencontext_begin_module(GenContext *c) c->debug.builder = LLVMCreateDIBuilder(c->module); c->debug.file = LLVMDIBuilderCreateFile(c->debug.builder, filename, strlen(filename), dir_path, strlen(dir_path)); - bool is_optimized = c->build_target->optimization_level != OPTIMIZATION_NONE; + bool is_optimized = active_target.optimization_level != OPTIMIZATION_NONE; const char *dwarf_flags = ""; unsigned runtime_version = 1; - LLVMDWARFEmissionKind emission_kind = c->build_target->debug_info == DEBUG_INFO_FULL ? LLVMDWARFEmissionFull : LLVMDWARFEmissionLineTablesOnly; + LLVMDWARFEmissionKind emission_kind = active_target.debug_info == DEBUG_INFO_FULL ? LLVMDWARFEmissionFull : LLVMDWARFEmissionLineTablesOnly; c->debug.compile_unit = LLVMDIBuilderCreateCompileUnit(c->debug.builder, LLVMDWARFSourceLanguageC, c->debug.file, DWARF_PRODUCER_NAME, strlen(DWARF_PRODUCER_NAME), is_optimized, diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index b38da0194..82233c06e 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -1029,7 +1029,7 @@ static inline void gencontext_emit_assume(GenContext *c, Expr *expr) static inline void gencontext_emit_assert_stmt(GenContext *c, Ast *ast) { - if (c->build_target->feature.safe_mode) + if (active_target.feature.safe_mode) { BEValue value; llvm_emit_expr(c, &value, ast->assert_stmt.expr); diff --git a/src/compiler_tests/tests.c b/src/compiler_tests/tests.c index 5c1e0b57a..6498956bd 100644 --- a/src/compiler_tests/tests.c +++ b/src/compiler_tests/tests.c @@ -119,8 +119,7 @@ void test_compiler(void) char *res = NULL; asprintf(&res, "tests/%s", files[i]); single_file[0] = res; - BuildTarget target = { .type = TARGET_TYPE_EXECUTABLE, .sources = single_file, .name = "a.out" }; - compile_files(&target); + active_target = (BuildTarget) { .type = TARGET_TYPE_EXECUTABLE, .sources = single_file, .name = "a.out" }; free(res); } diff --git a/src/main.c b/src/main.c index 04fd1f054..346cef970 100644 --- a/src/main.c +++ b/src/main.c @@ -35,8 +35,7 @@ int main(int argc, const char *argv[]) case COMMAND_GENERATE_HEADERS: case COMMAND_COMPILE: case COMMAND_COMPILE_RUN: - init_default_build_target(&build_target, &build_options, "foo.out"); - compile_files(&build_target); + compile_target(&build_options); break; case COMMAND_BUILD: case COMMAND_RUN: @@ -45,8 +44,7 @@ int main(int argc, const char *argv[]) case COMMAND_DIST: case COMMAND_DOCS: case COMMAND_BENCH: - init_build_target(&build_target, &build_options); - compile_files(&build_target); + compile_file_list(&build_options); break; case COMMAND_MISSING: printf("TODO\n");