mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Begin cleanup for allowing for multiple LLVM modules
This commit is contained in:
+304
-276
@@ -12912,12 +12912,15 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
void lb_init_module(lbModule *m, Checker *c) {
|
void lb_init_module(lbModule *m, Checker *c) {
|
||||||
m->info = &c->info;
|
m->info = &c->info;
|
||||||
|
|
||||||
#if 0
|
gbString module_name = nullptr;
|
||||||
m->ctx = LLVMGetGlobalContext();
|
if (m->pkg) {
|
||||||
#else
|
module_name = gb_string_make(heap_allocator(), "odin_package-");
|
||||||
|
module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
m->ctx = LLVMContextCreate();
|
m->ctx = LLVMContextCreate();
|
||||||
#endif
|
m->mod = LLVMModuleCreateWithNameInContext(module_name ? module_name : "odin_package", m->ctx);
|
||||||
m->mod = LLVMModuleCreateWithNameInContext("odin_module", m->ctx);
|
|
||||||
// m->debug_builder = nullptr;
|
// m->debug_builder = nullptr;
|
||||||
if (build_context.ODIN_DEBUG) {
|
if (build_context.ODIN_DEBUG) {
|
||||||
enum {DEBUG_METADATA_VERSION = 3};
|
enum {DEBUG_METADATA_VERSION = 3};
|
||||||
@@ -13012,8 +13015,18 @@ bool lb_init_generator(lbGenerator *gen, Checker *c) {
|
|||||||
|
|
||||||
gen->info = &c->info;
|
gen->info = &c->info;
|
||||||
|
|
||||||
lb_init_module(&gen->module, c);
|
map_init(&gen->modules, permanent_allocator(), gen->info->packages.entries.count*2);
|
||||||
|
|
||||||
|
for_array(i, gen->info->packages.entries) {
|
||||||
|
AstPackage *pkg = gen->info->packages.entries[i].value;
|
||||||
|
|
||||||
|
auto m = gb_alloc_item(permanent_allocator(), lbModule);
|
||||||
|
m->pkg = pkg;
|
||||||
|
map_set(&gen->modules, hash_pointer(pkg), m);
|
||||||
|
lb_init_module(m, c);
|
||||||
|
}
|
||||||
|
map_set(&gen->modules, hash_pointer(nullptr), &gen->default_module);
|
||||||
|
lb_init_module(&gen->default_module, c);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -13833,18 +13846,261 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct lbGlobalVariable {
|
||||||
|
lbValue var;
|
||||||
|
lbValue init;
|
||||||
|
DeclInfo *decl;
|
||||||
|
bool is_initialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
lbProcedure *lb_create_startup_type_info(lbModule *m) {
|
||||||
|
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
|
||||||
|
defer (LLVMDisposePassManager(default_function_pass_manager));
|
||||||
|
lb_populate_function_pass_manager(default_function_pass_manager, false, build_context.optimization_level);
|
||||||
|
LLVMFinalizeFunctionPassManager(default_function_pass_manager);
|
||||||
|
|
||||||
|
Type *params = alloc_type_tuple();
|
||||||
|
Type *results = alloc_type_tuple();
|
||||||
|
|
||||||
|
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl);
|
||||||
|
|
||||||
|
lbProcedure *p = lb_create_dummy_procedure(m, str_lit(LB_STARTUP_TYPE_INFO_PROC_NAME), proc_type);
|
||||||
|
p->is_startup = true;
|
||||||
|
|
||||||
|
lb_begin_procedure_body(p);
|
||||||
|
|
||||||
|
lb_setup_type_info_data(p);
|
||||||
|
|
||||||
|
lb_end_procedure_body(p);
|
||||||
|
|
||||||
|
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
||||||
|
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
|
||||||
|
LLVMDumpValue(p->value);
|
||||||
|
gb_printf_err("\n\n\n\n");
|
||||||
|
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbProcedure *lb_create_startup_runtime(lbModule *m, lbProcedure *startup_type_info, Array<lbGlobalVariable> &global_variables) { // Startup Runtime
|
||||||
|
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
|
||||||
|
defer (LLVMDisposePassManager(default_function_pass_manager));
|
||||||
|
lb_populate_function_pass_manager(default_function_pass_manager, false, build_context.optimization_level);
|
||||||
|
LLVMFinalizeFunctionPassManager(default_function_pass_manager);
|
||||||
|
|
||||||
|
Type *params = alloc_type_tuple();
|
||||||
|
Type *results = alloc_type_tuple();
|
||||||
|
|
||||||
|
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl);
|
||||||
|
|
||||||
|
lbProcedure *p = lb_create_dummy_procedure(m, str_lit(LB_STARTUP_RUNTIME_PROC_NAME), proc_type);
|
||||||
|
p->is_startup = true;
|
||||||
|
|
||||||
|
lb_begin_procedure_body(p);
|
||||||
|
|
||||||
|
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, startup_type_info->type)), startup_type_info->value, nullptr, 0, "");
|
||||||
|
|
||||||
|
for_array(i, global_variables) {
|
||||||
|
auto *var = &global_variables[i];
|
||||||
|
if (var->is_initialized) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity *e = var->decl->entity;
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
|
||||||
|
if (var->decl->init_expr != nullptr) {
|
||||||
|
// gb_printf_err("%s\n", expr_to_string(var->decl->init_expr));
|
||||||
|
lbValue init = lb_build_expr(p, var->decl->init_expr);
|
||||||
|
LLVMValueKind value_kind = LLVMGetValueKind(init.value);
|
||||||
|
// gb_printf_err("%s %d\n", LLVMPrintValueToString(init.value));
|
||||||
|
|
||||||
|
if (lb_is_const_or_global(init)) {
|
||||||
|
if (!var->is_initialized) {
|
||||||
|
LLVMSetInitializer(var->var.value, init.value);
|
||||||
|
var->is_initialized = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var->init = init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var->init.value != nullptr) {
|
||||||
|
GB_ASSERT(!var->is_initialized);
|
||||||
|
Type *t = type_deref(var->var.type);
|
||||||
|
|
||||||
|
if (is_type_any(t)) {
|
||||||
|
// NOTE(bill): Edge case for 'any' type
|
||||||
|
Type *var_type = default_type(var->init.type);
|
||||||
|
lbAddr g = lb_add_global_generated(m, var_type, var->init);
|
||||||
|
lb_addr_store(p, g, var->init);
|
||||||
|
lbValue gp = lb_addr_get_ptr(p, g);
|
||||||
|
|
||||||
|
lbValue data = lb_emit_struct_ep(p, var->var, 0);
|
||||||
|
lbValue ti = lb_emit_struct_ep(p, var->var, 1);
|
||||||
|
lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr));
|
||||||
|
lb_emit_store(p, ti, lb_type_info(m, var_type));
|
||||||
|
} else {
|
||||||
|
LLVMTypeRef pvt = LLVMTypeOf(var->var.value);
|
||||||
|
LLVMTypeRef vt = LLVMGetElementType(pvt);
|
||||||
|
lbValue src0 = lb_emit_conv(p, var->init, t);
|
||||||
|
LLVMValueRef src = OdinLLVMBuildTransmute(p, src0.value, vt);
|
||||||
|
LLVMValueRef dst = var->var.value;
|
||||||
|
LLVMBuildStore(p->builder, src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
var->is_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lb_end_procedure_body(p);
|
||||||
|
|
||||||
|
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
||||||
|
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
|
||||||
|
LLVMDumpValue(p->value);
|
||||||
|
gb_printf_err("\n\n\n\n");
|
||||||
|
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime) {
|
||||||
|
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
|
||||||
|
defer (LLVMDisposePassManager(default_function_pass_manager));
|
||||||
|
lb_populate_function_pass_manager(default_function_pass_manager, false, build_context.optimization_level);
|
||||||
|
LLVMFinalizeFunctionPassManager(default_function_pass_manager);
|
||||||
|
|
||||||
|
Type *params = alloc_type_tuple();
|
||||||
|
Type *results = alloc_type_tuple();
|
||||||
|
|
||||||
|
Type *t_ptr_cstring = alloc_type_pointer(t_cstring);
|
||||||
|
|
||||||
|
String name = str_lit("main");
|
||||||
|
if (build_context.metrics.os == TargetOs_windows && build_context.metrics.arch == TargetArch_386) {
|
||||||
|
name = str_lit("mainCRTStartup");
|
||||||
|
} else {
|
||||||
|
array_init(¶ms->Tuple.variables, permanent_allocator(), 2);
|
||||||
|
params->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("argc"), t_i32, false, true);
|
||||||
|
params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("argv"), t_ptr_cstring, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_init(&results->Tuple.variables, permanent_allocator(), 1);
|
||||||
|
results->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("_"), t_i32, false, true);
|
||||||
|
|
||||||
|
Type *proc_type = alloc_type_proc(nullptr,
|
||||||
|
params, params->Tuple.variables.count,
|
||||||
|
results, results->Tuple.variables.count, false, ProcCC_CDecl);
|
||||||
|
|
||||||
|
|
||||||
|
lbProcedure *p = lb_create_dummy_procedure(m, name, proc_type);
|
||||||
|
p->is_startup = true;
|
||||||
|
|
||||||
|
lb_begin_procedure_body(p);
|
||||||
|
|
||||||
|
{ // initialize `runtime.args__`
|
||||||
|
lbValue argc = {LLVMGetParam(p->value, 0), t_i32};
|
||||||
|
argc = lb_emit_conv(p, argc, t_int);
|
||||||
|
lbValue argv = {LLVMGetParam(p->value, 1), t_ptr_cstring};
|
||||||
|
lbAddr args = lb_addr(lb_find_runtime_value(p->module, str_lit("args__")));
|
||||||
|
lb_fill_slice(p, args, argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, startup_runtime->type)), startup_runtime->value, nullptr, 0, "");
|
||||||
|
|
||||||
|
if (build_context.command_kind == Command_test) {
|
||||||
|
Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test"));
|
||||||
|
Type *array_type = alloc_type_array(t_Internal_Test, m->info->testing_procedures.count);
|
||||||
|
Type *slice_type = alloc_type_slice(t_Internal_Test);
|
||||||
|
lbAddr all_tests_array_addr = lb_add_global_generated(p->module, array_type, {});
|
||||||
|
lbValue all_tests_array = lb_addr_get_ptr(p, all_tests_array_addr);
|
||||||
|
|
||||||
|
LLVMTypeRef lbt_Internal_Test = lb_type(m, t_Internal_Test);
|
||||||
|
|
||||||
|
LLVMValueRef indices[2] = {};
|
||||||
|
indices[0] = LLVMConstInt(lb_type(m, t_i32), 0, false);
|
||||||
|
|
||||||
|
for_array(i, m->info->testing_procedures) {
|
||||||
|
Entity *testing_proc = m->info->testing_procedures[i];
|
||||||
|
String name = testing_proc->token.string;
|
||||||
|
lbValue *found = map_get(&m->values, hash_entity(testing_proc));
|
||||||
|
GB_ASSERT(found != nullptr);
|
||||||
|
|
||||||
|
String pkg_name = {};
|
||||||
|
if (testing_proc->pkg != nullptr) {
|
||||||
|
pkg_name = testing_proc->pkg->name;
|
||||||
|
}
|
||||||
|
lbValue v_pkg = lb_find_or_add_entity_string(m, pkg_name);
|
||||||
|
lbValue v_name = lb_find_or_add_entity_string(m, name);
|
||||||
|
lbValue v_proc = *found;
|
||||||
|
|
||||||
|
indices[1] = LLVMConstInt(lb_type(m, t_int), i, false);
|
||||||
|
|
||||||
|
LLVMValueRef vals[3] = {};
|
||||||
|
vals[0] = v_pkg.value;
|
||||||
|
vals[1] = v_name.value;
|
||||||
|
vals[2] = v_proc.value;
|
||||||
|
GB_ASSERT(LLVMIsConstant(vals[0]));
|
||||||
|
GB_ASSERT(LLVMIsConstant(vals[1]));
|
||||||
|
GB_ASSERT(LLVMIsConstant(vals[2]));
|
||||||
|
|
||||||
|
LLVMValueRef dst = LLVMConstInBoundsGEP(all_tests_array.value, indices, gb_count_of(indices));
|
||||||
|
LLVMValueRef src = llvm_const_named_struct(lbt_Internal_Test, vals, gb_count_of(vals));
|
||||||
|
|
||||||
|
LLVMBuildStore(p->builder, src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
lbAddr all_tests_slice = lb_add_local_generated(p, slice_type, true);
|
||||||
|
lb_fill_slice(p, all_tests_slice,
|
||||||
|
lb_array_elem(p, all_tests_array),
|
||||||
|
lb_const_int(m, t_int, m->info->testing_procedures.count));
|
||||||
|
|
||||||
|
|
||||||
|
lbValue runner = lb_find_package_value(m, str_lit("testing"), str_lit("runner"));
|
||||||
|
|
||||||
|
auto args = array_make<lbValue>(heap_allocator(), 1);
|
||||||
|
args[0] = lb_addr_load(p, all_tests_slice);
|
||||||
|
lb_emit_call(p, runner, args);
|
||||||
|
} else {
|
||||||
|
lbValue *found = map_get(&m->values, hash_entity(m->info->entry_point));
|
||||||
|
GB_ASSERT(found != nullptr);
|
||||||
|
lb_emit_call(p, *found, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false));
|
||||||
|
|
||||||
|
lb_end_procedure_body(p);
|
||||||
|
|
||||||
|
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
||||||
|
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
|
||||||
|
LLVMDumpValue(p->value);
|
||||||
|
gb_printf_err("\n\n\n\n");
|
||||||
|
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void lb_generate_code(lbGenerator *gen) {
|
void lb_generate_code(lbGenerator *gen) {
|
||||||
#define TIME_SECTION(str) do { if (build_context.show_more_timings) timings_start_section(&global_timings, str_lit(str)); } while (0)
|
#define TIME_SECTION(str) do { if (build_context.show_more_timings) timings_start_section(&global_timings, str_lit(str)); } while (0)
|
||||||
|
|
||||||
TIME_SECTION("LLVM Initializtion");
|
TIME_SECTION("LLVM Initializtion");
|
||||||
|
|
||||||
lbModule *m = &gen->module;
|
lbModule *m = &gen->default_module;
|
||||||
LLVMModuleRef mod = gen->module.mod;
|
|
||||||
CheckerInfo *info = gen->info;
|
CheckerInfo *info = gen->info;
|
||||||
|
|
||||||
auto *min_dep_set = &info->minimum_dependency_set;
|
auto *min_dep_set = &info->minimum_dependency_set;
|
||||||
|
|
||||||
|
|
||||||
LLVMInitializeAllTargetInfos();
|
LLVMInitializeAllTargetInfos();
|
||||||
LLVMInitializeAllTargets();
|
LLVMInitializeAllTargets();
|
||||||
LLVMInitializeAllTargetMCs();
|
LLVMInitializeAllTargetMCs();
|
||||||
@@ -13853,16 +14109,19 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
LLVMInitializeAllDisassemblers();
|
LLVMInitializeAllDisassemblers();
|
||||||
LLVMInitializeNativeTarget();
|
LLVMInitializeNativeTarget();
|
||||||
|
|
||||||
|
|
||||||
char const *target_triple = alloc_cstring(permanent_allocator(), build_context.metrics.target_triplet);
|
char const *target_triple = alloc_cstring(permanent_allocator(), build_context.metrics.target_triplet);
|
||||||
char const *target_data_layout = alloc_cstring(permanent_allocator(), build_context.metrics.target_data_layout);
|
char const *target_data_layout = alloc_cstring(permanent_allocator(), build_context.metrics.target_data_layout);
|
||||||
LLVMSetTarget(mod, target_triple);
|
for_array(i, gen->modules.entries) {
|
||||||
|
LLVMSetTarget(gen->modules.entries[i].value->mod, target_triple);
|
||||||
|
}
|
||||||
|
|
||||||
LLVMTargetRef target = {};
|
LLVMTargetRef target = {};
|
||||||
char *llvm_error = nullptr;
|
char *llvm_error = nullptr;
|
||||||
LLVMGetTargetFromTriple(target_triple, &target, &llvm_error);
|
LLVMGetTargetFromTriple(target_triple, &target, &llvm_error);
|
||||||
GB_ASSERT(target != nullptr);
|
GB_ASSERT(target != nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TIME_SECTION("LLVM Create Target Machine");
|
TIME_SECTION("LLVM Create Target Machine");
|
||||||
|
|
||||||
LLVMCodeModel code_mode = LLVMCodeModelDefault;
|
LLVMCodeModel code_mode = LLVMCodeModelDefault;
|
||||||
@@ -13905,7 +14164,9 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
defer (LLVMDisposeTargetMachine(target_machine));
|
defer (LLVMDisposeTargetMachine(target_machine));
|
||||||
|
|
||||||
|
|
||||||
LLVMSetModuleDataLayout(mod, LLVMCreateTargetDataLayout(target_machine));
|
for_array(i, gen->modules.entries) {
|
||||||
|
LLVMSetModuleDataLayout(gen->modules.entries[i].value->mod, LLVMCreateTargetDataLayout(target_machine));
|
||||||
|
}
|
||||||
|
|
||||||
if (m->debug_builder) { // Debug Info
|
if (m->debug_builder) { // Debug Info
|
||||||
for_array(i, info->files.entries) {
|
for_array(i, info->files.entries) {
|
||||||
@@ -13960,7 +14221,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
isize max_type_info_count = info->minimum_dependency_type_info_set.entries.count+1;
|
isize max_type_info_count = info->minimum_dependency_type_info_set.entries.count+1;
|
||||||
// gb_printf_err("max_type_info_count: %td\n", max_type_info_count);
|
// gb_printf_err("max_type_info_count: %td\n", max_type_info_count);
|
||||||
Type *t = alloc_type_array(t_type_info, max_type_info_count);
|
Type *t = alloc_type_array(t_type_info, max_type_info_count);
|
||||||
LLVMValueRef g = LLVMAddGlobal(mod, lb_type(m, t), LB_TYPE_INFO_DATA_NAME);
|
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), LB_TYPE_INFO_DATA_NAME);
|
||||||
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
||||||
LLVMSetLinkage(g, LLVMInternalLinkage);
|
LLVMSetLinkage(g, LLVMInternalLinkage);
|
||||||
|
|
||||||
@@ -13998,7 +14259,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
{
|
{
|
||||||
char const *name = LB_TYPE_INFO_TYPES_NAME;
|
char const *name = LB_TYPE_INFO_TYPES_NAME;
|
||||||
Type *t = alloc_type_array(t_type_info_ptr, count);
|
Type *t = alloc_type_array(t_type_info_ptr, count);
|
||||||
LLVMValueRef g = LLVMAddGlobal(mod, lb_type(m, t), name);
|
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||||
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
||||||
LLVMSetLinkage(g, LLVMInternalLinkage);
|
LLVMSetLinkage(g, LLVMInternalLinkage);
|
||||||
lb_global_type_info_member_types = lb_addr({g, alloc_type_pointer(t)});
|
lb_global_type_info_member_types = lb_addr({g, alloc_type_pointer(t)});
|
||||||
@@ -14007,7 +14268,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
{
|
{
|
||||||
char const *name = LB_TYPE_INFO_NAMES_NAME;
|
char const *name = LB_TYPE_INFO_NAMES_NAME;
|
||||||
Type *t = alloc_type_array(t_string, count);
|
Type *t = alloc_type_array(t_string, count);
|
||||||
LLVMValueRef g = LLVMAddGlobal(mod, lb_type(m, t), name);
|
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||||
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
||||||
LLVMSetLinkage(g, LLVMInternalLinkage);
|
LLVMSetLinkage(g, LLVMInternalLinkage);
|
||||||
lb_global_type_info_member_names = lb_addr({g, alloc_type_pointer(t)});
|
lb_global_type_info_member_names = lb_addr({g, alloc_type_pointer(t)});
|
||||||
@@ -14015,7 +14276,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
{
|
{
|
||||||
char const *name = LB_TYPE_INFO_OFFSETS_NAME;
|
char const *name = LB_TYPE_INFO_OFFSETS_NAME;
|
||||||
Type *t = alloc_type_array(t_uintptr, count);
|
Type *t = alloc_type_array(t_uintptr, count);
|
||||||
LLVMValueRef g = LLVMAddGlobal(mod, lb_type(m, t), name);
|
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||||
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
||||||
LLVMSetLinkage(g, LLVMInternalLinkage);
|
LLVMSetLinkage(g, LLVMInternalLinkage);
|
||||||
lb_global_type_info_member_offsets = lb_addr({g, alloc_type_pointer(t)});
|
lb_global_type_info_member_offsets = lb_addr({g, alloc_type_pointer(t)});
|
||||||
@@ -14024,7 +14285,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
{
|
{
|
||||||
char const *name = LB_TYPE_INFO_USINGS_NAME;
|
char const *name = LB_TYPE_INFO_USINGS_NAME;
|
||||||
Type *t = alloc_type_array(t_bool, count);
|
Type *t = alloc_type_array(t_bool, count);
|
||||||
LLVMValueRef g = LLVMAddGlobal(mod, lb_type(m, t), name);
|
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||||
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
||||||
LLVMSetLinkage(g, LLVMInternalLinkage);
|
LLVMSetLinkage(g, LLVMInternalLinkage);
|
||||||
lb_global_type_info_member_usings = lb_addr({g, alloc_type_pointer(t)});
|
lb_global_type_info_member_usings = lb_addr({g, alloc_type_pointer(t)});
|
||||||
@@ -14033,7 +14294,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
{
|
{
|
||||||
char const *name = LB_TYPE_INFO_TAGS_NAME;
|
char const *name = LB_TYPE_INFO_TAGS_NAME;
|
||||||
Type *t = alloc_type_array(t_string, count);
|
Type *t = alloc_type_array(t_string, count);
|
||||||
LLVMValueRef g = LLVMAddGlobal(mod, lb_type(m, t), name);
|
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||||
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
||||||
LLVMSetLinkage(g, LLVMInternalLinkage);
|
LLVMSetLinkage(g, LLVMInternalLinkage);
|
||||||
lb_global_type_info_member_tags = lb_addr({g, alloc_type_pointer(t)});
|
lb_global_type_info_member_tags = lb_addr({g, alloc_type_pointer(t)});
|
||||||
@@ -14073,13 +14334,8 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GlobalVariable {
|
|
||||||
lbValue var;
|
auto global_variables = array_make<lbGlobalVariable>(permanent_allocator(), 0, global_variable_max_count);
|
||||||
lbValue init;
|
|
||||||
DeclInfo *decl;
|
|
||||||
bool is_initialized;
|
|
||||||
};
|
|
||||||
auto global_variables = array_make<GlobalVariable>(permanent_allocator(), 0, global_variable_max_count);
|
|
||||||
|
|
||||||
for_array(i, info->variable_init_order) {
|
for_array(i, info->variable_init_order) {
|
||||||
DeclInfo *d = info->variable_init_order[i];
|
DeclInfo *d = info->variable_init_order[i];
|
||||||
@@ -14141,7 +14397,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
LLVMSetLinkage(g.value, LLVMInternalLinkage);
|
LLVMSetLinkage(g.value, LLVMInternalLinkage);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalVariable var = {};
|
lbGlobalVariable var = {};
|
||||||
var.var = g;
|
var.var = g;
|
||||||
var.decl = decl;
|
var.decl = decl;
|
||||||
|
|
||||||
@@ -14259,10 +14515,10 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
|
|
||||||
LLVMPassRegistryRef pass_registry = LLVMGetGlobalPassRegistry();
|
LLVMPassRegistryRef pass_registry = LLVMGetGlobalPassRegistry();
|
||||||
|
|
||||||
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(mod);
|
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
|
||||||
LLVMPassManagerRef function_pass_manager_minimal = LLVMCreateFunctionPassManagerForModule(mod);
|
LLVMPassManagerRef function_pass_manager_minimal = LLVMCreateFunctionPassManagerForModule(m->mod);
|
||||||
LLVMPassManagerRef function_pass_manager_size = LLVMCreateFunctionPassManagerForModule(mod);
|
LLVMPassManagerRef function_pass_manager_size = LLVMCreateFunctionPassManagerForModule(m->mod);
|
||||||
LLVMPassManagerRef function_pass_manager_speed = LLVMCreateFunctionPassManagerForModule(mod);
|
LLVMPassManagerRef function_pass_manager_speed = LLVMCreateFunctionPassManagerForModule(m->mod);
|
||||||
defer (LLVMDisposePassManager(default_function_pass_manager));
|
defer (LLVMDisposePassManager(default_function_pass_manager));
|
||||||
defer (LLVMDisposePassManager(function_pass_manager_minimal));
|
defer (LLVMDisposePassManager(function_pass_manager_minimal));
|
||||||
defer (LLVMDisposePassManager(function_pass_manager_size));
|
defer (LLVMDisposePassManager(function_pass_manager_size));
|
||||||
@@ -14284,142 +14540,18 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
LLVMFinalizeFunctionPassManager(function_pass_manager_speed);
|
LLVMFinalizeFunctionPassManager(function_pass_manager_speed);
|
||||||
|
|
||||||
|
|
||||||
LLVMPassManagerRef default_function_pass_manager_without_memcpy = LLVMCreateFunctionPassManagerForModule(mod);
|
LLVMPassManagerRef default_function_pass_manager_without_memcpy = LLVMCreateFunctionPassManagerForModule(m->mod);
|
||||||
defer (LLVMDisposePassManager(default_function_pass_manager_without_memcpy));
|
defer (LLVMDisposePassManager(default_function_pass_manager_without_memcpy));
|
||||||
LLVMInitializeFunctionPassManager(default_function_pass_manager_without_memcpy);
|
LLVMInitializeFunctionPassManager(default_function_pass_manager_without_memcpy);
|
||||||
lb_populate_function_pass_manager(default_function_pass_manager_without_memcpy, true, build_context.optimization_level);
|
lb_populate_function_pass_manager(default_function_pass_manager_without_memcpy, true, build_context.optimization_level);
|
||||||
LLVMFinalizeFunctionPassManager(default_function_pass_manager_without_memcpy);
|
LLVMFinalizeFunctionPassManager(default_function_pass_manager_without_memcpy);
|
||||||
|
|
||||||
TIME_SECTION("LLVM Runtime Type Information Creation");
|
TIME_SECTION("LLVM Runtime Type Information Creation");
|
||||||
|
lbProcedure *startup_type_info = lb_create_startup_type_info(m);
|
||||||
|
|
||||||
lbProcedure *startup_type_info = nullptr;
|
|
||||||
lbProcedure *startup_runtime = nullptr;
|
|
||||||
{ // Startup Type Info
|
|
||||||
Type *params = alloc_type_tuple();
|
|
||||||
Type *results = alloc_type_tuple();
|
|
||||||
|
|
||||||
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl);
|
|
||||||
|
|
||||||
lbProcedure *p = lb_create_dummy_procedure(m, str_lit(LB_STARTUP_TYPE_INFO_PROC_NAME), proc_type);
|
|
||||||
p->is_startup = true;
|
|
||||||
startup_type_info = p;
|
|
||||||
|
|
||||||
lb_begin_procedure_body(p);
|
|
||||||
|
|
||||||
lb_setup_type_info_data(p);
|
|
||||||
|
|
||||||
lb_end_procedure_body(p);
|
|
||||||
|
|
||||||
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
|
||||||
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
|
|
||||||
LLVMDumpValue(p->value);
|
|
||||||
gb_printf_err("\n\n\n\n");
|
|
||||||
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
|
||||||
}
|
|
||||||
TIME_SECTION("LLVM Runtime Startup Creation (Global Variables)");
|
TIME_SECTION("LLVM Runtime Startup Creation (Global Variables)");
|
||||||
{ // Startup Runtime
|
lbProcedure *startup_runtime = lb_create_startup_runtime(m, startup_type_info, global_variables);
|
||||||
Type *params = alloc_type_tuple();
|
|
||||||
Type *results = alloc_type_tuple();
|
|
||||||
|
|
||||||
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl);
|
|
||||||
|
|
||||||
lbProcedure *p = lb_create_dummy_procedure(m, str_lit(LB_STARTUP_RUNTIME_PROC_NAME), proc_type);
|
|
||||||
p->is_startup = true;
|
|
||||||
startup_runtime = p;
|
|
||||||
|
|
||||||
lb_begin_procedure_body(p);
|
|
||||||
|
|
||||||
|
|
||||||
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, startup_type_info->type)), startup_type_info->value, nullptr, 0, "");
|
|
||||||
|
|
||||||
for_array(i, global_variables) {
|
|
||||||
auto *var = &global_variables[i];
|
|
||||||
if (var->is_initialized) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity *e = var->decl->entity;
|
|
||||||
GB_ASSERT(e->kind == Entity_Variable);
|
|
||||||
|
|
||||||
if (var->decl->init_expr != nullptr) {
|
|
||||||
// gb_printf_err("%s\n", expr_to_string(var->decl->init_expr));
|
|
||||||
lbValue init = lb_build_expr(p, var->decl->init_expr);
|
|
||||||
LLVMValueKind value_kind = LLVMGetValueKind(init.value);
|
|
||||||
// gb_printf_err("%s %d\n", LLVMPrintValueToString(init.value));
|
|
||||||
|
|
||||||
if (lb_is_const_or_global(init)) {
|
|
||||||
if (!var->is_initialized) {
|
|
||||||
LLVMSetInitializer(var->var.value, init.value);
|
|
||||||
var->is_initialized = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var->init = init;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var->init.value != nullptr) {
|
|
||||||
GB_ASSERT(!var->is_initialized);
|
|
||||||
Type *t = type_deref(var->var.type);
|
|
||||||
|
|
||||||
if (is_type_any(t)) {
|
|
||||||
// NOTE(bill): Edge case for 'any' type
|
|
||||||
Type *var_type = default_type(var->init.type);
|
|
||||||
lbAddr g = lb_add_global_generated(m, var_type, var->init);
|
|
||||||
lb_addr_store(p, g, var->init);
|
|
||||||
lbValue gp = lb_addr_get_ptr(p, g);
|
|
||||||
|
|
||||||
lbValue data = lb_emit_struct_ep(p, var->var, 0);
|
|
||||||
lbValue ti = lb_emit_struct_ep(p, var->var, 1);
|
|
||||||
lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr));
|
|
||||||
lb_emit_store(p, ti, lb_type_info(m, var_type));
|
|
||||||
} else {
|
|
||||||
LLVMTypeRef pvt = LLVMTypeOf(var->var.value);
|
|
||||||
LLVMTypeRef vt = LLVMGetElementType(pvt);
|
|
||||||
lbValue src0 = lb_emit_conv(p, var->init, t);
|
|
||||||
LLVMValueRef src = OdinLLVMBuildTransmute(p, src0.value, vt);
|
|
||||||
LLVMValueRef dst = var->var.value;
|
|
||||||
LLVMBuildStore(p->builder, src, dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
var->is_initialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
lb_end_procedure_body(p);
|
|
||||||
|
|
||||||
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
|
||||||
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
|
|
||||||
LLVMDumpValue(p->value);
|
|
||||||
gb_printf_err("\n\n\n\n");
|
|
||||||
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
|
||||||
|
|
||||||
/*{
|
|
||||||
LLVMValueRef last_instr = LLVMGetLastInstruction(p->decl_block->block);
|
|
||||||
for (LLVMValueRef instr = LLVMGetFirstInstruction(p->decl_block->block);
|
|
||||||
instr != last_instr;
|
|
||||||
instr = LLVMGetNextInstruction(instr)) {
|
|
||||||
if (LLVMIsAAllocaInst(instr)) {
|
|
||||||
LLVMTypeRef type = LLVMGetAllocatedType(instr);
|
|
||||||
LLVMValueRef sz_val = LLVMSizeOf(type);
|
|
||||||
GB_ASSERT(LLVMIsConstant(sz_val));
|
|
||||||
gb_printf_err(">> 0x%p\n", sz_val);
|
|
||||||
LLVMTypeRef sz_type = LLVMTypeOf(sz_val);
|
|
||||||
gb_printf_err(">> %s\n", LLVMPrintTypeToString(sz_type));
|
|
||||||
unsigned long long sz = LLVMConstIntGetZExtValue(sz_val);
|
|
||||||
// long long sz = LLVMConstIntGetSExtValue(sz_val);
|
|
||||||
gb_printf_err(">> %ll\n", sz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
String filepath_ll = concatenate_strings(permanent_allocator(), gen->output_base, STR_LIT(".ll"));
|
String filepath_ll = concatenate_strings(permanent_allocator(), gen->output_base, STR_LIT(".ll"));
|
||||||
|
|
||||||
@@ -14453,7 +14585,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
|
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
|
||||||
LLVMDumpValue(p->value);
|
LLVMDumpValue(p->value);
|
||||||
gb_printf_err("\n\n\n\n");
|
gb_printf_err("\n\n\n\n");
|
||||||
if (LLVMPrintModuleToFile(mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
||||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||||
}
|
}
|
||||||
LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
|
LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
|
||||||
@@ -14463,117 +14595,8 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
|
|
||||||
|
|
||||||
if (!(build_context.build_mode == BuildMode_DynamicLibrary && !has_dll_main)) {
|
if (!(build_context.build_mode == BuildMode_DynamicLibrary && !has_dll_main)) {
|
||||||
TIME_SECTION("LLVM DLL main");
|
TIME_SECTION("LLVM main");
|
||||||
|
lb_create_main_procedure(m, startup_runtime);
|
||||||
|
|
||||||
Type *params = alloc_type_tuple();
|
|
||||||
Type *results = alloc_type_tuple();
|
|
||||||
|
|
||||||
Type *t_ptr_cstring = alloc_type_pointer(t_cstring);
|
|
||||||
|
|
||||||
String name = str_lit("main");
|
|
||||||
if (build_context.metrics.os == TargetOs_windows && build_context.metrics.arch == TargetArch_386) {
|
|
||||||
name = str_lit("mainCRTStartup");
|
|
||||||
} else {
|
|
||||||
array_init(¶ms->Tuple.variables, permanent_allocator(), 2);
|
|
||||||
params->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("argc"), t_i32, false, true);
|
|
||||||
params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("argv"), t_ptr_cstring, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
array_init(&results->Tuple.variables, permanent_allocator(), 1);
|
|
||||||
results->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("_"), t_i32, false, true);
|
|
||||||
|
|
||||||
Type *proc_type = alloc_type_proc(nullptr,
|
|
||||||
params, params->Tuple.variables.count,
|
|
||||||
results, results->Tuple.variables.count, false, ProcCC_CDecl);
|
|
||||||
|
|
||||||
|
|
||||||
lbProcedure *p = lb_create_dummy_procedure(m, name, proc_type);
|
|
||||||
p->is_startup = true;
|
|
||||||
|
|
||||||
lb_begin_procedure_body(p);
|
|
||||||
|
|
||||||
{ // initialize `runtime.args__`
|
|
||||||
lbValue argc = {LLVMGetParam(p->value, 0), t_i32};
|
|
||||||
argc = lb_emit_conv(p, argc, t_int);
|
|
||||||
lbValue argv = {LLVMGetParam(p->value, 1), t_ptr_cstring};
|
|
||||||
lbAddr args = lb_addr(lb_find_runtime_value(p->module, str_lit("args__")));
|
|
||||||
lb_fill_slice(p, args, argv, argc);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, startup_runtime->type)), startup_runtime->value, nullptr, 0, "");
|
|
||||||
|
|
||||||
if (build_context.command_kind == Command_test) {
|
|
||||||
Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test"));
|
|
||||||
Type *array_type = alloc_type_array(t_Internal_Test, m->info->testing_procedures.count);
|
|
||||||
Type *slice_type = alloc_type_slice(t_Internal_Test);
|
|
||||||
lbAddr all_tests_array_addr = lb_add_global_generated(p->module, array_type, {});
|
|
||||||
lbValue all_tests_array = lb_addr_get_ptr(p, all_tests_array_addr);
|
|
||||||
|
|
||||||
LLVMTypeRef lbt_Internal_Test = lb_type(m, t_Internal_Test);
|
|
||||||
|
|
||||||
LLVMValueRef indices[2] = {};
|
|
||||||
indices[0] = LLVMConstInt(lb_type(m, t_i32), 0, false);
|
|
||||||
|
|
||||||
for_array(i, m->info->testing_procedures) {
|
|
||||||
Entity *testing_proc = m->info->testing_procedures[i];
|
|
||||||
String name = testing_proc->token.string;
|
|
||||||
lbValue *found = map_get(&m->values, hash_entity(testing_proc));
|
|
||||||
GB_ASSERT(found != nullptr);
|
|
||||||
|
|
||||||
String pkg_name = {};
|
|
||||||
if (testing_proc->pkg != nullptr) {
|
|
||||||
pkg_name = testing_proc->pkg->name;
|
|
||||||
}
|
|
||||||
lbValue v_pkg = lb_find_or_add_entity_string(m, pkg_name);
|
|
||||||
lbValue v_name = lb_find_or_add_entity_string(m, name);
|
|
||||||
lbValue v_proc = *found;
|
|
||||||
|
|
||||||
indices[1] = LLVMConstInt(lb_type(m, t_int), i, false);
|
|
||||||
|
|
||||||
LLVMValueRef vals[3] = {};
|
|
||||||
vals[0] = v_pkg.value;
|
|
||||||
vals[1] = v_name.value;
|
|
||||||
vals[2] = v_proc.value;
|
|
||||||
GB_ASSERT(LLVMIsConstant(vals[0]));
|
|
||||||
GB_ASSERT(LLVMIsConstant(vals[1]));
|
|
||||||
GB_ASSERT(LLVMIsConstant(vals[2]));
|
|
||||||
|
|
||||||
LLVMValueRef dst = LLVMConstInBoundsGEP(all_tests_array.value, indices, gb_count_of(indices));
|
|
||||||
LLVMValueRef src = llvm_const_named_struct(lbt_Internal_Test, vals, gb_count_of(vals));
|
|
||||||
|
|
||||||
LLVMBuildStore(p->builder, src, dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
lbAddr all_tests_slice = lb_add_local_generated(p, slice_type, true);
|
|
||||||
lb_fill_slice(p, all_tests_slice,
|
|
||||||
lb_array_elem(p, all_tests_array),
|
|
||||||
lb_const_int(m, t_int, m->info->testing_procedures.count));
|
|
||||||
|
|
||||||
|
|
||||||
lbValue runner = lb_find_package_value(m, str_lit("testing"), str_lit("runner"));
|
|
||||||
|
|
||||||
auto args = array_make<lbValue>(heap_allocator(), 1);
|
|
||||||
args[0] = lb_addr_load(p, all_tests_slice);
|
|
||||||
lb_emit_call(p, runner, args);
|
|
||||||
} else {
|
|
||||||
lbValue *found = map_get(&m->values, hash_entity(entry_point));
|
|
||||||
GB_ASSERT(found != nullptr);
|
|
||||||
lb_emit_call(p, *found, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false));
|
|
||||||
|
|
||||||
lb_end_procedure_body(p);
|
|
||||||
|
|
||||||
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
|
||||||
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
|
|
||||||
LLVMDumpValue(p->value);
|
|
||||||
gb_printf_err("\n\n\n\n");
|
|
||||||
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -14583,7 +14606,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
|
|
||||||
|
|
||||||
TIME_SECTION("LLVM Print Module to File");
|
TIME_SECTION("LLVM Print Module to File");
|
||||||
if (LLVMPrintModuleToFile(mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
||||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||||
gb_exit(1);
|
gb_exit(1);
|
||||||
return;
|
return;
|
||||||
@@ -14594,7 +14617,9 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
|
|
||||||
|
|
||||||
TIME_SECTION("LLVM Function Pass");
|
TIME_SECTION("LLVM Function Pass");
|
||||||
{
|
for_array(i, gen->modules.entries) {
|
||||||
|
lbModule *m = gen->modules.entries[i].value;
|
||||||
|
|
||||||
for_array(i, m->procedures_to_generate) {
|
for_array(i, m->procedures_to_generate) {
|
||||||
lbProcedure *p = m->procedures_to_generate[i];
|
lbProcedure *p = m->procedures_to_generate[i];
|
||||||
if (p->body != nullptr) { // Build Procedure
|
if (p->body != nullptr) { // Build Procedure
|
||||||
@@ -14640,7 +14665,10 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
defer (LLVMDisposePassManager(module_pass_manager));
|
defer (LLVMDisposePassManager(module_pass_manager));
|
||||||
lb_populate_module_pass_manager(target_machine, module_pass_manager, build_context.optimization_level);
|
lb_populate_module_pass_manager(target_machine, module_pass_manager, build_context.optimization_level);
|
||||||
|
|
||||||
LLVMRunPassManager(module_pass_manager, mod);
|
for_array(i, gen->modules.entries) {
|
||||||
|
lbModule *m = gen->modules.entries[i].value;
|
||||||
|
LLVMRunPassManager(module_pass_manager, m->mod);
|
||||||
|
}
|
||||||
|
|
||||||
llvm_error = nullptr;
|
llvm_error = nullptr;
|
||||||
defer (LLVMDisposeMessage(llvm_error));
|
defer (LLVMDisposeMessage(llvm_error));
|
||||||
@@ -14667,11 +14695,11 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LLVMVerifyModule(mod, LLVMReturnStatusAction, &llvm_error)) {
|
if (LLVMVerifyModule(m->mod, LLVMReturnStatusAction, &llvm_error)) {
|
||||||
gb_printf_err("LLVM Error:\n%s\n", llvm_error);
|
gb_printf_err("LLVM Error:\n%s\n", llvm_error);
|
||||||
if (build_context.keep_temp_files) {
|
if (build_context.keep_temp_files) {
|
||||||
TIME_SECTION("LLVM Print Module to File");
|
TIME_SECTION("LLVM Print Module to File");
|
||||||
if (LLVMPrintModuleToFile(mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
||||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||||
gb_exit(1);
|
gb_exit(1);
|
||||||
return;
|
return;
|
||||||
@@ -14684,7 +14712,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
if (build_context.keep_temp_files ||
|
if (build_context.keep_temp_files ||
|
||||||
build_context.build_mode == BuildMode_LLVM_IR) {
|
build_context.build_mode == BuildMode_LLVM_IR) {
|
||||||
TIME_SECTION("LLVM Print Module to File");
|
TIME_SECTION("LLVM Print Module to File");
|
||||||
if (LLVMPrintModuleToFile(mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
||||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||||
gb_exit(1);
|
gb_exit(1);
|
||||||
return;
|
return;
|
||||||
@@ -14697,7 +14725,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
|
|
||||||
TIME_SECTION("LLVM Object Generation");
|
TIME_SECTION("LLVM Object Generation");
|
||||||
|
|
||||||
if (LLVMTargetMachineEmitToFile(target_machine, mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) {
|
if (LLVMTargetMachineEmitToFile(target_machine, m->mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) {
|
||||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||||
gb_exit(1);
|
gb_exit(1);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ struct lbModule {
|
|||||||
LLVMContextRef ctx;
|
LLVMContextRef ctx;
|
||||||
|
|
||||||
CheckerInfo *info;
|
CheckerInfo *info;
|
||||||
|
AstPackage *pkg; // associated
|
||||||
|
|
||||||
gbMutex mutex;
|
gbMutex mutex;
|
||||||
|
|
||||||
@@ -124,12 +125,13 @@ struct lbModule {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct lbGenerator {
|
struct lbGenerator {
|
||||||
lbModule module;
|
|
||||||
CheckerInfo *info;
|
CheckerInfo *info;
|
||||||
|
|
||||||
Array<String> output_object_paths;
|
Array<String> output_object_paths;
|
||||||
String output_base;
|
String output_base;
|
||||||
String output_name;
|
String output_name;
|
||||||
|
Map<lbModule *> modules; // Key: AstPackage *
|
||||||
|
lbModule default_module;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+13
-2
@@ -218,8 +218,19 @@ i32 linker_stage(lbGenerator *gen) {
|
|||||||
add_path(find_result.vs_library_path);
|
add_path(find_result.vs_library_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
for_array(i, gen->module.foreign_library_paths) {
|
for_array(j, gen->modules.entries) {
|
||||||
String lib = gen->module.foreign_library_paths[i];
|
lbModule *m = gen->modules.entries[j].value;
|
||||||
|
for_array(i, m->foreign_library_paths) {
|
||||||
|
String lib = m->foreign_library_paths[i];
|
||||||
|
GB_ASSERT(lib.len < gb_count_of(lib_str_buf)-1);
|
||||||
|
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||||
|
" \"%.*s\"", LIT(lib));
|
||||||
|
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for_array(i, gen->default_module.foreign_library_paths) {
|
||||||
|
String lib = gen->default_module.foreign_library_paths[i];
|
||||||
GB_ASSERT(lib.len < gb_count_of(lib_str_buf)-1);
|
GB_ASSERT(lib.len < gb_count_of(lib_str_buf)-1);
|
||||||
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||||
" \"%.*s\"", LIT(lib));
|
" \"%.*s\"", LIT(lib));
|
||||||
|
|||||||
Reference in New Issue
Block a user