mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-05 10:14:05 +00:00
Begin work on making LLVM backend work with multiple modules for possible faster compilation
This commit is contained in:
@@ -207,6 +207,8 @@ struct BuildContext {
|
||||
bool ignore_microsoft_magic;
|
||||
bool linker_map_file;
|
||||
|
||||
bool use_separate_modules;
|
||||
|
||||
u32 cmd_doc_flags;
|
||||
Array<String> extra_packages;
|
||||
|
||||
@@ -807,6 +809,10 @@ void init_build_context(TargetMetrics *cross_target) {
|
||||
bc->max_align = metrics->max_align;
|
||||
bc->link_flags = str_lit(" ");
|
||||
|
||||
if (bc->metrics.os == TargetOs_windows) {
|
||||
// bc->use_separate_modules = bc->optimization_level == 0;
|
||||
}
|
||||
|
||||
|
||||
// NOTE(zangent): The linker flags to set the build architecture are different
|
||||
// across OSs. It doesn't make sense to allocate extra data on the heap
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#ifndef USE_SEPARTE_MODULES
|
||||
#define USE_SEPARTE_MODULES build_context.use_separate_modules
|
||||
#endif
|
||||
|
||||
#include "llvm_backend.hpp"
|
||||
#include "llvm_abi.cpp"
|
||||
#include "llvm_backend_opt.cpp"
|
||||
@@ -74,6 +78,15 @@ bool lb_is_instr_terminating(LLVMValueRef instr) {
|
||||
|
||||
|
||||
|
||||
lbModule *lb_pkg_module(lbGenerator *gen, AstPackage *pkg) {
|
||||
auto *found = map_get(&gen->modules, hash_pointer(pkg));
|
||||
if (found) {
|
||||
return *found;
|
||||
}
|
||||
return &gen->default_module;
|
||||
}
|
||||
|
||||
|
||||
lbAddr lb_addr(lbValue addr) {
|
||||
lbAddr v = {lbAddr_Default, addr};
|
||||
if (addr.type != nullptr && is_type_relative_pointer(type_deref(addr.type))) {
|
||||
@@ -2528,10 +2541,17 @@ void lb_ensure_abi_function_type(lbModule *m, lbProcedure *p) {
|
||||
GB_ASSERT(p->abi_function_type != nullptr);
|
||||
}
|
||||
|
||||
lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
||||
lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) {
|
||||
GB_ASSERT(entity != nullptr);
|
||||
|
||||
String link_name = lb_get_entity_name(m, entity);
|
||||
String link_name = {};
|
||||
|
||||
if (ignore_body) {
|
||||
lbModule *other_module = lb_pkg_module(m->gen, entity->pkg);
|
||||
link_name = lb_get_entity_name(other_module, entity);
|
||||
} else {
|
||||
link_name = lb_get_entity_name(m, entity);
|
||||
}
|
||||
|
||||
{
|
||||
StringHashKey key = string_hash_string(link_name);
|
||||
@@ -2699,6 +2719,10 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ignore_body) {
|
||||
p->body = nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (m->debug_builder) { // Debug Information
|
||||
Type *bt = base_type(p->type);
|
||||
@@ -5484,9 +5508,10 @@ LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String const &str) {
|
||||
|
||||
isize max_len = 7+8+1;
|
||||
char *name = gb_alloc_array(permanent_allocator(), char, max_len);
|
||||
isize len = gb_snprintf(name, max_len, "csbs$%x", m->global_array_index);
|
||||
|
||||
u32 id = cast(u32)gb_atomic32_fetch_add(&m->gen->global_array_index, 1);
|
||||
isize len = gb_snprintf(name, max_len, "csbs$%x", id);
|
||||
len -= 1;
|
||||
m->global_array_index++;
|
||||
|
||||
LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name);
|
||||
LLVMSetInitializer(global_data, data);
|
||||
@@ -5526,9 +5551,9 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str)
|
||||
{
|
||||
isize max_len = 7+8+1;
|
||||
name = gb_alloc_array(permanent_allocator(), char, max_len);
|
||||
isize len = gb_snprintf(name, max_len, "csbs$%x", m->global_array_index);
|
||||
u32 id = cast(u32)gb_atomic32_fetch_add(&m->gen->global_array_index, 1);
|
||||
isize len = gb_snprintf(name, max_len, "csbs$%x", id);
|
||||
len -= 1;
|
||||
m->global_array_index++;
|
||||
}
|
||||
LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name);
|
||||
LLVMSetInitializer(global_data, data);
|
||||
@@ -5684,6 +5709,7 @@ LLVMValueRef lb_build_constant_array_values(lbModule *m, Type *type, Type *elem_
|
||||
}
|
||||
|
||||
lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) {
|
||||
GB_ASSERT(is_type_proc(e->type));
|
||||
e = strip_entity_wrapping(e);
|
||||
GB_ASSERT(e != nullptr);
|
||||
auto *found = map_get(&m->values, hash_entity(e));
|
||||
@@ -5691,8 +5717,14 @@ lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) {
|
||||
return *found;
|
||||
}
|
||||
|
||||
// TODO(bill): this is
|
||||
lbProcedure *missing_proc = lb_create_procedure(m, e);
|
||||
bool ignore_body = false;
|
||||
|
||||
if (USE_SEPARTE_MODULES) {
|
||||
lbModule *other_module = lb_pkg_module(m->gen, e->pkg);
|
||||
ignore_body = other_module != m;
|
||||
}
|
||||
|
||||
lbProcedure *missing_proc = lb_create_procedure(m, e, ignore_body);
|
||||
found = map_get(&m->values, hash_entity(e));
|
||||
if (found) {
|
||||
return *found;
|
||||
@@ -5702,6 +5734,47 @@ lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) {
|
||||
return {};
|
||||
}
|
||||
|
||||
lbValue lb_find_value_from_entity(lbModule *m, Entity *e) {
|
||||
e = strip_entity_wrapping(e);
|
||||
GB_ASSERT(e != nullptr);
|
||||
if (is_type_proc(e->type)) {
|
||||
return lb_find_procedure_value_from_entity(m, e);
|
||||
}
|
||||
|
||||
auto *found = map_get(&m->values, hash_entity(e));
|
||||
if (found) {
|
||||
return *found;
|
||||
}
|
||||
|
||||
if (USE_SEPARTE_MODULES) {
|
||||
lbModule *other_module = lb_pkg_module(m->gen, e->pkg);
|
||||
bool is_external = other_module != m;
|
||||
if (!is_external) {
|
||||
other_module = e->code_gen_module;
|
||||
is_external = other_module != m;
|
||||
}
|
||||
|
||||
if (is_external) {
|
||||
String name = lb_get_entity_name(other_module, e);
|
||||
|
||||
lbValue g = {};
|
||||
g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
|
||||
g.type = alloc_type_pointer(e->type);
|
||||
LLVMSetExternallyInitialized(g.value, true);
|
||||
|
||||
lb_add_entity(m, e, g);
|
||||
lb_add_member(m, name, g);
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
GB_PANIC("\n\tError in: %s, missing value %.*s\n", token_pos_to_string(e->token.pos), LIT(e->token.string));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_local) {
|
||||
LLVMContextRef ctx = m->ctx;
|
||||
@@ -5777,8 +5850,8 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
||||
} else {
|
||||
isize max_len = 7+8+1;
|
||||
char *str = gb_alloc_array(permanent_allocator(), char, max_len);
|
||||
isize len = gb_snprintf(str, max_len, "csba$%x", m->global_array_index);
|
||||
m->global_array_index++;
|
||||
u32 id = cast(u32)gb_atomic32_fetch_add(&m->gen->global_array_index, 1);
|
||||
isize len = gb_snprintf(str, max_len, "csba$%x", id);
|
||||
|
||||
String name = make_string(cast(u8 *)str, len-1);
|
||||
|
||||
@@ -8192,31 +8265,18 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
lbValue lb_emit_runtime_call(lbProcedure *p, char const *c_name, Array<lbValue> const &args) {
|
||||
// LLVMMetadataRef curr_loc = LLVMGetCurrentDebugLocation2(p->builder);
|
||||
// LLVMSetCurrentDebugLocation2(p->builder, nullptr);
|
||||
// defer (if (curr_loc) {
|
||||
// LLVMSetCurrentDebugLocation2(p->builder, curr_loc);
|
||||
// });
|
||||
|
||||
String name = make_string_c(c_name);
|
||||
|
||||
|
||||
AstPackage *pkg = p->module->info->runtime_package;
|
||||
lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name) {
|
||||
AstPackage *pkg = m->info->runtime_package;
|
||||
Entity *e = scope_lookup_current(pkg->scope, name);
|
||||
return lb_find_procedure_value_from_entity(m, e);
|
||||
}
|
||||
|
||||
lbValue *found = nullptr;
|
||||
if (p->module != e->code_gen_module) {
|
||||
gb_mutex_lock(&p->module->mutex);
|
||||
}
|
||||
GB_ASSERT(e->code_gen_module != nullptr);
|
||||
found = map_get(&e->code_gen_module->values, hash_entity(e));
|
||||
if (p->module != e->code_gen_module) {
|
||||
gb_mutex_unlock(&p->module->mutex);
|
||||
}
|
||||
|
||||
GB_ASSERT_MSG(found != nullptr, "%s", c_name);
|
||||
return lb_emit_call(p, *found, args);
|
||||
lbValue lb_emit_runtime_call(lbProcedure *p, char const *c_name, Array<lbValue> const &args) {
|
||||
String name = make_string_c(c_name);
|
||||
lbValue proc = lb_lookup_runtime_procedure(p->module, name);
|
||||
return lb_emit_call(p, proc, args);
|
||||
}
|
||||
|
||||
lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining, bool use_return_ptr_hint) {
|
||||
@@ -9946,24 +10006,6 @@ void lb_emit_increment(lbProcedure *p, lbValue addr) {
|
||||
|
||||
}
|
||||
|
||||
LLVMValueRef lb_lookup_runtime_procedure(lbModule *m, String const &name) {
|
||||
AstPackage *pkg = m->info->runtime_package;
|
||||
Entity *e = scope_lookup_current(pkg->scope, name);
|
||||
|
||||
lbValue *found = nullptr;
|
||||
if (m != e->code_gen_module) {
|
||||
gb_mutex_lock(&m->mutex);
|
||||
}
|
||||
GB_ASSERT(e->code_gen_module != nullptr);
|
||||
found = map_get(&e->code_gen_module->values, hash_entity(e));
|
||||
if (m != e->code_gen_module) {
|
||||
gb_mutex_unlock(&m->mutex);
|
||||
}
|
||||
GB_ASSERT(found != nullptr);
|
||||
|
||||
return found->value;
|
||||
}
|
||||
|
||||
lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *end_type) {
|
||||
GB_ASSERT(type_size_of(value.type) == type_size_of(end_type));
|
||||
|
||||
@@ -11122,6 +11164,44 @@ lbValue lb_emit_any_cast(lbProcedure *p, lbValue value, Type *type, TokenPos pos
|
||||
}
|
||||
|
||||
|
||||
lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *expr) {
|
||||
auto *found = map_get(&m->values, hash_entity(e));
|
||||
if (found) {
|
||||
auto v = *found;
|
||||
// NOTE(bill): This is because pointers are already pointers in LLVM
|
||||
if (is_type_proc(v.type)) {
|
||||
return v;
|
||||
}
|
||||
return lb_emit_load(p, v);
|
||||
} else if (e != nullptr && e->kind == Entity_Variable) {
|
||||
return lb_addr_load(p, lb_build_addr(p, expr));
|
||||
}
|
||||
|
||||
if (USE_SEPARTE_MODULES) {
|
||||
lbModule *other_module = lb_pkg_module(m->gen, e->pkg);
|
||||
if (other_module != m) {
|
||||
String name = lb_get_entity_name(other_module, e);
|
||||
|
||||
lbValue g = {};
|
||||
g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
|
||||
g.type = alloc_type_pointer(e->type);
|
||||
LLVMSetExternallyInitialized(g.value, true);
|
||||
|
||||
lb_add_entity(m, e, g);
|
||||
lb_add_member(m, name, g);
|
||||
return lb_emit_load(p, g);
|
||||
}
|
||||
}
|
||||
|
||||
String pkg = {};
|
||||
if (e->pkg) {
|
||||
pkg = e->pkg->name;
|
||||
}
|
||||
gb_printf_err("Error in: %s\n", token_pos_to_string(ast_token(expr).pos));
|
||||
GB_PANIC("nullptr value for expression from identifier: %.*s.%.*s (%p) : %s @ %p", LIT(pkg), LIT(e->token.string), e, type_to_string(e->type), expr);
|
||||
return {};
|
||||
}
|
||||
|
||||
lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
lbModule *m = p->module;
|
||||
|
||||
@@ -11211,24 +11291,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
}
|
||||
GB_ASSERT(e->kind != Entity_ProcGroup);
|
||||
|
||||
auto *found = map_get(&p->module->values, hash_entity(e));
|
||||
if (found) {
|
||||
auto v = *found;
|
||||
// NOTE(bill): This is because pointers are already pointers in LLVM
|
||||
if (is_type_proc(v.type)) {
|
||||
return v;
|
||||
}
|
||||
return lb_emit_load(p, v);
|
||||
} else if (e != nullptr && e->kind == Entity_Variable) {
|
||||
return lb_addr_load(p, lb_build_addr(p, expr));
|
||||
}
|
||||
gb_printf_err("Error in: %s\n", token_pos_to_string(i->token.pos));
|
||||
String pkg = {};
|
||||
if (e->pkg) {
|
||||
pkg = e->pkg->name;
|
||||
}
|
||||
GB_PANIC("nullptr value for expression from identifier: %.*s.%.*s (%p) : %s @ %p", LIT(pkg), LIT(e->token.string), e, type_to_string(e->type), expr);
|
||||
return {};
|
||||
return lb_find_ident(p, m, e, expr);
|
||||
case_end;
|
||||
|
||||
case_ast_node(de, DerefExpr, expr);
|
||||
@@ -11609,11 +11672,14 @@ lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *expr) {
|
||||
return lb_get_soa_variable_addr(p, e);
|
||||
}
|
||||
|
||||
|
||||
if (v.value == nullptr) {
|
||||
error(expr, "%.*s Unknown value: %.*s, entity: %p %.*s",
|
||||
LIT(p->name),
|
||||
LIT(e->token.string), e, LIT(entity_strings[e->kind]));
|
||||
GB_PANIC("Unknown value");
|
||||
return lb_addr(lb_find_value_from_entity(p->module, e));
|
||||
|
||||
// error(expr, "%.*s Unknown value: %.*s, entity: %p %.*s",
|
||||
// LIT(p->name),
|
||||
// LIT(e->token.string), e, LIT(entity_strings[e->kind]));
|
||||
// GB_PANIC("Unknown value");
|
||||
}
|
||||
|
||||
return lb_addr(v);
|
||||
@@ -13031,18 +13097,31 @@ bool lb_init_generator(lbGenerator *gen, Checker *c) {
|
||||
gen->info = &c->info;
|
||||
|
||||
map_init(&gen->modules, permanent_allocator(), gen->info->packages.entries.count*2);
|
||||
map_init(&gen->modules_through_ctx, permanent_allocator(), gen->info->packages.entries.count*2);
|
||||
|
||||
for_array(i, gen->info->packages.entries) {
|
||||
AstPackage *pkg = gen->info->packages.entries[i].value;
|
||||
if (USE_SEPARTE_MODULES) {
|
||||
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);
|
||||
auto m = gb_alloc_item(permanent_allocator(), lbModule);
|
||||
m->pkg = pkg;
|
||||
m->gen = gen;
|
||||
map_set(&gen->modules, hash_pointer(pkg), m);
|
||||
lb_init_module(m, c);
|
||||
}
|
||||
}
|
||||
|
||||
gen->default_module.gen = gen;
|
||||
map_set(&gen->modules, hash_pointer(nullptr), &gen->default_module);
|
||||
lb_init_module(&gen->default_module, c);
|
||||
|
||||
|
||||
for_array(i, gen->modules.entries) {
|
||||
lbModule *m = gen->modules.entries[i].value;
|
||||
LLVMContextRef ctx = LLVMGetModuleContext(m->mod);
|
||||
map_set(&gen->modules_through_ctx, hash_pointer(ctx), m);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13052,8 +13131,10 @@ lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value) {
|
||||
|
||||
isize max_len = 7+8+1;
|
||||
u8 *str = cast(u8 *)gb_alloc_array(permanent_allocator(), u8, max_len);
|
||||
isize len = gb_snprintf(cast(char *)str, max_len, "ggv$%x", m->global_generated_index);
|
||||
m->global_generated_index++;
|
||||
|
||||
u32 id = cast(u32)gb_atomic32_fetch_add(&m->gen->global_generated_index, 1);
|
||||
|
||||
isize len = gb_snprintf(cast(char *)str, max_len, "ggv$%x", id);
|
||||
String name = make_string(str, len-1);
|
||||
|
||||
Scope *scope = nullptr;
|
||||
@@ -13076,17 +13157,12 @@ lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value) {
|
||||
lbValue lb_find_runtime_value(lbModule *m, String const &name) {
|
||||
AstPackage *p = m->info->runtime_package;
|
||||
Entity *e = scope_lookup_current(p->scope, name);
|
||||
lbValue *found = map_get(&m->values, hash_entity(e));
|
||||
GB_ASSERT_MSG(found != nullptr, "Unable to find runtime value '%.*s'", LIT(name));
|
||||
lbValue value = *found;
|
||||
return value;
|
||||
return lb_find_value_from_entity(m, e);
|
||||
}
|
||||
lbValue lb_find_package_value(lbModule *m, String const &pkg, String const &name) {
|
||||
Entity *e = find_entity_in_pkg(m->info, pkg, name);
|
||||
lbValue *found = map_get(&m->values, hash_entity(e));
|
||||
GB_ASSERT_MSG(found != nullptr, "Unable to find value '%.*s.%.*s'", LIT(pkg), LIT(name));
|
||||
lbValue value = *found;
|
||||
return value;
|
||||
return lb_find_value_from_entity(m, e);
|
||||
}
|
||||
|
||||
lbValue lb_get_type_info_ptr(lbModule *m, Type *type) {
|
||||
@@ -13900,8 +13976,8 @@ lbProcedure *lb_create_startup_type_info(lbModule *m) {
|
||||
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);
|
||||
lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *startup_type_info, Array<lbGlobalVariable> &global_variables) { // Startup Runtime
|
||||
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(main_module->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);
|
||||
@@ -13911,12 +13987,12 @@ lbProcedure *lb_create_startup_runtime(lbModule *m, lbProcedure *startup_type_in
|
||||
|
||||
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);
|
||||
lbProcedure *p = lb_create_dummy_procedure(main_module, 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, "");
|
||||
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, "");
|
||||
|
||||
for_array(i, global_variables) {
|
||||
auto *var = &global_variables[i];
|
||||
@@ -13924,8 +14000,11 @@ lbProcedure *lb_create_startup_runtime(lbModule *m, lbProcedure *startup_type_in
|
||||
continue;
|
||||
}
|
||||
|
||||
lbModule *entity_module = main_module;
|
||||
|
||||
Entity *e = var->decl->entity;
|
||||
GB_ASSERT(e->kind == Entity_Variable);
|
||||
e->code_gen_module = entity_module;
|
||||
|
||||
if (var->decl->init_expr != nullptr) {
|
||||
// gb_printf_err("%s\n", expr_to_string(var->decl->init_expr));
|
||||
@@ -13951,14 +14030,14 @@ lbProcedure *lb_create_startup_runtime(lbModule *m, lbProcedure *startup_type_in
|
||||
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);
|
||||
lbAddr g = lb_add_global_generated(main_module, 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));
|
||||
lb_emit_store(p, ti, lb_type_info(main_module, var_type));
|
||||
} else {
|
||||
LLVMTypeRef pvt = LLVMTypeOf(var->var.value);
|
||||
LLVMTypeRef vt = LLVMGetElementType(pvt);
|
||||
@@ -13975,7 +14054,7 @@ lbProcedure *lb_create_startup_runtime(lbModule *m, lbProcedure *startup_type_in
|
||||
|
||||
lb_end_procedure_body(p);
|
||||
|
||||
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
||||
if (!main_module->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");
|
||||
@@ -14085,9 +14164,8 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
|
||||
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, {});
|
||||
lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point);
|
||||
lb_emit_call(p, entry_point, {});
|
||||
}
|
||||
|
||||
LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false));
|
||||
@@ -14105,13 +14183,51 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
|
||||
return p;
|
||||
}
|
||||
|
||||
String lb_filepath_ll_for_module(lbModule *m) {
|
||||
String path = m->gen->output_base;
|
||||
if (m->pkg) {
|
||||
path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name);
|
||||
}
|
||||
path = concatenate_strings(permanent_allocator(), path, STR_LIT(".ll"));
|
||||
|
||||
return path;
|
||||
}
|
||||
String lb_filepath_obj_for_module(lbModule *m) {
|
||||
String path = m->gen->output_base;
|
||||
if (m->pkg) {
|
||||
path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name);
|
||||
}
|
||||
|
||||
String ext = {};
|
||||
|
||||
if (build_context.build_mode == BuildMode_Assembly) {
|
||||
ext = STR_LIT(".S");
|
||||
} else {
|
||||
switch (build_context.metrics.os) {
|
||||
case TargetOs_windows:
|
||||
ext = STR_LIT(".obj");
|
||||
break;
|
||||
case TargetOs_darwin:
|
||||
case TargetOs_linux:
|
||||
case TargetOs_essence:
|
||||
ext = STR_LIT(".o");
|
||||
break;
|
||||
case TargetOs_js:
|
||||
ext = STR_LIT(".wasm-obj");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return concatenate_strings(permanent_allocator(), path, ext);
|
||||
}
|
||||
|
||||
|
||||
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->default_module;
|
||||
lbModule *default_module = &gen->default_module;
|
||||
CheckerInfo *info = gen->info;
|
||||
|
||||
auto *min_dep_set = &info->minimum_dependency_set;
|
||||
@@ -14183,62 +14299,67 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
LLVMSetModuleDataLayout(gen->modules.entries[i].value->mod, LLVMCreateTargetDataLayout(target_machine));
|
||||
}
|
||||
|
||||
if (m->debug_builder) { // Debug Info
|
||||
for_array(i, info->files.entries) {
|
||||
AstFile *f = info->files.entries[i].value;
|
||||
String fullpath = f->fullpath;
|
||||
String filename = remove_directory_from_path(fullpath);
|
||||
String directory = directory_from_path(fullpath);
|
||||
LLVMMetadataRef res = LLVMDIBuilderCreateFile(m->debug_builder,
|
||||
cast(char const *)filename.text, filename.len,
|
||||
cast(char const *)directory.text, directory.len);
|
||||
lb_set_llvm_metadata(m, f, res);
|
||||
for_array(i, gen->modules.entries) {
|
||||
lbModule *m = gen->modules.entries[i].value;
|
||||
if (m->debug_builder) { // Debug Info
|
||||
for_array(i, info->files.entries) {
|
||||
AstFile *f = info->files.entries[i].value;
|
||||
String fullpath = f->fullpath;
|
||||
String filename = remove_directory_from_path(fullpath);
|
||||
String directory = directory_from_path(fullpath);
|
||||
LLVMMetadataRef res = LLVMDIBuilderCreateFile(m->debug_builder,
|
||||
cast(char const *)filename.text, filename.len,
|
||||
cast(char const *)directory.text, directory.len);
|
||||
lb_set_llvm_metadata(m, f, res);
|
||||
}
|
||||
|
||||
gbString producer = gb_string_make(heap_allocator(), "odin");
|
||||
// producer = gb_string_append_fmt(producer, " version %.*s", LIT(ODIN_VERSION));
|
||||
// #ifdef NIGHTLY
|
||||
// producer = gb_string_appendc(producer, "-nightly");
|
||||
// #endif
|
||||
// #ifdef GIT_SHA
|
||||
// producer = gb_string_append_fmt(producer, "-%s", GIT_SHA);
|
||||
// #endif
|
||||
|
||||
gbString split_name = gb_string_make(heap_allocator(), "");
|
||||
|
||||
LLVMBool is_optimized = build_context.optimization_level > 0;
|
||||
AstFile *init_file = m->info->init_package->files[0];
|
||||
if (m->info->entry_point && m->info->entry_point->identifier && m->info->entry_point->identifier->file) {
|
||||
init_file = m->info->entry_point->identifier->file;
|
||||
}
|
||||
|
||||
LLVMBool split_debug_inlining = false;
|
||||
LLVMBool debug_info_for_profiling = false;
|
||||
|
||||
m->debug_compile_unit = LLVMDIBuilderCreateCompileUnit(m->debug_builder, LLVMDWARFSourceLanguageC99,
|
||||
lb_get_llvm_metadata(m, init_file),
|
||||
producer, gb_string_length(producer),
|
||||
is_optimized, "", 0,
|
||||
1, split_name, gb_string_length(split_name),
|
||||
LLVMDWARFEmissionFull,
|
||||
0, split_debug_inlining,
|
||||
debug_info_for_profiling,
|
||||
"", 0, // sys_root
|
||||
"", 0 // SDK
|
||||
);
|
||||
GB_ASSERT(m->debug_compile_unit != nullptr);
|
||||
}
|
||||
|
||||
gbString producer = gb_string_make(heap_allocator(), "odin");
|
||||
// producer = gb_string_append_fmt(producer, " version %.*s", LIT(ODIN_VERSION));
|
||||
// #ifdef NIGHTLY
|
||||
// producer = gb_string_appendc(producer, "-nightly");
|
||||
// #endif
|
||||
// #ifdef GIT_SHA
|
||||
// producer = gb_string_append_fmt(producer, "-%s", GIT_SHA);
|
||||
// #endif
|
||||
|
||||
gbString split_name = gb_string_make(heap_allocator(), "");
|
||||
|
||||
LLVMBool is_optimized = build_context.optimization_level > 0;
|
||||
AstFile *init_file = m->info->init_package->files[0];
|
||||
if (m->info->entry_point && m->info->entry_point->identifier && m->info->entry_point->identifier->file) {
|
||||
init_file = m->info->entry_point->identifier->file;
|
||||
}
|
||||
|
||||
LLVMBool split_debug_inlining = false;
|
||||
LLVMBool debug_info_for_profiling = false;
|
||||
|
||||
m->debug_compile_unit = LLVMDIBuilderCreateCompileUnit(m->debug_builder, LLVMDWARFSourceLanguageC99,
|
||||
lb_get_llvm_metadata(m, init_file),
|
||||
producer, gb_string_length(producer),
|
||||
is_optimized, "", 0,
|
||||
1, split_name, gb_string_length(split_name),
|
||||
LLVMDWARFEmissionFull,
|
||||
0, split_debug_inlining,
|
||||
debug_info_for_profiling,
|
||||
"", 0, // sys_root
|
||||
"", 0 // SDK
|
||||
);
|
||||
GB_ASSERT(m->debug_compile_unit != nullptr);
|
||||
}
|
||||
|
||||
TIME_SECTION("LLVM Global Variables");
|
||||
|
||||
{
|
||||
lbModule *m = default_module;
|
||||
|
||||
{ // Add type info data
|
||||
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(m->mod, lb_type(m, t), LB_TYPE_INFO_DATA_NAME);
|
||||
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
|
||||
LLVMSetLinkage(g, LLVMInternalLinkage);
|
||||
// LLVMSetLinkage(g, LLVMInternalLinkage);
|
||||
|
||||
lbValue value = {};
|
||||
value.value = g;
|
||||
@@ -14276,7 +14397,7 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
Type *t = alloc_type_array(t_type_info_ptr, count);
|
||||
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||
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)});
|
||||
|
||||
}
|
||||
@@ -14285,7 +14406,7 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
Type *t = alloc_type_array(t_string, count);
|
||||
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||
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)});
|
||||
}
|
||||
{
|
||||
@@ -14293,7 +14414,7 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
Type *t = alloc_type_array(t_uintptr, count);
|
||||
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||
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)});
|
||||
}
|
||||
|
||||
@@ -14302,7 +14423,7 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
Type *t = alloc_type_array(t_bool, count);
|
||||
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||
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)});
|
||||
}
|
||||
|
||||
@@ -14311,7 +14432,7 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
Type *t = alloc_type_array(t_string, count);
|
||||
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
|
||||
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)});
|
||||
}
|
||||
}
|
||||
@@ -14373,8 +14494,9 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
bool is_foreign = e->Variable.is_foreign;
|
||||
bool is_export = e->Variable.is_export;
|
||||
|
||||
String name = lb_get_entity_name(m, e);
|
||||
|
||||
lbModule *m = &gen->default_module;
|
||||
String name = lb_get_entity_name(m, e);
|
||||
|
||||
lbValue g = {};
|
||||
g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
|
||||
@@ -14409,7 +14531,7 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
}
|
||||
|
||||
if (e->flags & EntityFlag_Static) {
|
||||
LLVMSetLinkage(g.value, LLVMInternalLinkage);
|
||||
// LLVMSetLinkage(g.value, LLVMInternalLinkage);
|
||||
}
|
||||
|
||||
lbGlobalVariable var = {};
|
||||
@@ -14439,6 +14561,7 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
lb_add_entity(m, e, g);
|
||||
lb_add_member(m, name, g);
|
||||
|
||||
|
||||
if (m->debug_builder) {
|
||||
String global_name = e->token.string;
|
||||
if (global_name.len != 0 && global_name != "_") {
|
||||
@@ -14509,6 +14632,10 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lbModule *m = &gen->default_module;
|
||||
if (USE_SEPARTE_MODULES) {
|
||||
m = lb_pkg_module(gen, e->pkg);
|
||||
}
|
||||
|
||||
String mangled_name = lb_get_entity_name(m, e);
|
||||
|
||||
@@ -14526,108 +14653,70 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
}
|
||||
|
||||
|
||||
TIME_SECTION("LLVM Registry Initializtion");
|
||||
|
||||
LLVMPassRegistryRef pass_registry = LLVMGetGlobalPassRegistry();
|
||||
|
||||
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));
|
||||
defer (LLVMDisposePassManager(function_pass_manager_speed));
|
||||
|
||||
LLVMInitializeFunctionPassManager(default_function_pass_manager);
|
||||
LLVMInitializeFunctionPassManager(function_pass_manager_minimal);
|
||||
LLVMInitializeFunctionPassManager(function_pass_manager_size);
|
||||
LLVMInitializeFunctionPassManager(function_pass_manager_speed);
|
||||
|
||||
lb_populate_function_pass_manager(default_function_pass_manager, false, build_context.optimization_level);
|
||||
lb_populate_function_pass_manager_specific(function_pass_manager_minimal, 0);
|
||||
lb_populate_function_pass_manager_specific(function_pass_manager_size, 1);
|
||||
lb_populate_function_pass_manager_specific(function_pass_manager_speed, 2);
|
||||
|
||||
LLVMFinalizeFunctionPassManager(default_function_pass_manager);
|
||||
LLVMFinalizeFunctionPassManager(function_pass_manager_minimal);
|
||||
LLVMFinalizeFunctionPassManager(function_pass_manager_size);
|
||||
LLVMFinalizeFunctionPassManager(function_pass_manager_speed);
|
||||
|
||||
|
||||
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 = lb_create_startup_type_info(default_module);
|
||||
|
||||
TIME_SECTION("LLVM Runtime Startup Creation (Global Variables)");
|
||||
lbProcedure *startup_runtime = lb_create_startup_runtime(m, startup_type_info, global_variables);
|
||||
lbProcedure *startup_runtime = lb_create_startup_runtime(default_module, startup_type_info, global_variables);
|
||||
|
||||
|
||||
String filepath_ll = concatenate_strings(permanent_allocator(), gen->output_base, STR_LIT(".ll"));
|
||||
|
||||
TIME_SECTION("LLVM Procedure Generation");
|
||||
for_array(i, m->procedures_to_generate) {
|
||||
lbProcedure *p = m->procedures_to_generate[i];
|
||||
if (p->is_done) {
|
||||
continue;
|
||||
}
|
||||
if (p->body != nullptr) { // Build Procedure
|
||||
m->curr_procedure = p;
|
||||
lb_begin_procedure_body(p);
|
||||
lb_build_stmt(p, p->body);
|
||||
lb_end_procedure_body(p);
|
||||
p->is_done = true;
|
||||
m->curr_procedure = nullptr;
|
||||
}
|
||||
lb_end_procedure(p);
|
||||
|
||||
// Add Flags
|
||||
if (p->body != nullptr) {
|
||||
if (p->name == "memcpy" || p->name == "memmove" ||
|
||||
p->name == "runtime.mem_copy" || p->name == "mem_copy_non_overlapping" ||
|
||||
string_starts_with(p->name, str_lit("llvm.memcpy")) ||
|
||||
string_starts_with(p->name, str_lit("llvm.memmove"))) {
|
||||
p->flags |= lbProcedureFlag_WithoutMemcpyPass;
|
||||
for_array(j, gen->modules.entries) {
|
||||
lbModule *m = gen->modules.entries[j].value;
|
||||
for_array(i, m->procedures_to_generate) {
|
||||
lbProcedure *p = m->procedures_to_generate[i];
|
||||
if (p->is_done) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
||||
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(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||
if (p->body != nullptr) { // Build Procedure
|
||||
m->curr_procedure = p;
|
||||
lb_begin_procedure_body(p);
|
||||
lb_build_stmt(p, p->body);
|
||||
lb_end_procedure_body(p);
|
||||
p->is_done = true;
|
||||
m->curr_procedure = nullptr;
|
||||
}
|
||||
lb_end_procedure(p);
|
||||
|
||||
// Add Flags
|
||||
if (p->body != nullptr) {
|
||||
if (p->name == "memcpy" || p->name == "memmove" ||
|
||||
p->name == "runtime.mem_copy" || p->name == "mem_copy_non_overlapping" ||
|
||||
string_starts_with(p->name, str_lit("llvm.memcpy")) ||
|
||||
string_starts_with(p->name, str_lit("llvm.memmove"))) {
|
||||
p->flags |= lbProcedureFlag_WithoutMemcpyPass;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
||||
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
|
||||
LLVMDumpValue(p->value);
|
||||
gb_printf_err("\n\n\n\n");
|
||||
String filepath_ll = lb_filepath_ll_for_module(m);
|
||||
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);
|
||||
gb_exit(1);
|
||||
}
|
||||
LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
|
||||
gb_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!(build_context.build_mode == BuildMode_DynamicLibrary && !has_dll_main)) {
|
||||
TIME_SECTION("LLVM main");
|
||||
lb_create_main_procedure(m, startup_runtime);
|
||||
lb_create_main_procedure(default_module, startup_runtime);
|
||||
}
|
||||
|
||||
|
||||
if (m->debug_builder != nullptr) {
|
||||
TIME_SECTION("LLVM Debug Info Complete Types");
|
||||
lb_debug_complete_types(m);
|
||||
|
||||
|
||||
TIME_SECTION("LLVM Print Module to File");
|
||||
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;
|
||||
if (build_context.ODIN_DEBUG) {
|
||||
TIME_SECTION("LLVM Debug Info Complete Types and Finalize");
|
||||
for_array(j, gen->modules.entries) {
|
||||
lbModule *m = gen->modules.entries[j].value;
|
||||
if (m->debug_builder != nullptr) {
|
||||
lb_debug_complete_types(m);
|
||||
LLVMDIBuilderFinalize(m->debug_builder);
|
||||
}
|
||||
}
|
||||
TIME_SECTION("LLVM Debug Info Builder Finalize");
|
||||
LLVMDIBuilderFinalize(m->debug_builder);
|
||||
}
|
||||
|
||||
|
||||
@@ -14635,6 +14724,38 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
for_array(i, gen->modules.entries) {
|
||||
lbModule *m = gen->modules.entries[i].value;
|
||||
|
||||
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));
|
||||
defer (LLVMDisposePassManager(function_pass_manager_speed));
|
||||
|
||||
LLVMInitializeFunctionPassManager(default_function_pass_manager);
|
||||
LLVMInitializeFunctionPassManager(function_pass_manager_minimal);
|
||||
LLVMInitializeFunctionPassManager(function_pass_manager_size);
|
||||
LLVMInitializeFunctionPassManager(function_pass_manager_speed);
|
||||
|
||||
lb_populate_function_pass_manager(default_function_pass_manager, false, build_context.optimization_level);
|
||||
lb_populate_function_pass_manager_specific(function_pass_manager_minimal, 0);
|
||||
lb_populate_function_pass_manager_specific(function_pass_manager_size, 1);
|
||||
lb_populate_function_pass_manager_specific(function_pass_manager_speed, 2);
|
||||
|
||||
LLVMFinalizeFunctionPassManager(default_function_pass_manager);
|
||||
LLVMFinalizeFunctionPassManager(function_pass_manager_minimal);
|
||||
LLVMFinalizeFunctionPassManager(function_pass_manager_size);
|
||||
LLVMFinalizeFunctionPassManager(function_pass_manager_speed);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
for_array(i, m->procedures_to_generate) {
|
||||
lbProcedure *p = m->procedures_to_generate[i];
|
||||
if (p->body != nullptr) { // Build Procedure
|
||||
@@ -14688,49 +14809,41 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
llvm_error = nullptr;
|
||||
defer (LLVMDisposeMessage(llvm_error));
|
||||
|
||||
String filepath_obj = {};
|
||||
LLVMCodeGenFileType code_gen_file_type = LLVMObjectFile;
|
||||
|
||||
if (build_context.build_mode == BuildMode_Assembly) {
|
||||
filepath_obj = concatenate_strings(permanent_allocator(), gen->output_base, STR_LIT(".S"));
|
||||
code_gen_file_type = LLVMAssemblyFile;
|
||||
} else {
|
||||
switch (build_context.metrics.os) {
|
||||
case TargetOs_windows:
|
||||
filepath_obj = concatenate_strings(permanent_allocator(), gen->output_base, STR_LIT(".obj"));
|
||||
break;
|
||||
case TargetOs_darwin:
|
||||
case TargetOs_linux:
|
||||
case TargetOs_essence:
|
||||
filepath_obj = concatenate_strings(permanent_allocator(), gen->output_base, STR_LIT(".o"));
|
||||
break;
|
||||
case TargetOs_js:
|
||||
filepath_obj = concatenate_strings(permanent_allocator(), gen->output_base, STR_LIT(".wasm-obj"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||
gb_exit(1);
|
||||
return;
|
||||
for_array(j, gen->modules.entries) {
|
||||
lbModule *m = gen->modules.entries[j].value;
|
||||
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");
|
||||
String filepath_ll = lb_filepath_ll_for_module(m);
|
||||
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;
|
||||
}
|
||||
}
|
||||
gb_exit(1);
|
||||
return;
|
||||
}
|
||||
gb_exit(1);
|
||||
return;
|
||||
}
|
||||
llvm_error = nullptr;
|
||||
if (build_context.keep_temp_files ||
|
||||
build_context.build_mode == BuildMode_LLVM_IR) {
|
||||
TIME_SECTION("LLVM Print Module to File");
|
||||
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;
|
||||
|
||||
for_array(j, gen->modules.entries) {
|
||||
lbModule *m = gen->modules.entries[j].value;
|
||||
String filepath_ll = lb_filepath_ll_for_module(m);
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (build_context.build_mode == BuildMode_LLVM_IR) {
|
||||
gb_exit(0);
|
||||
@@ -14740,18 +14853,25 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
|
||||
TIME_SECTION("LLVM Object Generation");
|
||||
|
||||
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;
|
||||
for_array(j, gen->modules.entries) {
|
||||
lbModule *m = gen->modules.entries[j].value;
|
||||
String filepath_obj = lb_filepath_obj_for_module(m);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
array_add(&gen->output_object_paths, filepath_obj);
|
||||
for_array(i, m->info->required_foreign_imports_through_force) {
|
||||
Entity *e = m->info->required_foreign_imports_through_force[i];
|
||||
lb_add_foreign_library_path(m, e);
|
||||
}
|
||||
}
|
||||
|
||||
array_add(&gen->output_object_paths, filepath_obj);
|
||||
|
||||
for_array(i, m->info->required_foreign_imports_through_force) {
|
||||
Entity *e = m->info->required_foreign_imports_through_force[i];
|
||||
lb_add_foreign_library_path(m, e);
|
||||
}
|
||||
|
||||
|
||||
#undef TIME_SECTION
|
||||
}
|
||||
|
||||
@@ -85,6 +85,8 @@ struct lbModule {
|
||||
LLVMModuleRef mod;
|
||||
LLVMContextRef ctx;
|
||||
|
||||
struct lbGenerator *gen;
|
||||
|
||||
CheckerInfo *info;
|
||||
AstPackage *pkg; // associated
|
||||
|
||||
@@ -108,8 +110,6 @@ struct lbModule {
|
||||
Map<lbProcedure *> equal_procs; // Key: Type *
|
||||
Map<lbProcedure *> hasher_procs; // Key: Type *
|
||||
|
||||
u32 global_array_index;
|
||||
u32 global_generated_index;
|
||||
u32 nested_type_name_guid;
|
||||
|
||||
Array<lbProcedure *> procedures_to_generate;
|
||||
@@ -131,7 +131,11 @@ struct lbGenerator {
|
||||
String output_base;
|
||||
String output_name;
|
||||
Map<lbModule *> modules; // Key: AstPackage *
|
||||
Map<lbModule *> modules_through_ctx; // Key: LLVMContextRef *
|
||||
lbModule default_module;
|
||||
|
||||
gbAtomic32 global_array_index;
|
||||
gbAtomic32 global_generated_index;
|
||||
};
|
||||
|
||||
|
||||
@@ -271,7 +275,7 @@ String lb_get_entity_name(lbModule *m, Entity *e, String name = {});
|
||||
LLVMAttributeRef lb_create_enum_attribute(LLVMContextRef ctx, char const *name, u64 value=0);
|
||||
void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *name, u64 value);
|
||||
void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *name);
|
||||
lbProcedure *lb_create_procedure(lbModule *module, Entity *entity);
|
||||
lbProcedure *lb_create_procedure(lbModule *module, Entity *entity, bool ignore_body=false);
|
||||
void lb_end_procedure(lbProcedure *p);
|
||||
|
||||
|
||||
@@ -383,6 +387,7 @@ lbValue lb_gen_map_hash(lbProcedure *p, lbValue key, Type *key_type);
|
||||
void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbAddr addr, Type *map_type, lbValue map_key, lbValue map_value, Ast *node);
|
||||
|
||||
|
||||
|
||||
void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value);
|
||||
lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValue value);
|
||||
lbValue lb_emit_source_code_location(lbProcedure *p, String const &procedure, TokenPos const &pos);
|
||||
|
||||
11
src/main.cpp
11
src/main.cpp
@@ -1542,12 +1542,19 @@ void show_timings(Checker *c, Timings *t) {
|
||||
}
|
||||
}
|
||||
|
||||
void remove_temp_files(String output_base) {
|
||||
void remove_temp_files(lbGenerator *gen) {
|
||||
if (build_context.keep_temp_files) return;
|
||||
|
||||
String output_base = gen->output_base;
|
||||
|
||||
auto data = array_make<u8>(heap_allocator(), output_base.len + 30);
|
||||
defer (array_free(&data));
|
||||
|
||||
for_array(i, gen->output_object_paths) {
|
||||
String path = gen->output_object_paths[i];
|
||||
gb_file_remove(cast(char const *)path.text);
|
||||
}
|
||||
|
||||
isize n = output_base.len;
|
||||
gb_memmove(data.data, output_base.text, n);
|
||||
#define EXT_REMOVE(s) do { \
|
||||
@@ -2183,7 +2190,7 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
show_timings(&checker, timings);
|
||||
}
|
||||
|
||||
remove_temp_files(gen.output_base);
|
||||
remove_temp_files(&gen);
|
||||
|
||||
if (run_output) {
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
|
||||
Reference in New Issue
Block a user