diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index cec5122f4..23c34da16 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -3,9 +3,15 @@ // a copy of which can be found in the LICENSE file. #include "compiler_internal.h" -#include "../build/build_options.h" #include +#if PLATFORM_POSIX +#include +#define USE_PTHREAD 1 +#else +#define USE_PTHREAD 0 +#endif + GlobalContext global_context; BuildTarget active_target; @@ -30,6 +36,7 @@ void compiler_init(const char *std_lib_dir) //compiler.lib_dir = find_lib_dir(); //DEBUG_LOG("Found std library: %s", compiler.lib_dir); stable_init(&global_context.modules, 64); + stable_init(&global_context.scratch_table, 32); global_context.module_list = NULL; global_context.generic_module_list = NULL; stable_init(&global_context.global_symbols, 0x1000); @@ -96,6 +103,12 @@ static inline void halt_on_error(void) if (global_context.errors_found > 0) exit(EXIT_FAILURE); } +#if USE_PTHREAD +void* compile_on_pthread(void *gencontext) +{ + return (void *)llvm_codegen(gencontext); +} +#endif void compiler_compile(void) { Context **contexts = NULL; @@ -186,6 +199,7 @@ void compiler_compile(void) llvm_codegen_setup(); void **gen_contexts = malloc(source_count * sizeof(void *)); + for (unsigned i = 0; i < source_count; i++) { Context *context = contexts[i]; @@ -197,6 +211,7 @@ void compiler_compile(void) gen_contexts[i] = llvm_gen(context); } + printf("-- AST/EXPR INFO -- \n"); printf(" * Ast memory use: %llukb\n", (unsigned long long)ast_arena.allocated / 1024); printf(" * Decl memory use: %llukb\n", (unsigned long long)decl_arena.allocated / 1024); @@ -220,6 +235,22 @@ void compiler_compile(void) const char **obj_files = NULL; +#if USE_PTHREAD + pthread_t *threads = malloc(source_count * sizeof(threads)); + for (unsigned i = 0; i < source_count; i++) + { + if (!gen_contexts[i]) continue; + pthread_create(&threads[i], NULL, &compile_on_pthread, gen_contexts[i]); + } + for (unsigned i = 0; i < source_count; i++) + { + void *file_name; + pthread_join(threads[i], &file_name); + assert(file_name || !create_exe); + printf("Received result: %s\n", (char*)file_name); + vec_add(obj_files, file_name); + } +#else for (unsigned i = 0; i < source_count; i++) { if (!gen_contexts[i]) continue; @@ -227,6 +258,7 @@ void compiler_compile(void) assert(file_name || !create_exe); vec_add(obj_files, file_name); } +#endif if (create_exe) { diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 09fb1076e..214e2a1bb 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -41,8 +41,8 @@ typedef struct #define INVALID_TOKEN_ID ((TokenId) { UINT32_MAX }) #define INVALID_RANGE ((SourceSpan){ INVALID_TOKEN_ID, INVALID_TOKEN_ID }) #define MAX_LOCALS 0xFFFF -#define MAX_SCOPE_DEPTH 0xFF -#define MAX_PATH 1024 +#define MAX_SCOPE_DEPTH 0x1000 +#define MAX_PATH 0x10000 #define MAX_MACRO_NESTING 1024 #define MAX_FUNCTION_SIGNATURE_SIZE 2048 #define MAX_PARAMS 512 @@ -1254,20 +1254,16 @@ typedef struct _Context int macro_nesting; }; Decl **last_local; - char path_scratch[MAX_PATH]; struct { STable external_symbols; Decl **external_symbol_list; }; - STable scratch_table; Lexer lexer; Token tok; TokenId prev_tok; Token next_tok; TokenId docs_start; TokenId docs_end; - Decl* locals[MAX_LOCALS]; - DynamicScope scopes[MAX_SCOPE_DEPTH]; } Context; typedef struct @@ -1284,13 +1280,12 @@ typedef struct bool in_test_mode : 1; unsigned errors_found; unsigned warnings_found; + char path_scratch[MAX_PATH]; + Decl* locals[MAX_LOCALS]; + DynamicScope scopes[MAX_SCOPE_DEPTH]; + STable scratch_table; } GlobalContext; -typedef enum -{ - MODULE_SYMBOL_SEARCH_EXTERNAL, - MODULE_SYMBOL_SEARCH_MODULE -} ModuleSymbolSearch; typedef enum { @@ -1652,11 +1647,9 @@ void stable_clear(STable *table); const char *symtab_add(const char *symbol, uint32_t len, uint32_t fnv1hash, TokenType *type); +void *llvm_target_machine_create(void); void target_setup(BuildTarget *build_target); int target_alloca_addr_space(); -void *target_data_layout(); -void *target_machine(); -void *target_target(); #define TOK2VARSTR(_token) _token.span.length, _token.start bool token_is_type(TokenType type); diff --git a/src/compiler/context.c b/src/compiler/context.c index 0a0e15ff4..5988d6308 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -11,7 +11,6 @@ Context *context_create(File *file) context->file = file; stable_init(&context->local_symbols, 256); stable_init(&context->external_symbols, 256); - stable_init(&context->scratch_table, 32); return context; } diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 313849e78..1f3993a84 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -49,6 +49,8 @@ static void gencontext_init(GenContext *context, Context *ast_context) static void gencontext_destroy(GenContext *context) { LLVMContextDispose(context->context); + LLVMDisposeTargetData(context->target_data); + LLVMDisposeTargetMachine(context->machine); free(context); } @@ -426,12 +428,12 @@ void gencontext_emit_object_file(GenContext *context) { char *err = ""; LLVMSetTarget(context->module, platform_target.target_triple); - char *layout = LLVMCopyStringRepOfTargetData(target_data_layout()); + char *layout = LLVMCopyStringRepOfTargetData(context->target_data); LLVMSetDataLayout(context->module, layout); LLVMDisposeMessage(layout); // Generate .o or .obj file - if (LLVMTargetMachineEmitToFile(target_machine(), context->module, context->object_filename, LLVMObjectFile, &err)) + if (LLVMTargetMachineEmitToFile(context->machine, context->module, context->object_filename, LLVMObjectFile, &err)) { error_exit("Could not emit object file: %s", err); } @@ -893,8 +895,8 @@ const char *llvm_codegen(void *context) LLVMPassManagerBuilderUseInlinerWithThreshold(pass_manager_builder, get_inlining_threshold()); LLVMPassManagerRef pass_manager = LLVMCreatePassManager(); LLVMPassManagerRef function_pass_manager = LLVMCreateFunctionPassManagerForModule(module); - LLVMAddAnalysisPasses(target_machine(), function_pass_manager); - LLVMAddAnalysisPasses(target_machine(), pass_manager); + LLVMAddAnalysisPasses(c->machine, function_pass_manager); + LLVMAddAnalysisPasses(c->machine, pass_manager); LLVMPassManagerBuilderPopulateModulePassManager(pass_manager_builder, pass_manager); LLVMPassManagerBuilderPopulateFunctionPassManager(pass_manager_builder, function_pass_manager); @@ -1017,14 +1019,14 @@ void llvm_attribute_add_string(GenContext *context, LLVMValueRef value_to_add_at LLVMAddAttributeAtIndex(value_to_add_attribute_to, index, llvm_attr); } -unsigned llvm_abi_size(LLVMTypeRef type) +unsigned llvm_abi_size(GenContext *c, LLVMTypeRef type) { - return LLVMABISizeOfType(target_data_layout(), type); + return LLVMABISizeOfType(c->target_data, type); } -AlignSize llvm_abi_alignment(LLVMTypeRef type) +AlignSize llvm_abi_alignment(GenContext *c, LLVMTypeRef type) { - return (AlignSize)LLVMABIAlignmentOfType(target_data_layout(), type); + return (AlignSize)LLVMABIAlignmentOfType(c->target_data, type); } void llvm_store_bevalue_aligned(GenContext *c, LLVMValueRef destination, BEValue *value, AlignSize alignment) @@ -1111,16 +1113,16 @@ void llvm_emit_memcpy_to_decl(GenContext *c, Decl *decl, LLVMValueRef source, un llvm_emit_memcpy(c, decl->backend_ref, decl->alignment, source, source_alignment, type_size(decl->type)); } -LLVMValueRef llvm_emit_load_aligned(GenContext *context, LLVMTypeRef type, LLVMValueRef pointer, AlignSize alignment, const char *name) +LLVMValueRef llvm_emit_load_aligned(GenContext *c, LLVMTypeRef type, LLVMValueRef pointer, AlignSize alignment, const char *name) { - LLVMValueRef value = LLVMBuildLoad2(context->builder, type, pointer, name); - llvm_set_alignment(value, alignment ?: llvm_abi_alignment(type)); + LLVMValueRef value = LLVMBuildLoad2(c->builder, type, pointer, name); + llvm_set_alignment(value, alignment ?: llvm_abi_alignment(c, type)); return value; } -unsigned llvm_store_size(LLVMTypeRef type) +unsigned llvm_store_size(GenContext *c, LLVMTypeRef type) { - return LLVMStoreSizeOfType(target_data_layout(), type); + return LLVMStoreSizeOfType(c->target_data, type); } void llvm_set_error_exit(GenContext *c, LLVMBasicBlockRef block) diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 105893867..67a66367c 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -59,39 +59,39 @@ static inline LLVMValueRef llvm_emit_add_int(GenContext *c, Type *type, LLVMValu return LLVMBuildAdd(c->builder, left, right, "add"); } -LLVMValueRef llvm_emit_coerce(GenContext *context, LLVMTypeRef coerced, BEValue *value, Type *original_type) +LLVMValueRef llvm_emit_coerce(GenContext *c, LLVMTypeRef coerced, BEValue *value, Type *original_type) { LLVMValueRef cast; - AlignSize target_alignment = llvm_abi_alignment(coerced); - AlignSize max_align = MAX(value->alignment, llvm_abi_alignment(coerced)); + AlignSize target_alignment = llvm_abi_alignment(c, coerced); + AlignSize max_align = MAX(value->alignment, llvm_abi_alignment(c, coerced)); // If we are loading something with greater alignment than what we have, we cannot directly memcpy. if (llvm_value_is_addr(value) && value->alignment < target_alignment) { // So load it instead. - llvm_value_rvalue(context, value); + llvm_value_rvalue(c, value); } // In this case we have something nicely aligned, so we just do a cast. if (llvm_value_is_addr(value)) { - cast = LLVMBuildBitCast(context->builder, value->value, LLVMPointerType(coerced, 0), ""); + cast = LLVMBuildBitCast(c->builder, value->value, LLVMPointerType(coerced, 0), ""); } else { - cast = llvm_emit_alloca(context, coerced, max_align, "coerce"); - LLVMValueRef target = LLVMBuildBitCast(context->builder, cast, llvm_get_ptr_type(context, value->type), ""); - llvm_store_bevalue_aligned(context, target, value, max_align); + cast = llvm_emit_alloca(c, coerced, max_align, "coerce"); + LLVMValueRef target = LLVMBuildBitCast(c->builder, cast, llvm_get_ptr_type(c, value->type), ""); + llvm_store_bevalue_aligned(c, target, value, max_align); } - return llvm_emit_load_aligned(context, coerced, cast, max_align, "coerced"); + return llvm_emit_load_aligned(c, coerced, cast, max_align, "coerced"); } -void llvm_emit_convert_value_from_coerced(GenContext *context, BEValue *result, LLVMTypeRef coerced, LLVMValueRef value, Type *original_type) +void llvm_emit_convert_value_from_coerced(GenContext *c, BEValue *result, LLVMTypeRef coerced, LLVMValueRef value, Type *original_type) { - unsigned max_align = MAX(llvm_abi_alignment(coerced), type_abi_alignment(original_type)); - LLVMValueRef temp = llvm_emit_alloca(context, coerced, max_align, "coerce_temp"); - llvm_store_aligned(context, temp, value, max_align); - temp = LLVMBuildBitCast(context->builder, temp, llvm_get_type(context, type_get_ptr(original_type)), ""); + unsigned max_align = MAX(llvm_abi_alignment(c, coerced), type_abi_alignment(original_type)); + LLVMValueRef temp = llvm_emit_alloca(c, coerced, max_align, "coerce_temp"); + llvm_store_aligned(c, temp, value, max_align); + temp = LLVMBuildBitCast(c->builder, temp, llvm_get_type(c, type_get_ptr(original_type)), ""); llvm_value_set_address_align(result, temp, original_type, max_align); } @@ -1686,7 +1686,7 @@ static inline LLVMValueRef llvm_fixup_shift_rhs(GenContext *c, LLVMValueRef left LLVMTypeRef left_type = LLVMTypeOf(left); LLVMTypeRef right_type = LLVMTypeOf(right); if (left_type == right_type) return right; - if (LLVMStoreSizeOfType(platform_target.target, left_type) < LLVMStoreSizeOfType(platform_target.target, right_type)) + if (LLVMStoreSizeOfType(c->target_data, left_type) < LLVMStoreSizeOfType(c->target_data, right_type)) { return LLVMBuildTrunc(c->builder, right, left_type, ""); } @@ -2447,7 +2447,7 @@ void gencontext_emit_call_intrinsic_expr(GenContext *c, BEValue *be_value, Expr UNREACHABLE } -void llvm_emit_parameter(GenContext *context, LLVMValueRef **args, ABIArgInfo *info, BEValue *be_value, Type *type) +void llvm_emit_parameter(GenContext *c, LLVMValueRef **args, ABIArgInfo *info, BEValue *be_value, Type *type) { switch (info->kind) { @@ -2458,100 +2458,100 @@ void llvm_emit_parameter(GenContext *context, LLVMValueRef **args, ABIArgInfo *i { // If we want we could optimize for structs by doing it by reference here. unsigned alignment = info->indirect.realignment ?: type_abi_alignment(type); - LLVMValueRef indirect = llvm_emit_alloca(context, - llvm_get_type(context, type), + LLVMValueRef indirect = llvm_emit_alloca(c, + llvm_get_type(c, type), alignment, "indirectarg"); - llvm_store_bevalue_aligned(context, indirect, be_value, alignment); + llvm_store_bevalue_aligned(c, indirect, be_value, alignment); vec_add(*args, indirect); return; } case ABI_ARG_DIRECT_COERCE: { - LLVMTypeRef coerce_type = llvm_get_coerce_type(context, info); - if (!coerce_type || coerce_type == llvm_get_type(context, type)) + LLVMTypeRef coerce_type = llvm_get_coerce_type(c, info); + if (!coerce_type || coerce_type == llvm_get_type(c, type)) { - vec_add(*args, llvm_value_rvalue_store(context, be_value)); + vec_add(*args, llvm_value_rvalue_store(c, be_value)); return; } if (!abi_info_should_flatten(info)) { - vec_add(*args, llvm_emit_coerce(context, coerce_type, be_value, type)); + vec_add(*args, llvm_emit_coerce(c, coerce_type, be_value, type)); return; } LLVMValueRef cast; - AlignSize target_alignment = llvm_abi_alignment(coerce_type); - AlignSize max_align = MAX((be_value->alignment), llvm_abi_alignment(coerce_type)); + AlignSize target_alignment = llvm_abi_alignment(c, coerce_type); + AlignSize max_align = MAX((be_value->alignment), llvm_abi_alignment(c, coerce_type)); // If we are loading something with greater alignment than what we have, we cannot directly memcpy. if (llvm_value_is_addr(be_value) && be_value->alignment < target_alignment) { // So load it instead. - llvm_value_rvalue(context, be_value); + llvm_value_rvalue(c, be_value); } // In this case we have something nicely aligned, so we just do a cast. if (llvm_value_is_addr(be_value)) { - cast = LLVMBuildBitCast(context->builder, be_value->value, LLVMPointerType(coerce_type, 0), ""); + cast = LLVMBuildBitCast(c->builder, be_value->value, LLVMPointerType(coerce_type, 0), ""); } else { - cast = llvm_emit_alloca(context, coerce_type, max_align, "coerce"); - LLVMValueRef target = LLVMBuildBitCast(context->builder, cast, llvm_get_ptr_type(context, type), ""); - llvm_store_bevalue_aligned(context, target, be_value, max_align); + cast = llvm_emit_alloca(c, coerce_type, max_align, "coerce"); + LLVMValueRef target = LLVMBuildBitCast(c->builder, cast, llvm_get_ptr_type(c, type), ""); + llvm_store_bevalue_aligned(c, target, be_value, max_align); } - LLVMTypeRef element = llvm_abi_type(context, info->direct_coerce.type); + LLVMTypeRef element = llvm_abi_type(c, info->direct_coerce.type); for (unsigned idx = 0; idx < info->direct_coerce.elements; idx++) { - LLVMValueRef element_ptr = LLVMBuildStructGEP2(context->builder, coerce_type, cast, idx, ""); + LLVMValueRef element_ptr = LLVMBuildStructGEP2(c->builder, coerce_type, cast, idx, ""); vec_add(*args, - llvm_emit_load_aligned(context, element, element_ptr, llvm_abi_alignment(element), "")); + llvm_emit_load_aligned(c, element, element_ptr, llvm_abi_alignment(c, element), "")); } return; } case ABI_ARG_DIRECT_PAIR: { - llvm_value_addr(context, be_value); + llvm_value_addr(c, be_value); printf("Handle invalid alignment"); // Here we do the following transform: // struct -> { lo, hi } -> lo, hi - LLVMTypeRef lo = llvm_abi_type(context, info->direct_pair.lo); - LLVMTypeRef hi = llvm_abi_type(context, info->direct_pair.hi); - LLVMTypeRef struct_type = llvm_get_coerce_type(context, info); - LLVMValueRef cast = LLVMBuildBitCast(context->builder, be_value->value, llvm_get_ptr_type(context, type), "casttemp"); + LLVMTypeRef lo = llvm_abi_type(c, info->direct_pair.lo); + LLVMTypeRef hi = llvm_abi_type(c, info->direct_pair.hi); + LLVMTypeRef struct_type = llvm_get_coerce_type(c, info); + LLVMValueRef cast = LLVMBuildBitCast(c->builder, be_value->value, llvm_get_ptr_type(c, type), "casttemp"); // Get the lo value. - LLVMValueRef lo_ptr = LLVMBuildStructGEP2(context->builder, struct_type, cast, 0, "lo"); - vec_add(*args, llvm_emit_load_aligned(context, lo, lo_ptr, llvm_abi_alignment(lo), "lo")); + LLVMValueRef lo_ptr = LLVMBuildStructGEP2(c->builder, struct_type, cast, 0, "lo"); + vec_add(*args, llvm_emit_load_aligned(c, lo, lo_ptr, llvm_abi_alignment(c, lo), "lo")); // Get the hi value. - LLVMValueRef hi_ptr = LLVMBuildStructGEP2(context->builder, struct_type, cast, 1, "hi"); - vec_add(*args, llvm_emit_load_aligned(context, hi, hi_ptr, llvm_abi_alignment(hi), "hi")); + LLVMValueRef hi_ptr = LLVMBuildStructGEP2(c->builder, struct_type, cast, 1, "hi"); + vec_add(*args, llvm_emit_load_aligned(c, hi, hi_ptr, llvm_abi_alignment(c, hi), "hi")); return; } case ABI_ARG_EXPAND_COERCE: { // Move this to an address (if needed) - llvm_value_addr(context, be_value); - LLVMTypeRef coerce_type = llvm_get_coerce_type(context, info); - LLVMValueRef temp = LLVMBuildBitCast(context->builder, be_value->value, LLVMPointerType(coerce_type, 0), "coerce"); - LLVMValueRef gep_first = LLVMBuildStructGEP2(context->builder, coerce_type, temp, info->coerce_expand.lo_index, "first"); - vec_add(*args, LLVMBuildLoad2(context->builder, llvm_abi_type(context, info->coerce_expand.lo), gep_first, "")); + llvm_value_addr(c, be_value); + LLVMTypeRef coerce_type = llvm_get_coerce_type(c, info); + LLVMValueRef temp = LLVMBuildBitCast(c->builder, be_value->value, LLVMPointerType(coerce_type, 0), "coerce"); + LLVMValueRef gep_first = LLVMBuildStructGEP2(c->builder, coerce_type, temp, info->coerce_expand.lo_index, "first"); + vec_add(*args, LLVMBuildLoad2(c->builder, llvm_abi_type(c, info->coerce_expand.lo), gep_first, "")); if (info->coerce_expand.hi) { - LLVMValueRef gep_second = LLVMBuildStructGEP2(context->builder, coerce_type, temp, info->coerce_expand.hi_index, "second"); - vec_add(*args, LLVMBuildLoad2(context->builder, llvm_abi_type(context, info->coerce_expand.hi), gep_second, "")); + LLVMValueRef gep_second = LLVMBuildStructGEP2(c->builder, coerce_type, temp, info->coerce_expand.hi_index, "second"); + vec_add(*args, LLVMBuildLoad2(c->builder, llvm_abi_type(c, info->coerce_expand.hi), gep_second, "")); } return; } case ABI_ARG_EXPAND: { // Move this to an address (if needed) - llvm_value_addr(context, be_value); - llvm_expand_type_to_args(context, type, be_value->value, args); + llvm_value_addr(c, be_value); + llvm_expand_type_to_args(c, type, be_value->value, args); // Expand the padding here. if (info->expand.padding_type) { - vec_add(*args, LLVMGetUndef(llvm_get_type(context, info->expand.padding_type))); + vec_add(*args, LLVMGetUndef(llvm_get_type(c, info->expand.padding_type))); } return; } diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 3da889da1..77f2e8e6f 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -162,12 +162,12 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsig // Point to the lo value. LLVMValueRef lo_ptr = LLVMBuildStructGEP2(c->builder, struct_type, cast, 0, "lo"); // Store it in the struct. - AlignSize lo_alignment = MIN(llvm_abi_alignment(lo), decl_alignment); + AlignSize lo_alignment = MIN(llvm_abi_alignment(c, lo), decl_alignment); llvm_store_aligned(c, lo_ptr, llvm_get_next_param(c, index), lo_alignment); // Point to the hi value. LLVMValueRef hi_ptr = LLVMBuildStructGEP2(c->builder, struct_type, cast, 1, "hi"); // Store it in the struct. - AlignSize hi_alignment = MIN(llvm_abi_alignment(hi), decl_alignment); + AlignSize hi_alignment = MIN(llvm_abi_alignment(c, hi), decl_alignment); llvm_store_aligned(c, hi_ptr, llvm_get_next_param(c, index), decl_alignment); return; } @@ -199,7 +199,7 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsig LLVMValueRef element_ptr = LLVMBuildStructGEP2(c->builder, coerce_type, cast, idx, ""); LLVMValueRef value = llvm_get_next_param(c, index); - llvm_store_aligned(c, element_ptr, value, MIN(llvm_abi_alignment(element_type), decl->alignment)); + llvm_store_aligned(c, element_ptr, value, MIN(llvm_abi_alignment(c, element_type), decl->alignment)); } return; } diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 7e141608b..8ba05f23f 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -63,6 +63,8 @@ typedef struct typedef struct { LLVMModuleRef module; + LLVMTargetMachineRef machine; + LLVMTargetDataRef target_data; LLVMContextRef context; LLVMValueRef function; LLVMValueRef alloca_point; @@ -193,8 +195,8 @@ void llvm_value_struct_gep(GenContext *c, BEValue *element, BEValue *struct_poin LLVMValueRef llvm_value_rvalue_store(GenContext *c, BEValue *value); LLVMTypeRef llvm_abi_type(GenContext *c, AbiType *type); -unsigned llvm_abi_size(LLVMTypeRef type); -AlignSize llvm_abi_alignment(LLVMTypeRef type); +unsigned llvm_abi_size(GenContext *c, LLVMTypeRef type); +AlignSize llvm_abi_alignment(GenContext *c, LLVMTypeRef type); void llvm_attribute_add_range(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, int index_start, int index_end); void llvm_attribute_add(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, int index); void llvm_attribute_add_string(GenContext *c, LLVMValueRef value_to_add_attribute_to, const char *attribute, const char *value, int index); @@ -211,7 +213,7 @@ void llvm_emit_block(GenContext *c, LLVMBasicBlockRef next_block); void llvm_emit_br(GenContext *c, LLVMBasicBlockRef next_block); void llvm_emit_compound_stmt(GenContext *context, Ast *ast); void llvm_emit_and_set_decl_alloca(GenContext *c, Decl *decl); -void llvm_emit_convert_value_from_coerced(GenContext *context, BEValue *result, LLVMTypeRef coerced, LLVMValueRef value, Type *original_type); +void llvm_emit_convert_value_from_coerced(GenContext *c, BEValue *result, LLVMTypeRef coerced, LLVMValueRef value, Type *original_type); void llvm_emit_function_body(GenContext *context, Decl *decl); void llvm_emit_function_decl(GenContext *c, Decl *decl); LLVMValueRef llvm_emit_call_intrinsic(GenContext *c, unsigned intrinsic_id, LLVMTypeRef *types, unsigned type_count, LLVMValueRef *values, unsigned arg_count); @@ -230,7 +232,7 @@ LLVMValueRef llvm_emit_int_comparison(GenContext *c, Type *lhs_type, Type *rhs_t LLVMValueRef llvm_emit_is_no_error_value(GenContext *c, BEValue *value); void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_len); -LLVMValueRef llvm_emit_load_aligned(GenContext *context, LLVMTypeRef type, LLVMValueRef pointer, AlignSize alignment, const char *name); +LLVMValueRef llvm_emit_load_aligned(GenContext *c, LLVMTypeRef type, LLVMValueRef pointer, AlignSize alignment, const char *name); void llvm_emit_local_var_alloca(GenContext *c, Decl *decl); void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr); LLVMValueRef llvm_emit_memclear_size_align(GenContext *c, LLVMValueRef ref, uint64_t size, unsigned align, bool bitcast); @@ -264,7 +266,7 @@ LLVMMetadataRef llvm_debug_current_scope(GenContext *context); bool llvm_emit_check_block_branch(GenContext *context); -unsigned llvm_store_size(LLVMTypeRef type); +unsigned llvm_store_size(GenContext *c, LLVMTypeRef type); void llvm_store_bevalue(GenContext *c, BEValue *destination, BEValue *value); void llvm_store_bevalue_raw(GenContext *c, BEValue *destination, LLVMValueRef raw_value); void llvm_store_bevalue_dest_aligned(GenContext *c, LLVMValueRef destination, BEValue *value); @@ -274,7 +276,7 @@ void llvm_store_aligned(GenContext *context, LLVMValueRef pointer, LLVMValueRef void llvm_store_aligned_decl(GenContext *context, Decl *decl, LLVMValueRef value); LLVMTypeRef llvm_get_twostruct(GenContext *context, LLVMTypeRef lo, LLVMTypeRef hi); -LLVMValueRef llvm_emit_coerce(GenContext *context, LLVMTypeRef coerced, BEValue *value, Type *original_type); +LLVMValueRef llvm_emit_coerce(GenContext *c, LLVMTypeRef coerced, BEValue *value, Type *original_type); static inline LLVMValueRef gencontext_emit_load(GenContext *c, Type *type, LLVMValueRef value) { diff --git a/src/compiler/llvm_codegen_module.c b/src/compiler/llvm_codegen_module.c index c82dc4b0a..af4850017 100644 --- a/src/compiler/llvm_codegen_module.c +++ b/src/compiler/llvm_codegen_module.c @@ -15,7 +15,9 @@ void gencontext_begin_module(GenContext *c) const char *full_path = c->ast_context->file->full_path; char *mangled_module_name = strformat("%s-%s", c->ast_context->module->name->module, c->ast_context->file->name); c->module = LLVMModuleCreateWithNameInContext(mangled_module_name, c->context); - LLVMSetModuleDataLayout(c->module, target_data_layout()); + c->machine = llvm_target_machine_create(); + c->target_data = LLVMCreateTargetDataLayout(c->machine); + LLVMSetModuleDataLayout(c->module, c->target_data); LLVMSetSourceFileName(c->module, full_path, strlen(c->ast_context->file->full_path)); LLVMTypeRef options_type = LLVMInt8TypeInContext(c->context); diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index fab885105..8d315d219 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -257,7 +257,7 @@ static inline Decl *parse_ct_switch_top_level(Context *context) static inline Path *parse_module_path(Context *context) { assert(TOKEN_IS(TOKEN_IDENT)); - char *scratch_ptr = context->path_scratch; + char *scratch_ptr = global_context.path_scratch; size_t offset = 0; SourceSpan span = source_span_from_token_id(context->tok.id); unsigned len = TOKLEN(context->tok); @@ -469,7 +469,7 @@ Path *parse_path_prefix(Context *context, bool *had_error) *had_error = false; if (!TOKEN_IS(TOKEN_IDENT) || context->next_tok.type != TOKEN_SCOPE) return NULL; - char *scratch_ptr = context->path_scratch; + char *scratch_ptr = global_context.path_scratch; size_t offset = 0; Path *path = CALLOCS(Path); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 0b44eaf29..38ceb14cb 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -373,7 +373,7 @@ static inline Type *sema_analyse_function_signature(Context *context, FunctionSi SEMA_ERROR(signature->params[MAX_PARAMS], "Number of params exceeds %d which is unsupported.", MAX_PARAMS); return false; } - STable *names = &context->scratch_table; + STable *names = &global_context.scratch_table; stable_clear(names); VECEACH(signature->params, i) @@ -1048,7 +1048,7 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl, Module *mo parameter_count, vec_size(decl->define_decl.params)); return false; } - char *param_path = c->path_scratch; + char *param_path = global_context.path_scratch; memcpy(param_path, module->name->module, module->name->len); unsigned offset = module->name->len; param_path[offset++] = '('; diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index 1c542f9df..5abf9ea3f 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -126,7 +126,7 @@ Decl *sema_resolve_symbol(Context *context, const char *symbol, Path *path, Decl if (context->current_scope) { - Decl **first = &context->locals[0]; + Decl **first = &global_context.locals[0]; if (context->macro_nesting) first = context->macro_locals_start; Decl **current = context->last_local - 1; while (current >= first) @@ -179,7 +179,7 @@ Decl *sema_resolve_symbol(Context *context, const char *symbol, Path *path, Decl static inline bool sema_append_local(Context *context, Decl *decl) { - if (context->last_local == &context->locals[MAX_LOCALS - 1]) + if (context->last_local == &global_context.locals[MAX_LOCALS - 1]) { SEMA_ERROR(decl, "Reached the maximum number of locals."); return false; diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index 84df69c25..1f28e6e5d 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -182,9 +182,9 @@ void sema_analysis_pass_decls(Context *context) if (context->module->parameters) return; DEBUG_LOG("Pass: Decl analysis %s", context->file->name); - context->current_scope = &context->scopes[0]; + context->current_scope = &global_context.scopes[0]; context->current_scope->scope_id = 0; - context->last_local = &context->locals[0]; + context->last_local = &global_context.locals[0]; VECEACH(context->enums, i) { sema_analyse_decl(context, context->enums[i]); diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 0b1ee90f7..8d0118b29 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -9,7 +9,7 @@ void context_push_scope_with_flags(Context *context, ScopeFlags flags) { - if (context->current_scope == &context->scopes[MAX_SCOPE_DEPTH - 1]) + if (context->current_scope == &global_context.scopes[MAX_SCOPE_DEPTH - 1]) { FATAL_ERROR("Too deeply nested scopes."); } @@ -67,7 +67,7 @@ static inline void context_pop_defers_to(Context *context, DeferList *list) void context_pop_scope(Context *context) { - assert(context->current_scope != &context->scopes[0]); + assert(context->current_scope != &global_context.scopes[0]); context->last_local = context->current_scope->local_decl_start; assert(context_start_defer(context) == context->current_scope->defer_last); @@ -114,7 +114,7 @@ static void context_pop_defers_and_replace_ast(Context *context, Ast *ast) AstId context_start_defer(Context *context) { - if (context->current_scope == context->scopes) return 0; + if (context->current_scope == global_context.scopes) return 0; if (context->current_scope->in_defer != context->current_scope[-1].in_defer) return 0; return context->current_scope[-1].defer_last; } @@ -933,7 +933,7 @@ static DynamicScope *context_find_scope_by_id(Context *context, ScopeId scope_id while (1) { if (scope->scope_id == scope_id) return scope; - assert(scope != &context->scopes[0]); + assert(scope != &global_context.scopes[0]); scope--; } UNREACHABLE @@ -968,7 +968,7 @@ static inline Decl *sema_analyse_label(Context *context, Ast *stmt) static bool context_labels_exist_in_scope(Context *context) { - for (Decl **from = &context->locals[0]; from < context->last_local; from++) + for (Decl **from = &global_context.locals[0]; from < context->last_local; from++) { if ((*from)->decl_kind == DECL_LABEL) return true; } @@ -1919,7 +1919,7 @@ bool sema_analyse_function_body(Context *context, Decl *func) FunctionSignature *signature = &func->func.function_signature; context->active_function_for_analysis = func; context->rtype = signature->rtype->type; - context->current_scope = &context->scopes[0]; + context->current_scope = &global_context.scopes[0]; context->current_scope->scope_id = 0; context->failable_return = signature->failable; @@ -1929,9 +1929,8 @@ bool sema_analyse_function_body(Context *context, Decl *func) // Clear returns vec_resize(context->returns, 0); context->scope_id = 0; - context->returns = NULL; context->expected_block_type = NULL; - context->last_local = &context->locals[0]; + context->last_local = &global_context.locals[0]; context->in_volatile_section = 0; context->macro_counter = 0; context->macro_nesting = 0; @@ -1942,13 +1941,13 @@ bool sema_analyse_function_body(Context *context, Decl *func) func->func.annotations = CALLOCS(FuncAnnotations); context_push_scope(context); Decl **params = signature->params; - assert(context->current_scope == &context->scopes[1]); + assert(context->current_scope == &global_context.scopes[1]); VECEACH(params, i) { if (!sema_add_local(context, params[i])) return false; } if (!sema_analyse_compound_statement_no_scope(context, func->func.body)) return false; - assert(context->current_scope == &context->scopes[1]); + assert(context->current_scope == &global_context.scopes[1]); if (!context->current_scope->jump_end) { Type *canonical_rtype = signature->rtype->type->canonical; diff --git a/src/compiler/target.c b/src/compiler/target.c index a0e664091..ff15065b0 100644 --- a/src/compiler/target.c +++ b/src/compiler/target.c @@ -375,22 +375,6 @@ static char *arch_to_target_triple[ARCH_OS_TARGET_LAST + 1] = { void target_destroy() { - assert(platform_target.machine); - LLVMDisposeTargetMachine(platform_target.machine); -} - -void *target_target() -{ - return platform_target.target; -} - -void *target_machine() -{ - return platform_target.machine; -} -void *target_data_layout() -{ - return platform_target.llvm_data_layout; } static bool arch_is_supported(ArchType arch) @@ -1046,38 +1030,54 @@ static unsigned os_target_pref_alignment_of_float(OsType os, ArchType arch, int UNREACHABLE } +void *llvm_target_machine_create(void) +{ + char *err = NULL; + LLVMTargetRef target = NULL; + if (LLVMGetTargetFromTriple(platform_target.target_triple, &target, &err) != 0) + { + error_exit("Could not create target: %s for triple '%s'", err, platform_target.target_triple); + // Usually we would dispose of err, but no need to do it due to exit. + } + void *result = LLVMCreateTargetMachine(target, platform_target.target_triple, + platform_target.cpu ?: "", platform_target.features ?: "", + (LLVMCodeGenOptLevel)platform_target.llvm_opt_level, + (LLVMRelocMode)platform_target.llvm_reloc_mode, LLVMCodeModelDefault); + if (!result) error_exit("Failed to create target machine."); + return result; +} + + +#define INITIALIZE_TARGET(X) do { \ + DEBUG_LOG("Initialize target: %s.", #X); \ + LLVMInitialize ## X ## AsmParser(); \ + LLVMInitialize ## X ## AsmPrinter(); \ + LLVMInitialize ## X ## TargetInfo(); \ + LLVMInitialize ## X ## Target(); \ + LLVMInitialize ## X ## Disassembler(); \ + LLVMInitialize ## X ## TargetMC(); \ + } while(0) + void target_setup(BuildTarget *target) { - assert(!platform_target.target); + INITIALIZE_TARGET(ARM); + INITIALIZE_TARGET(AArch64); + INITIALIZE_TARGET(RISCV); + INITIALIZE_TARGET(WebAssembly); + INITIALIZE_TARGET(X86); + // To support more targets, add them above. - LLVMInitializeAllTargetInfos(); - LLVMInitializeAllTargetMCs(); - LLVMInitializeAllTargets(); - LLVMInitializeAllAsmPrinters(); - LLVMInitializeAllAsmParsers(); - - platform_target.target = NULL; - - const char *triple; if (target->arch_os_target == ARCH_OS_TARGET_DEFAULT) { - triple = LLVMGetDefaultTargetTriple(); + platform_target.target_triple = LLVMGetDefaultTargetTriple(); } else { - triple = arch_to_target_triple[target->arch_os_target]; - } - - char *err = NULL; - if (LLVMGetTargetFromTriple(triple, ((LLVMTargetRef *)&platform_target.target), &err) != 0) - { - error_exit("Could not create target: %s", err); - // Usually we would dispose of err, but no need to do it due to exit. + platform_target.target_triple = arch_to_target_triple[target->arch_os_target]; } platform_target.alloca_address_space = 0; - DEBUG_LOG("Target set to %s.", triple); // Create a specific target machine LLVMCodeGenOptLevel level; LLVMRelocMode reloc_mode = LLVMRelocDefault; @@ -1123,19 +1123,15 @@ void target_setup(BuildTarget *target) reloc_mode = LLVMRelocStatic; } - /* - if (!opt->features) - { - opt->features = ""; - }*/ - if (!(platform_target.machine = LLVMCreateTargetMachine(platform_target.target, triple, "", "", level, reloc_mode, - LLVMCodeModelDefault))) { - error_exit("Failed to create target machine."); - } + DEBUG_LOG("Feature and CPU not checked."); - platform_target.llvm_data_layout = LLVMCreateTargetDataLayout(platform_target.machine); + platform_target.llvm_opt_level = (int)level; + platform_target.llvm_reloc_mode = (int)reloc_mode; + DEBUG_LOG("Triple picked was %s.", platform_target.target_triple); - char *target_triple = LLVMGetTargetMachineTriple(platform_target.machine); + LLVMTargetMachineRef machine = llvm_target_machine_create(); + char *target_triple = LLVMGetTargetMachineTriple(machine); + LLVMDisposeTargetMachine(machine); platform_target.target_triple = strdup(target_triple); platform_target.arch = arch_from_llvm_string(strtok(target_triple, "-")); @@ -1153,7 +1149,6 @@ void target_setup(BuildTarget *target) platform_target.float_abi = false; platform_target.little_endian = arch_little_endian(platform_target.arch); platform_target.width_pointer = arch_pointer_bit_width(platform_target.os, platform_target.arch); - assert(platform_target.width_pointer == LLVMPointerSize(platform_target.llvm_data_layout) * 8); platform_target.alloca_address_space = 0; // Todo PIC or no PIC depending on architecture. diff --git a/src/compiler/target.h b/src/compiler/target.h index 28d2baf51..4941d2ced 100644 --- a/src/compiler/target.h +++ b/src/compiler/target.h @@ -235,10 +235,11 @@ typedef enum typedef struct { - void *target; - void *machine; - void *llvm_data_layout; const char *target_triple; + int llvm_opt_level; + int llvm_reloc_mode; + const char *features; + const char *cpu; ArchType arch; OsType os; VendorType vendor;