diff options
| author | gingerBill <bill@gingerbill.org> | 2020-02-26 22:05:52 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-02-26 22:05:52 +0000 |
| commit | 470508adbc9fb8b0e79d8ef1c7ca6a92d4babfcd (patch) | |
| tree | 0f1d455569fa7a0214c19b4d13503c992b391cc2 /src/llvm_backend.cpp | |
| parent | b13423d7f7b8ef07cfb7e5e03b6520a63f0861e3 (diff) | |
Clean-up initialization code
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 649 |
1 files changed, 618 insertions, 31 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index d676e2148..547d3b8f3 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1,5 +1,7 @@ #include "llvm_backend.hpp" +gb_global lbValue lb_global_type_info_data = {}; + struct lbLoopData { lbAddr idx_addr; 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); 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_gen_global_type_name(m, e, name); } 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); } else if (is_type_union(t)) { 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"); } else if (is_type_tuple(t)) { GB_ASSERT(t->Tuple.variables.count > 0); @@ -4050,7 +4052,7 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { break; case Type_Union: 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"); case Type_Tuple: @@ -6465,18 +6467,18 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { case_ast_node(ta, TypeAssertion, expr); gbAllocator a = heap_allocator(); 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)); if (is_type_union(t)) { Type *type = type_of_expr(expr); - lbValue v = lb_add_local_generated(proc, type, false); - ir_emit_comment(proc, str_lit("cast - union_cast")); - lb_emit_store(proc, v, ir_emit_union_cast(proc, lb_build_expr(proc, ta->expr), type, pos)); + lbValue v = lb_add_local_generated(p, type, false); + ir_emit_comment(p, str_lit("cast - union_cast")); + lb_emit_store(p, v, ir_emit_union_cast(p, lb_build_expr(p, ta->expr), type, pos)); return ir_addr(v); } 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); - 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 { 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(); // { // 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[2] = ir_emit_source_code_location(proc, proc_name, pos); - // lb_emit_runtime_call(proc, "__dynamic_map_reserve", args); + // args[2] = ir_emit_source_code_location(p, proc_name, pos); + // lb_emit_runtime_call(p, "__dynamic_map_reserve", args); // } // for_array(field_index, cl->elems) { // Ast *elem = cl->elems[field_index]; // ast_node(fv, FieldValue, elem); - // lbValue key = lb_build_expr(proc, fv->field); - // lbValue value = lb_build_expr(proc, fv->value); - // ir_insert_dynamic_map_key_and_value(proc, v, type, key, value); + // lbValue key = lb_build_expr(p, fv->field); + // lbValue value = lb_build_expr(p, fv->value); + // ir_insert_dynamic_map_key_and_value(p, v, type, key, value); // } break; } @@ -7334,13 +7336,13 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { { 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[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[5] = ir_emit_source_code_location(proc, proc_name, pos); - lb_emit_runtime_call(proc, "__dynamic_array_append", args); + args[5] = ir_emit_source_code_location(p, proc_name, pos); + lb_emit_runtime_call(p, "__dynamic_array_append", args); } #endif break; @@ -7551,6 +7553,563 @@ lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value) { 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) { lbModule *m = &gen->module; @@ -7818,24 +8377,22 @@ void lb_generate_code(lbGenerator *gen) { LLVMRunPassManager(module_pass_manager, mod); - if (!(build_context.is_dll && !has_dll_main)) { - LLVMContextRef ctx = LLVMGetModuleContext(mod); - + lbProcedure *startup_runtime = nullptr; + { // Startup Runtime 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); + Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl); - array_init(&results->Tuple.variables, heap_allocator(), 1); - results->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("_"), t_i32, false, true); + lbProcedure *p = lb_create_dummy_procedure(m, str_lit("__$startup_runtime"), proc_type); + startup_runtime = p; - Type *proc_type = alloc_type_proc(nullptr, params, 2, results, 1, false, ProcCC_CDecl); + lb_begin_procedure_body(p); - lbProcedure *p = lb_create_dummy_procedure(m, str_lit("main"), proc_type); + lb_emit_init_context(p); + + lb_setup_type_info_data(p); - lb_begin_procedure_body(p); for_array(i, global_variables) { auto *var = &global_variables[i]; 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)); 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, ""); LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false)); - lb_end_procedure_body(p); 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); if (ok) { gb_printf_err("LLVM Error: %s\n", llvm_error); + gb_exit(1); return; } |