Allow use of pthreads to parallelize codegen.

This commit is contained in:
Christoffer Lerno
2021-05-09 17:17:37 +02:00
committed by Christoffer Lerno
parent f7919edb35
commit 15a65d0c97
15 changed files with 185 additions and 160 deletions

View File

@@ -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 <unistd.h>
#if PLATFORM_POSIX
#include <pthread.h>
#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)
{

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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);

View File

@@ -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++] = '(';

View File

@@ -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;

View File

@@ -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]);

View File

@@ -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;

View File

@@ -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.

View File

@@ -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;