mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 06:38:47 +00:00
Clean-up initialization code
This commit is contained in:
+1
-1
@@ -15,7 +15,7 @@ struct irModule {
|
|||||||
u64 state_flags;
|
u64 state_flags;
|
||||||
|
|
||||||
// String source_filename;
|
// String source_filename;
|
||||||
String layout;
|
// String layout;
|
||||||
// String triple;
|
// String triple;
|
||||||
|
|
||||||
PtrSet<Entity *> min_dep_set;
|
PtrSet<Entity *> min_dep_set;
|
||||||
|
|||||||
+619
-32
@@ -1,5 +1,7 @@
|
|||||||
#include "llvm_backend.hpp"
|
#include "llvm_backend.hpp"
|
||||||
|
|
||||||
|
gb_global lbValue lb_global_type_info_data = {};
|
||||||
|
|
||||||
struct lbLoopData {
|
struct lbLoopData {
|
||||||
lbAddr idx_addr;
|
lbAddr idx_addr;
|
||||||
lbValue idx;
|
lbValue idx;
|
||||||
@@ -1492,7 +1494,7 @@ void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) {
|
|||||||
String name = make_string(cast(u8 *)name_text, name_len-1);
|
String name = make_string(cast(u8 *)name_text, name_len-1);
|
||||||
e->TypeName.ir_mangled_name = name;
|
e->TypeName.ir_mangled_name = name;
|
||||||
|
|
||||||
// irValue *value = ir_value_type_name(name, e->type);
|
// lbValue value = ir_value_type_name(name, e->type);
|
||||||
// ir_add_entity_name(m, e, name);
|
// ir_add_entity_name(m, e, name);
|
||||||
// ir_gen_global_type_name(m, e, name);
|
// ir_gen_global_type_name(m, e, name);
|
||||||
} else if (e->kind == Entity_Procedure) {
|
} else if (e->kind == Entity_Procedure) {
|
||||||
@@ -3929,7 +3931,7 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
|
|||||||
result_type = alloc_type_pointer(t->Struct.fields[index]->type);
|
result_type = alloc_type_pointer(t->Struct.fields[index]->type);
|
||||||
} else if (is_type_union(t)) {
|
} else if (is_type_union(t)) {
|
||||||
GB_ASSERT(index == -1);
|
GB_ASSERT(index == -1);
|
||||||
// return ir_emit_union_tag_ptr(proc, s);
|
// return ir_emit_union_tag_ptr(p, s);
|
||||||
GB_PANIC("ir_emit_union_tag_ptr");
|
GB_PANIC("ir_emit_union_tag_ptr");
|
||||||
} else if (is_type_tuple(t)) {
|
} else if (is_type_tuple(t)) {
|
||||||
GB_ASSERT(t->Tuple.variables.count > 0);
|
GB_ASSERT(t->Tuple.variables.count > 0);
|
||||||
@@ -4050,7 +4052,7 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) {
|
|||||||
break;
|
break;
|
||||||
case Type_Union:
|
case Type_Union:
|
||||||
GB_ASSERT(index == -1);
|
GB_ASSERT(index == -1);
|
||||||
// return lb_emit_union_tag_value(proc, s);
|
// return lb_emit_union_tag_value(p, s);
|
||||||
GB_PANIC("lb_emit_union_tag_value");
|
GB_PANIC("lb_emit_union_tag_value");
|
||||||
|
|
||||||
case Type_Tuple:
|
case Type_Tuple:
|
||||||
@@ -6465,18 +6467,18 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
case_ast_node(ta, TypeAssertion, expr);
|
case_ast_node(ta, TypeAssertion, expr);
|
||||||
gbAllocator a = heap_allocator();
|
gbAllocator a = heap_allocator();
|
||||||
TokenPos pos = ast_token(expr).pos;
|
TokenPos pos = ast_token(expr).pos;
|
||||||
lbValue e = lb_build_expr(proc, ta->expr);
|
lbValue e = lb_build_expr(p, ta->expr);
|
||||||
Type *t = type_deref(ir_type(e));
|
Type *t = type_deref(ir_type(e));
|
||||||
if (is_type_union(t)) {
|
if (is_type_union(t)) {
|
||||||
Type *type = type_of_expr(expr);
|
Type *type = type_of_expr(expr);
|
||||||
lbValue v = lb_add_local_generated(proc, type, false);
|
lbValue v = lb_add_local_generated(p, type, false);
|
||||||
ir_emit_comment(proc, str_lit("cast - union_cast"));
|
ir_emit_comment(p, str_lit("cast - union_cast"));
|
||||||
lb_emit_store(proc, v, ir_emit_union_cast(proc, lb_build_expr(proc, ta->expr), type, pos));
|
lb_emit_store(p, v, ir_emit_union_cast(p, lb_build_expr(p, ta->expr), type, pos));
|
||||||
return ir_addr(v);
|
return ir_addr(v);
|
||||||
} else if (is_type_any(t)) {
|
} else if (is_type_any(t)) {
|
||||||
ir_emit_comment(proc, str_lit("cast - any_cast"));
|
ir_emit_comment(p, str_lit("cast - any_cast"));
|
||||||
Type *type = type_of_expr(expr);
|
Type *type = type_of_expr(expr);
|
||||||
return ir_emit_any_cast_addr(proc, lb_build_expr(proc, ta->expr), type, pos);
|
return ir_emit_any_cast_addr(p, lb_build_expr(p, ta->expr), type, pos);
|
||||||
} else {
|
} else {
|
||||||
GB_PANIC("TODO(bill): type assertion %s", type_to_string(ir_type(e)));
|
GB_PANIC("TODO(bill): type assertion %s", type_to_string(ir_type(e)));
|
||||||
}
|
}
|
||||||
@@ -6958,18 +6960,18 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
// gbAllocator a = heap_allocator();
|
// gbAllocator a = heap_allocator();
|
||||||
// {
|
// {
|
||||||
// auto args = array_make<lbValue>(a, 3);
|
// auto args = array_make<lbValue>(a, 3);
|
||||||
// args[0] = ir_gen_map_header(proc, v, type);
|
// args[0] = ir_gen_map_header(p, v, type);
|
||||||
// args[1] = ir_const_int(2*cl->elems.count);
|
// args[1] = ir_const_int(2*cl->elems.count);
|
||||||
// args[2] = ir_emit_source_code_location(proc, proc_name, pos);
|
// args[2] = ir_emit_source_code_location(p, proc_name, pos);
|
||||||
// lb_emit_runtime_call(proc, "__dynamic_map_reserve", args);
|
// lb_emit_runtime_call(p, "__dynamic_map_reserve", args);
|
||||||
// }
|
// }
|
||||||
// for_array(field_index, cl->elems) {
|
// for_array(field_index, cl->elems) {
|
||||||
// Ast *elem = cl->elems[field_index];
|
// Ast *elem = cl->elems[field_index];
|
||||||
// ast_node(fv, FieldValue, elem);
|
// ast_node(fv, FieldValue, elem);
|
||||||
|
|
||||||
// lbValue key = lb_build_expr(proc, fv->field);
|
// lbValue key = lb_build_expr(p, fv->field);
|
||||||
// lbValue value = lb_build_expr(proc, fv->value);
|
// lbValue value = lb_build_expr(p, fv->value);
|
||||||
// ir_insert_dynamic_map_key_and_value(proc, v, type, key, value);
|
// ir_insert_dynamic_map_key_and_value(p, v, type, key, value);
|
||||||
// }
|
// }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -7334,13 +7336,13 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
auto args = array_make<lbValue>(a, 6);
|
auto args = array_make<lbValue>(a, 6);
|
||||||
args[0] = lb_emit_conv(proc, v, t_rawptr);
|
args[0] = lb_emit_conv(p, v, t_rawptr);
|
||||||
args[1] = size;
|
args[1] = size;
|
||||||
args[2] = align;
|
args[2] = align;
|
||||||
args[3] = lb_emit_conv(proc, items, t_rawptr);
|
args[3] = lb_emit_conv(p, items, t_rawptr);
|
||||||
args[4] = ir_const_int(item_count);
|
args[4] = ir_const_int(item_count);
|
||||||
args[5] = ir_emit_source_code_location(proc, proc_name, pos);
|
args[5] = ir_emit_source_code_location(p, proc_name, pos);
|
||||||
lb_emit_runtime_call(proc, "__dynamic_array_append", args);
|
lb_emit_runtime_call(p, "__dynamic_array_append", args);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -7551,6 +7553,563 @@ lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value) {
|
|||||||
return lb_addr(g);
|
return lb_addr(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lbValue lb_find_global_variable(lbModule *m, String const &name) {
|
||||||
|
lbValue *found = map_get(&m->values, hash_string(name));
|
||||||
|
GB_ASSERT_MSG(found != nullptr, "Unable to find global variable '%.*s'", LIT(name));
|
||||||
|
lbValue value = *found;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info data
|
||||||
|
lbModule *m = p->module;
|
||||||
|
gbAllocator a = heap_allocator();
|
||||||
|
CheckerInfo *info = m->info;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (true) {
|
||||||
|
lbValue global_type_table = lb_find_global_variable(m, str_lit("runtime.type_table"));
|
||||||
|
Type *type = base_type(type_deref(lb_global_type_info_data.type));
|
||||||
|
GB_ASSERT(is_type_array(type));
|
||||||
|
lbValue len = ir_const_int(type->Array.count);
|
||||||
|
ir_fill_slice(p, global_type_table,
|
||||||
|
ir_emit_array_epi(p, lb_global_type_info_data, 0),
|
||||||
|
len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Useful types
|
||||||
|
Type *t_i64_slice_ptr = alloc_type_pointer(alloc_type_slice(t_i64));
|
||||||
|
Type *t_string_slice_ptr = alloc_type_pointer(alloc_type_slice(t_string));
|
||||||
|
|
||||||
|
i32 type_info_member_types_index = 0;
|
||||||
|
i32 type_info_member_names_index = 0;
|
||||||
|
i32 type_info_member_offsets_index = 0;
|
||||||
|
|
||||||
|
for_array(type_info_type_index, info->type_info_types) {
|
||||||
|
Type *t = info->type_info_types[type_info_type_index];
|
||||||
|
t = default_type(t);
|
||||||
|
if (t == t_invalid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
isize entry_index = ir_type_info_index(info, t, false);
|
||||||
|
if (entry_index <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbValue tag = nullptr;
|
||||||
|
lbValue ti_ptr = ir_emit_array_epi(p, lb_global_type_info_data, cast(i32)entry_index);
|
||||||
|
lbValue variant_ptr = ir_emit_struct_ep(p, ti_ptr, 3);
|
||||||
|
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, ti_ptr, 0), ir_const_int(type_size_of(t)));
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, ti_ptr, 1), ir_const_int(type_align_of(t)));
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, ti_ptr, 2), ir_typeid(proc->module, t));
|
||||||
|
|
||||||
|
|
||||||
|
switch (t->kind) {
|
||||||
|
case Type_Named: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Named"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_named_ptr);
|
||||||
|
|
||||||
|
// TODO(bill): Which is better? The mangled name or actual name?
|
||||||
|
lbValue name = ir_const_string(proc->module, t->Named.type_name->token.string);
|
||||||
|
lbValue gtip = ir_get_type_info_ptr(p, t->Named.base);
|
||||||
|
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), name);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 1), gtip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type_Basic:
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Basic"));
|
||||||
|
switch (t->Basic.kind) {
|
||||||
|
case Basic_bool:
|
||||||
|
case Basic_b8:
|
||||||
|
case Basic_b16:
|
||||||
|
case Basic_b32:
|
||||||
|
case Basic_b64:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_boolean_ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Basic_i8:
|
||||||
|
case Basic_u8:
|
||||||
|
case Basic_i16:
|
||||||
|
case Basic_u16:
|
||||||
|
case Basic_i32:
|
||||||
|
case Basic_u32:
|
||||||
|
case Basic_i64:
|
||||||
|
case Basic_u64:
|
||||||
|
case Basic_i128:
|
||||||
|
case Basic_u128:
|
||||||
|
|
||||||
|
case Basic_i16le:
|
||||||
|
case Basic_u16le:
|
||||||
|
case Basic_i32le:
|
||||||
|
case Basic_u32le:
|
||||||
|
case Basic_i64le:
|
||||||
|
case Basic_u64le:
|
||||||
|
case Basic_i128le:
|
||||||
|
case Basic_u128le:
|
||||||
|
case Basic_i16be:
|
||||||
|
case Basic_u16be:
|
||||||
|
case Basic_i32be:
|
||||||
|
case Basic_u32be:
|
||||||
|
case Basic_i64be:
|
||||||
|
case Basic_u64be:
|
||||||
|
case Basic_i128be:
|
||||||
|
case Basic_u128be:
|
||||||
|
|
||||||
|
case Basic_int:
|
||||||
|
case Basic_uint:
|
||||||
|
case Basic_uintptr: {
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_integer_ptr);
|
||||||
|
lbValue is_signed = ir_const_bool((t->Basic.flags & BasicFlag_Unsigned) == 0);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), is_signed);
|
||||||
|
// NOTE(bill): This is matches the runtime layout
|
||||||
|
u8 endianness_value = 0;
|
||||||
|
if (t->Basic.flags & BasicFlag_EndianLittle) {
|
||||||
|
endianness_value = 1;
|
||||||
|
} else if (t->Basic.flags & BasicFlag_EndianBig) {
|
||||||
|
endianness_value = 2;
|
||||||
|
}
|
||||||
|
lbValue endianness = ir_const_u8(endianness_value);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 1), endianness);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Basic_rune:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_rune_ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// case Basic_f16:
|
||||||
|
case Basic_f32:
|
||||||
|
case Basic_f64:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_float_ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// case Basic_complex32:
|
||||||
|
case Basic_complex64:
|
||||||
|
case Basic_complex128:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_complex_ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Basic_quaternion128:
|
||||||
|
case Basic_quaternion256:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_quaternion_ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Basic_rawptr:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_pointer_ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Basic_string:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_string_ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Basic_cstring:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_string_ptr);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), v_true); // is_cstring
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Basic_any:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_any_ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Basic_typeid:
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_typeid_ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type_Pointer: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Pointer"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_pointer_ptr);
|
||||||
|
lbValue gep = ir_get_type_info_ptr(p, t->Pointer.elem);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), gep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_Array: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Array"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_array_ptr);
|
||||||
|
lbValue gep = ir_get_type_info_ptr(p, t->Array.elem);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), gep);
|
||||||
|
|
||||||
|
i64 ez = type_size_of(t->Array.elem);
|
||||||
|
lbValue elem_size = ir_emit_struct_ep(p, tag, 1);
|
||||||
|
ir_emit_store(p, elem_size, ir_const_int(ez));
|
||||||
|
|
||||||
|
lbValue count = ir_emit_struct_ep(p, tag, 2);
|
||||||
|
ir_emit_store(p, count, ir_const_int(t->Array.count));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_EnumeratedArray: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Enumerated_Array"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_enumerated_array_ptr);
|
||||||
|
lbValue elem = ir_get_type_info_ptr(p, t->EnumeratedArray.elem);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), elem);
|
||||||
|
|
||||||
|
lbValue index = ir_get_type_info_ptr(p, t->EnumeratedArray.index);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 1), index);
|
||||||
|
|
||||||
|
i64 ez = type_size_of(t->EnumeratedArray.elem);
|
||||||
|
lbValue elem_size = ir_emit_struct_ep(p, tag, 2);
|
||||||
|
ir_emit_store(p, elem_size, ir_const_int(ez));
|
||||||
|
|
||||||
|
lbValue count = ir_emit_struct_ep(p, tag, 3);
|
||||||
|
ir_emit_store(p, count, ir_const_int(t->EnumeratedArray.count));
|
||||||
|
|
||||||
|
lbValue min_value = ir_emit_struct_ep(p, tag, 4);
|
||||||
|
lbValue max_value = ir_emit_struct_ep(p, tag, 5);
|
||||||
|
|
||||||
|
lbValue min_v = ir_value_constant(core_type(t->EnumeratedArray.index), t->EnumeratedArray.min_value);
|
||||||
|
lbValue max_v = ir_value_constant(core_type(t->EnumeratedArray.index), t->EnumeratedArray.max_value);
|
||||||
|
|
||||||
|
ir_emit_store_union_variant(p, min_value, min_v, ir_type(min_v));
|
||||||
|
ir_emit_store_union_variant(p, max_value, max_v, ir_type(max_v));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_DynamicArray: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Dynamic_Array"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_dynamic_array_ptr);
|
||||||
|
lbValue gep = ir_get_type_info_ptr(p, t->DynamicArray.elem);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), gep);
|
||||||
|
|
||||||
|
i64 ez = type_size_of(t->DynamicArray.elem);
|
||||||
|
lbValue elem_size = ir_emit_struct_ep(p, tag, 1);
|
||||||
|
ir_emit_store(p, elem_size, ir_const_int(ez));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_Slice: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Slice"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_slice_ptr);
|
||||||
|
lbValue gep = ir_get_type_info_ptr(p, t->Slice.elem);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), gep);
|
||||||
|
|
||||||
|
i64 ez = type_size_of(t->Slice.elem);
|
||||||
|
lbValue elem_size = ir_emit_struct_ep(p, tag, 1);
|
||||||
|
ir_emit_store(p, elem_size, ir_const_int(ez));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_Proc: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Proc"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_procedure_ptr);
|
||||||
|
|
||||||
|
lbValue params = ir_emit_struct_ep(p, tag, 0);
|
||||||
|
lbValue results = ir_emit_struct_ep(p, tag, 1);
|
||||||
|
lbValue variadic = ir_emit_struct_ep(p, tag, 2);
|
||||||
|
lbValue convention = ir_emit_struct_ep(p, tag, 3);
|
||||||
|
|
||||||
|
if (t->Proc.params != nullptr) {
|
||||||
|
ir_emit_store(p, params, ir_get_type_info_ptr(p, t->Proc.params));
|
||||||
|
}
|
||||||
|
if (t->Proc.results != nullptr) {
|
||||||
|
ir_emit_store(p, results, ir_get_type_info_ptr(p, t->Proc.results));
|
||||||
|
}
|
||||||
|
ir_emit_store(p, variadic, ir_const_bool(t->Proc.variadic));
|
||||||
|
ir_emit_store(p, convention, ir_const_int(t->Proc.calling_convention));
|
||||||
|
|
||||||
|
// TODO(bill): TypeInfo for procedures
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_Tuple: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Tuple"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_tuple_ptr);
|
||||||
|
|
||||||
|
lbValue memory_types = ir_type_info_member_types_offset(p, t->Tuple.variables.count);
|
||||||
|
lbValue memory_names = ir_type_info_member_names_offset(p, t->Tuple.variables.count);
|
||||||
|
|
||||||
|
for_array(i, t->Tuple.variables) {
|
||||||
|
// NOTE(bill): offset is not used for tuples
|
||||||
|
Entity *f = t->Tuple.variables[i];
|
||||||
|
|
||||||
|
lbValue index = ir_const_int(i);
|
||||||
|
lbValue type_info = ir_emit_ptr_offset(p, memory_types, index);
|
||||||
|
|
||||||
|
ir_emit_store(p, type_info, ir_type_info(p, f->type));
|
||||||
|
if (f->token.string.len > 0) {
|
||||||
|
lbValue name = ir_emit_ptr_offset(p, memory_names, index);
|
||||||
|
ir_emit_store(p, name, ir_const_string(proc->module, f->token.string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lbValue count = ir_const_int(t->Tuple.variables.count);
|
||||||
|
ir_fill_slice(p, ir_emit_struct_ep(p, tag, 0), memory_types, count);
|
||||||
|
ir_fill_slice(p, ir_emit_struct_ep(p, tag, 1), memory_names, count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_Enum:
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Enum"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_enum_ptr);
|
||||||
|
{
|
||||||
|
GB_ASSERT(t->Enum.base_type != nullptr);
|
||||||
|
lbValue base = ir_type_info(p, t->Enum.base_type);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), base);
|
||||||
|
|
||||||
|
if (t->Enum.fields.count > 0) {
|
||||||
|
auto fields = t->Enum.fields;
|
||||||
|
lbValue name_array = ir_generate_array(m, t_string, fields.count,
|
||||||
|
str_lit("$enum_names"), cast(i64)entry_index);
|
||||||
|
lbValue value_array = ir_generate_array(m, t_type_info_enum_value, fields.count,
|
||||||
|
str_lit("$enum_values"), cast(i64)entry_index);
|
||||||
|
|
||||||
|
GB_ASSERT(is_type_integer(t->Enum.base_type));
|
||||||
|
|
||||||
|
for_array(i, fields) {
|
||||||
|
lbValue name_ep = ir_emit_array_epi(p, name_array, cast(i32)i);
|
||||||
|
lbValue value_ep = ir_emit_array_epi(p, value_array, cast(i32)i);
|
||||||
|
|
||||||
|
ExactValue value = fields[i]->Constant.value;
|
||||||
|
lbValue v = ir_value_constant(t->Enum.base_type, value);
|
||||||
|
|
||||||
|
ir_emit_store_union_variant(p, value_ep, v, ir_type(v));
|
||||||
|
ir_emit_store(p, name_ep, ir_const_string(proc->module, fields[i]->token.string));
|
||||||
|
}
|
||||||
|
|
||||||
|
lbValue v_count = ir_const_int(fields.count);
|
||||||
|
|
||||||
|
lbValue names = ir_emit_struct_ep(p, tag, 1);
|
||||||
|
lbValue name_array_elem = ir_array_elem(p, name_array);
|
||||||
|
ir_fill_slice(p, names, name_array_elem, v_count);
|
||||||
|
|
||||||
|
lbValue values = ir_emit_struct_ep(p, tag, 2);
|
||||||
|
lbValue value_array_elem = ir_array_elem(p, value_array);
|
||||||
|
ir_fill_slice(p, values, value_array_elem, v_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type_Union: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Union"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_union_ptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
lbValue variant_types = ir_emit_struct_ep(p, tag, 0);
|
||||||
|
lbValue tag_offset_ptr = ir_emit_struct_ep(p, tag, 1);
|
||||||
|
lbValue tag_type_ptr = ir_emit_struct_ep(p, tag, 2);
|
||||||
|
lbValue custom_align_ptr = ir_emit_struct_ep(p, tag, 3);
|
||||||
|
lbValue no_nil_ptr = ir_emit_struct_ep(p, tag, 4);
|
||||||
|
lbValue maybe_ptr = ir_emit_struct_ep(p, tag, 5);
|
||||||
|
|
||||||
|
isize variant_count = gb_max(0, t->Union.variants.count);
|
||||||
|
lbValue memory_types = ir_type_info_member_types_offset(p, variant_count);
|
||||||
|
|
||||||
|
// NOTE(bill): Zeroth is nil so ignore it
|
||||||
|
for (isize variant_index = 0; variant_index < variant_count; variant_index++) {
|
||||||
|
Type *vt = t->Union.variants[variant_index];
|
||||||
|
lbValue tip = ir_get_type_info_ptr(p, vt);
|
||||||
|
|
||||||
|
lbValue index = ir_const_int(variant_index);
|
||||||
|
lbValue type_info = ir_emit_ptr_offset(p, memory_types, index);
|
||||||
|
ir_emit_store(p, type_info, ir_type_info(p, vt));
|
||||||
|
}
|
||||||
|
|
||||||
|
lbValue count = ir_const_int(variant_count);
|
||||||
|
ir_fill_slice(p, variant_types, memory_types, count);
|
||||||
|
|
||||||
|
i64 tag_size = union_tag_size(t);
|
||||||
|
i64 tag_offset = align_formula(t->Union.variant_block_size, tag_size);
|
||||||
|
|
||||||
|
if (tag_size > 0) {
|
||||||
|
ir_emit_store(p, tag_offset_ptr, ir_const_uintptr(tag_offset));
|
||||||
|
ir_emit_store(p, tag_type_ptr, ir_type_info(p, union_tag_type(t)));
|
||||||
|
}
|
||||||
|
|
||||||
|
lbValue is_custom_align = ir_const_bool(t->Union.custom_align != 0);
|
||||||
|
ir_emit_store(p, custom_align_ptr, is_custom_align);
|
||||||
|
|
||||||
|
ir_emit_store(p, no_nil_ptr, ir_const_bool(t->Union.no_nil));
|
||||||
|
ir_emit_store(p, maybe_ptr, ir_const_bool(t->Union.maybe));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type_Struct: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Struct"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_struct_ptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
lbValue is_packed = ir_const_bool(t->Struct.is_packed);
|
||||||
|
lbValue is_raw_union = ir_const_bool(t->Struct.is_raw_union);
|
||||||
|
lbValue is_custom_align = ir_const_bool(t->Struct.custom_align != 0);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 5), is_packed);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 6), is_raw_union);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 7), is_custom_align);
|
||||||
|
|
||||||
|
if (t->Struct.soa_kind != StructSoa_None) {
|
||||||
|
lbValue kind = ir_emit_struct_ep(p, tag, 8);
|
||||||
|
Type *kind_type = type_deref(ir_type(kind));
|
||||||
|
|
||||||
|
lbValue soa_kind = ir_value_constant(kind_type, exact_value_i64(t->Struct.soa_kind));
|
||||||
|
lbValue soa_type = ir_type_info(p, t->Struct.soa_elem);
|
||||||
|
lbValue soa_len = ir_const_int(t->Struct.soa_count);
|
||||||
|
|
||||||
|
|
||||||
|
ir_emit_store(p, kind, soa_kind);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 9), soa_type);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 10), soa_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isize count = t->Struct.fields.count;
|
||||||
|
if (count > 0) {
|
||||||
|
lbValue memory_types = ir_type_info_member_types_offset (p, count);
|
||||||
|
lbValue memory_names = ir_type_info_member_names_offset (p, count);
|
||||||
|
lbValue memory_offsets = ir_type_info_member_offsets_offset(p, count);
|
||||||
|
lbValue memory_usings = ir_type_info_member_usings_offset (p, count);
|
||||||
|
lbValue memory_tags = ir_type_info_member_tags_offset (p, count);
|
||||||
|
|
||||||
|
type_set_offsets(t); // NOTE(bill): Just incase the offsets have not been set yet
|
||||||
|
for (isize source_index = 0; source_index < count; source_index++) {
|
||||||
|
// TODO(bill): Order fields in source order not layout order
|
||||||
|
Entity *f = t->Struct.fields[source_index];
|
||||||
|
lbValue tip = ir_get_type_info_ptr(p, f->type);
|
||||||
|
i64 foffset = 0;
|
||||||
|
if (!t->Struct.is_raw_union) {
|
||||||
|
foffset = t->Struct.offsets[f->Variable.field_index];
|
||||||
|
}
|
||||||
|
GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
|
||||||
|
|
||||||
|
lbValue index = ir_const_int(source_index);
|
||||||
|
lbValue type_info = ir_emit_ptr_offset(p, memory_types, index);
|
||||||
|
lbValue offset = ir_emit_ptr_offset(p, memory_offsets, index);
|
||||||
|
lbValue is_using = ir_emit_ptr_offset(p, memory_usings, index);
|
||||||
|
|
||||||
|
ir_emit_store(p, type_info, ir_type_info(p, f->type));
|
||||||
|
if (f->token.string.len > 0) {
|
||||||
|
lbValue name = ir_emit_ptr_offset(p, memory_names, index);
|
||||||
|
ir_emit_store(p, name, ir_const_string(proc->module, f->token.string));
|
||||||
|
}
|
||||||
|
ir_emit_store(p, offset, ir_const_uintptr(foffset));
|
||||||
|
ir_emit_store(p, is_using, ir_const_bool((f->flags&EntityFlag_Using) != 0));
|
||||||
|
|
||||||
|
if (t->Struct.tags.count > 0) {
|
||||||
|
String tag_string = t->Struct.tags[source_index];
|
||||||
|
if (tag_string.len > 0) {
|
||||||
|
lbValue tag_ptr = ir_emit_ptr_offset(p, memory_tags, index);
|
||||||
|
ir_emit_store(p, tag_ptr, ir_const_string(proc->module, tag_string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
lbValue cv = ir_const_int(count);
|
||||||
|
ir_fill_slice(p, ir_emit_struct_ep(p, tag, 0), memory_types, cv);
|
||||||
|
ir_fill_slice(p, ir_emit_struct_ep(p, tag, 1), memory_names, cv);
|
||||||
|
ir_fill_slice(p, ir_emit_struct_ep(p, tag, 2), memory_offsets, cv);
|
||||||
|
ir_fill_slice(p, ir_emit_struct_ep(p, tag, 3), memory_usings, cv);
|
||||||
|
ir_fill_slice(p, ir_emit_struct_ep(p, tag, 4), memory_tags, cv);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_Map: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Map"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_map_ptr);
|
||||||
|
init_map_internal_types(t);
|
||||||
|
|
||||||
|
lbValue key = ir_emit_struct_ep(p, tag, 0);
|
||||||
|
lbValue value = ir_emit_struct_ep(p, tag, 1);
|
||||||
|
lbValue generated_struct = ir_emit_struct_ep(p, tag, 2);
|
||||||
|
|
||||||
|
ir_emit_store(p, key, ir_get_type_info_ptr(p, t->Map.key));
|
||||||
|
ir_emit_store(p, value, ir_get_type_info_ptr(p, t->Map.value));
|
||||||
|
ir_emit_store(p, generated_struct, ir_get_type_info_ptr(p, t->Map.generated_struct_type));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type_BitField: {
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Bit_Field"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_bit_field_ptr);
|
||||||
|
// names: []string;
|
||||||
|
// bits: []u32;
|
||||||
|
// offsets: []u32;
|
||||||
|
isize count = t->BitField.fields.count;
|
||||||
|
if (count > 0) {
|
||||||
|
auto fields = t->BitField.fields;
|
||||||
|
lbValue name_array = ir_generate_array(m, t_string, count, str_lit("$bit_field_names"), cast(i64)entry_index);
|
||||||
|
lbValue bit_array = ir_generate_array(m, t_i32, count, str_lit("$bit_field_bits"), cast(i64)entry_index);
|
||||||
|
lbValue offset_array = ir_generate_array(m, t_i32, count, str_lit("$bit_field_offsets"), cast(i64)entry_index);
|
||||||
|
|
||||||
|
for (isize i = 0; i < count; i++) {
|
||||||
|
Entity *f = fields[i];
|
||||||
|
GB_ASSERT(f->type != nullptr);
|
||||||
|
GB_ASSERT(f->type->kind == Type_BitFieldValue);
|
||||||
|
lbValue name_ep = ir_emit_array_epi(p, name_array, cast(i32)i);
|
||||||
|
lbValue bit_ep = ir_emit_array_epi(p, bit_array, cast(i32)i);
|
||||||
|
lbValue offset_ep = ir_emit_array_epi(p, offset_array, cast(i32)i);
|
||||||
|
|
||||||
|
ir_emit_store(p, name_ep, ir_const_string(proc->module, f->token.string));
|
||||||
|
ir_emit_store(p, bit_ep, ir_const_i32(f->type->BitFieldValue.bits));
|
||||||
|
ir_emit_store(p, offset_ep, ir_const_i32(t->BitField.offsets[i]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
lbValue v_count = ir_const_int(count);
|
||||||
|
|
||||||
|
lbValue names = ir_emit_struct_ep(p, tag, 0);
|
||||||
|
lbValue name_array_elem = ir_array_elem(p, name_array);
|
||||||
|
ir_fill_slice(p, names, name_array_elem, v_count);
|
||||||
|
|
||||||
|
lbValue bits = ir_emit_struct_ep(p, tag, 1);
|
||||||
|
lbValue bit_array_elem = ir_array_elem(p, bit_array);
|
||||||
|
ir_fill_slice(p, bits, bit_array_elem, v_count);
|
||||||
|
|
||||||
|
lbValue offsets = ir_emit_struct_ep(p, tag, 2);
|
||||||
|
lbValue offset_array_elem = ir_array_elem(p, offset_array);
|
||||||
|
ir_fill_slice(p, offsets, offset_array_elem, v_count);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type_BitSet:
|
||||||
|
ir_emit_comment(p, str_lit("Type_Info_Bit_Set"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_bit_set_ptr);
|
||||||
|
|
||||||
|
GB_ASSERT(is_type_typed(t->BitSet.elem));
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), ir_get_type_info_ptr(p, t->BitSet.elem));
|
||||||
|
if (t->BitSet.underlying != nullptr) {
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 1), ir_get_type_info_ptr(p, t->BitSet.underlying));
|
||||||
|
}
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 2), ir_const_i64(t->BitSet.lower));
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 3), ir_const_i64(t->BitSet.upper));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type_Opaque:
|
||||||
|
ir_emit_comment(p, str_lit("Type_Opaque"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_opaque_ptr);
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), ir_get_type_info_ptr(p, t->Opaque.elem));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type_SimdVector:
|
||||||
|
ir_emit_comment(p, str_lit("Type_SimdVector"));
|
||||||
|
tag = ir_emit_conv(p, variant_ptr, t_type_info_simd_vector_ptr);
|
||||||
|
if (t->SimdVector.is_x86_mmx) {
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 3), v_true);
|
||||||
|
} else {
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 0), ir_get_type_info_ptr(p, t->SimdVector.elem));
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 1), ir_const_int(type_size_of(t->SimdVector.elem)));
|
||||||
|
ir_emit_store(p, ir_emit_struct_ep(p, tag, 2), ir_const_int(t->SimdVector.count));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (tag != nullptr) {
|
||||||
|
Type *tag_type = type_deref(ir_type(tag));
|
||||||
|
GB_ASSERT(is_type_named(tag_type));
|
||||||
|
ir_emit_store_union_variant(p, variant_ptr, ir_emit_load(p, tag), tag_type);
|
||||||
|
} else {
|
||||||
|
if (t != t_llvm_bool) {
|
||||||
|
GB_PANIC("Unhandled Type_Info variant: %s", type_to_string(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void lb_generate_code(lbGenerator *gen) {
|
void lb_generate_code(lbGenerator *gen) {
|
||||||
lbModule *m = &gen->module;
|
lbModule *m = &gen->module;
|
||||||
@@ -7818,24 +8377,22 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
LLVMRunPassManager(module_pass_manager, mod);
|
LLVMRunPassManager(module_pass_manager, mod);
|
||||||
|
|
||||||
|
|
||||||
if (!(build_context.is_dll && !has_dll_main)) {
|
lbProcedure *startup_runtime = nullptr;
|
||||||
LLVMContextRef ctx = LLVMGetModuleContext(mod);
|
{ // Startup Runtime
|
||||||
|
|
||||||
Type *params = alloc_type_tuple();
|
Type *params = alloc_type_tuple();
|
||||||
Type *results = alloc_type_tuple();
|
Type *results = alloc_type_tuple();
|
||||||
|
|
||||||
array_init(¶ms->Tuple.variables, heap_allocator(), 2);
|
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl);
|
||||||
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"), alloc_type_pointer(t_cstring), false, true);
|
|
||||||
|
|
||||||
array_init(&results->Tuple.variables, heap_allocator(), 1);
|
lbProcedure *p = lb_create_dummy_procedure(m, str_lit("__$startup_runtime"), proc_type);
|
||||||
results->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("_"), t_i32, false, true);
|
startup_runtime = p;
|
||||||
|
|
||||||
Type *proc_type = alloc_type_proc(nullptr, params, 2, results, 1, false, ProcCC_CDecl);
|
|
||||||
|
|
||||||
lbProcedure *p = lb_create_dummy_procedure(m, str_lit("main"), proc_type);
|
|
||||||
|
|
||||||
lb_begin_procedure_body(p);
|
lb_begin_procedure_body(p);
|
||||||
|
|
||||||
|
lb_emit_init_context(p);
|
||||||
|
|
||||||
|
lb_setup_type_info_data(p);
|
||||||
|
|
||||||
for_array(i, global_variables) {
|
for_array(i, global_variables) {
|
||||||
auto *var = &global_variables[i];
|
auto *var = &global_variables[i];
|
||||||
if (var->decl->init_expr != nullptr) {
|
if (var->decl->init_expr != nullptr) {
|
||||||
@@ -7874,13 +8431,42 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lb_end_procedure_body(p);
|
||||||
|
|
||||||
|
if (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(function_pass_manager, p->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(build_context.is_dll && !has_dll_main)) {
|
||||||
|
Type *params = alloc_type_tuple();
|
||||||
|
Type *results = alloc_type_tuple();
|
||||||
|
|
||||||
|
array_init(¶ms->Tuple.variables, heap_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"), alloc_type_pointer(t_cstring), false, true);
|
||||||
|
|
||||||
|
array_init(&results->Tuple.variables, heap_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, 2, results, 1, false, ProcCC_CDecl);
|
||||||
|
|
||||||
|
lbProcedure *p = lb_create_dummy_procedure(m, str_lit("main"), proc_type);
|
||||||
|
|
||||||
|
lb_begin_procedure_body(p);
|
||||||
|
|
||||||
lbValue *found = map_get(&m->values, hash_entity(entry_point));
|
lbValue *found = map_get(&m->values, hash_entity(entry_point));
|
||||||
GB_ASSERT(found != nullptr);
|
GB_ASSERT(found != nullptr);
|
||||||
|
|
||||||
|
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, startup_runtime->type)), startup_runtime->value, nullptr, 0, "");
|
||||||
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, found->type)), found->value, nullptr, 0, "");
|
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, found->type)), found->value, nullptr, 0, "");
|
||||||
LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false));
|
LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false));
|
||||||
|
|
||||||
|
|
||||||
lb_end_procedure_body(p);
|
lb_end_procedure_body(p);
|
||||||
|
|
||||||
if (LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
if (LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
|
||||||
@@ -7930,6 +8516,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
LLVMBool ok = LLVMTargetMachineEmitToFile(target_machine, mod, cast(char *)filepath_obj.text, LLVMObjectFile, &llvm_error);
|
LLVMBool ok = LLVMTargetMachineEmitToFile(target_machine, mod, cast(char *)filepath_obj.text, LLVMObjectFile, &llvm_error);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||||
|
gb_exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user