Begin cleanup for allowing for multiple LLVM modules

This commit is contained in:
gingerBill
2021-05-03 15:26:40 +01:00
parent 0d044eabac
commit b44a56118e
3 changed files with 320 additions and 279 deletions
+304 -276
View File
@@ -12912,12 +12912,15 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
void lb_init_module(lbModule *m, Checker *c) {
m->info = &c->info;
#if 0
m->ctx = LLVMGetGlobalContext();
#else
gbString module_name = nullptr;
if (m->pkg) {
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();
#endif
m->mod = LLVMModuleCreateWithNameInContext("odin_module", m->ctx);
m->mod = LLVMModuleCreateWithNameInContext(module_name ? module_name : "odin_package", m->ctx);
// m->debug_builder = nullptr;
if (build_context.ODIN_DEBUG) {
enum {DEBUG_METADATA_VERSION = 3};
@@ -13012,8 +13015,18 @@ bool lb_init_generator(lbGenerator *gen, Checker *c) {
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;
}
@@ -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(&params->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) {
#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");
lbModule *m = &gen->module;
LLVMModuleRef mod = gen->module.mod;
lbModule *m = &gen->default_module;
CheckerInfo *info = gen->info;
auto *min_dep_set = &info->minimum_dependency_set;
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargets();
LLVMInitializeAllTargetMCs();
@@ -13853,16 +14109,19 @@ void lb_generate_code(lbGenerator *gen) {
LLVMInitializeAllDisassemblers();
LLVMInitializeNativeTarget();
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);
LLVMSetTarget(mod, target_triple);
for_array(i, gen->modules.entries) {
LLVMSetTarget(gen->modules.entries[i].value->mod, target_triple);
}
LLVMTargetRef target = {};
char *llvm_error = nullptr;
LLVMGetTargetFromTriple(target_triple, &target, &llvm_error);
GB_ASSERT(target != nullptr);
TIME_SECTION("LLVM Create Target Machine");
LLVMCodeModel code_mode = LLVMCodeModelDefault;
@@ -13905,7 +14164,9 @@ void lb_generate_code(lbGenerator *gen) {
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
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;
// 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);
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)));
LLVMSetLinkage(g, LLVMInternalLinkage);
@@ -13998,7 +14259,7 @@ void lb_generate_code(lbGenerator *gen) {
{
char const *name = LB_TYPE_INFO_TYPES_NAME;
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)));
LLVMSetLinkage(g, LLVMInternalLinkage);
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;
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)));
LLVMSetLinkage(g, LLVMInternalLinkage);
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;
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)));
LLVMSetLinkage(g, LLVMInternalLinkage);
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;
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)));
LLVMSetLinkage(g, LLVMInternalLinkage);
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;
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)));
LLVMSetLinkage(g, LLVMInternalLinkage);
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;
lbValue init;
DeclInfo *decl;
bool is_initialized;
};
auto global_variables = array_make<GlobalVariable>(permanent_allocator(), 0, global_variable_max_count);
auto global_variables = array_make<lbGlobalVariable>(permanent_allocator(), 0, global_variable_max_count);
for_array(i, info->variable_init_order) {
DeclInfo *d = info->variable_init_order[i];
@@ -14141,7 +14397,7 @@ void lb_generate_code(lbGenerator *gen) {
LLVMSetLinkage(g.value, LLVMInternalLinkage);
}
GlobalVariable var = {};
lbGlobalVariable var = {};
var.var = g;
var.decl = decl;
@@ -14259,10 +14515,10 @@ void lb_generate_code(lbGenerator *gen) {
LLVMPassRegistryRef pass_registry = LLVMGetGlobalPassRegistry();
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(mod);
LLVMPassManagerRef function_pass_manager_minimal = LLVMCreateFunctionPassManagerForModule(mod);
LLVMPassManagerRef function_pass_manager_size = LLVMCreateFunctionPassManagerForModule(mod);
LLVMPassManagerRef function_pass_manager_speed = LLVMCreateFunctionPassManagerForModule(mod);
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
LLVMPassManagerRef function_pass_manager_minimal = LLVMCreateFunctionPassManagerForModule(m->mod);
LLVMPassManagerRef function_pass_manager_size = LLVMCreateFunctionPassManagerForModule(m->mod);
LLVMPassManagerRef function_pass_manager_speed = LLVMCreateFunctionPassManagerForModule(m->mod);
defer (LLVMDisposePassManager(default_function_pass_manager));
defer (LLVMDisposePassManager(function_pass_manager_minimal));
defer (LLVMDisposePassManager(function_pass_manager_size));
@@ -14284,142 +14540,18 @@ void lb_generate_code(lbGenerator *gen) {
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));
LLVMInitializeFunctionPassManager(default_function_pass_manager_without_memcpy);
lb_populate_function_pass_manager(default_function_pass_manager_without_memcpy, true, build_context.optimization_level);
LLVMFinalizeFunctionPassManager(default_function_pass_manager_without_memcpy);
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)");
{ // Startup Runtime
Type *params = alloc_type_tuple();
Type *results = alloc_type_tuple();
lbProcedure *startup_runtime = lb_create_startup_runtime(m, startup_type_info, global_variables);
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"));
@@ -14453,7 +14585,7 @@ void lb_generate_code(lbGenerator *gen) {
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
LLVMDumpValue(p->value);
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);
}
LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
@@ -14463,117 +14595,8 @@ void lb_generate_code(lbGenerator *gen) {
if (!(build_context.build_mode == BuildMode_DynamicLibrary && !has_dll_main)) {
TIME_SECTION("LLVM DLL main");
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(&params->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);
TIME_SECTION("LLVM main");
lb_create_main_procedure(m, startup_runtime);
}
@@ -14583,7 +14606,7 @@ void lb_generate_code(lbGenerator *gen) {
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_exit(1);
return;
@@ -14594,7 +14617,9 @@ void lb_generate_code(lbGenerator *gen) {
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) {
lbProcedure *p = m->procedures_to_generate[i];
if (p->body != nullptr) { // Build Procedure
@@ -14640,7 +14665,10 @@ void lb_generate_code(lbGenerator *gen) {
defer (LLVMDisposePassManager(module_pass_manager));
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;
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);
if (build_context.keep_temp_files) {
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_exit(1);
return;
@@ -14684,7 +14712,7 @@ void lb_generate_code(lbGenerator *gen) {
if (build_context.keep_temp_files ||
build_context.build_mode == BuildMode_LLVM_IR) {
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_exit(1);
return;
@@ -14697,7 +14725,7 @@ void lb_generate_code(lbGenerator *gen) {
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_exit(1);
return;
+3 -1
View File
@@ -86,6 +86,7 @@ struct lbModule {
LLVMContextRef ctx;
CheckerInfo *info;
AstPackage *pkg; // associated
gbMutex mutex;
@@ -124,12 +125,13 @@ struct lbModule {
};
struct lbGenerator {
lbModule module;
CheckerInfo *info;
Array<String> output_object_paths;
String output_base;
String output_name;
Map<lbModule *> modules; // Key: AstPackage *
lbModule default_module;
};
+13 -2
View File
@@ -218,8 +218,19 @@ i32 linker_stage(lbGenerator *gen) {
add_path(find_result.vs_library_path);
}
for_array(i, gen->module.foreign_library_paths) {
String lib = gen->module.foreign_library_paths[i];
for_array(j, gen->modules.entries) {
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);
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" \"%.*s\"", LIT(lib));