mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-23 06:05:00 -07:00
Begin working on a minimum build
This commit is contained in:
@@ -1046,6 +1046,7 @@ gb_internal void init_universal(void) {
|
||||
add_global_bool_constant("ODIN_NO_RTTI", bc->no_rtti);
|
||||
|
||||
add_global_bool_constant("ODIN_VALGRIND_SUPPORT", bc->ODIN_VALGRIND_SUPPORT);
|
||||
add_global_bool_constant("ODIN_TILDE", bc->tilde_backend);
|
||||
|
||||
add_global_constant("ODIN_COMPILE_TIMESTAMP", t_untyped_integer, exact_value_i64(odin_compile_timestamp()));
|
||||
|
||||
@@ -2311,7 +2312,9 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
||||
str_lit("memory_equal"),
|
||||
str_lit("memory_compare"),
|
||||
str_lit("memory_compare_zero"),
|
||||
);
|
||||
|
||||
FORCE_ADD_RUNTIME_ENTITIES(!build_context.tilde_backend,
|
||||
// Extended data type internal procedures
|
||||
str_lit("umodti3"),
|
||||
str_lit("udivti3"),
|
||||
|
||||
+43
-1
@@ -126,6 +126,19 @@ gb_internal cgValue cg_lvalue_addr(TB_Node *node, Type *type) {
|
||||
return v;
|
||||
}
|
||||
|
||||
gb_internal cgValue cg_lvalue_addr_to_value(cgValue v) {
|
||||
if (v.kind == cgValue_Value) {
|
||||
GB_ASSERT(is_type_pointer(v.type));
|
||||
GB_ASSERT(v.node->dt.type == TB_PTR);
|
||||
} else {
|
||||
GB_ASSERT(v.kind == cgValue_Addr);
|
||||
GB_ASSERT(v.node->dt.type == TB_PTR);
|
||||
v.kind = cgValue_Value;
|
||||
v.type = alloc_type_pointer(v.type);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
gb_internal cgValue cg_value_multi(cgValueMulti *multi, Type *type) {
|
||||
GB_ASSERT(type->kind == Type_Tuple);
|
||||
GB_ASSERT(multi != nullptr);
|
||||
@@ -138,6 +151,24 @@ gb_internal cgValue cg_value_multi(cgValueMulti *multi, Type *type) {
|
||||
return v;
|
||||
}
|
||||
|
||||
gb_internal cgValue cg_value_multi(Slice<cgValue> const &values, Type *type) {
|
||||
cgValueMulti *multi = gb_alloc_item(permanent_allocator(), cgValueMulti);
|
||||
multi->values = values;
|
||||
return cg_value_multi(multi, type);
|
||||
}
|
||||
|
||||
|
||||
gb_internal cgValue cg_value_multi2(cgValue const &x, cgValue const &y, Type *type) {
|
||||
GB_ASSERT(type->kind == Type_Tuple);
|
||||
GB_ASSERT(type->Tuple.variables.count == 2);
|
||||
cgValueMulti *multi = gb_alloc_item(permanent_allocator(), cgValueMulti);
|
||||
multi->values = slice_make<cgValue>(permanent_allocator(), 2);
|
||||
multi->values[0] = x;
|
||||
multi->values[1] = y;
|
||||
return cg_value_multi(multi, type);
|
||||
}
|
||||
|
||||
|
||||
gb_internal cgAddr cg_addr(cgValue const &value) {
|
||||
GB_ASSERT(value.kind != cgValue_Multi);
|
||||
cgAddr addr = {};
|
||||
@@ -151,10 +182,21 @@ gb_internal cgAddr cg_addr(cgValue const &value) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
gb_internal void cg_set_debug_pos_from_node(cgProcedure *p, Ast *node) {
|
||||
if (node) {
|
||||
TokenPos pos = ast_token(node).pos;
|
||||
TB_FileID *file_id = map_get(&p->module->file_id_map, cast(uintptr)pos.file_id);
|
||||
if (file_id) {
|
||||
tb_inst_set_location(p->func, *file_id, pos.line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gb_internal void cg_add_entity(cgModule *m, Entity *e, cgValue const &val) {
|
||||
if (e) {
|
||||
rw_mutex_lock(&m->values_mutex);
|
||||
GB_ASSERT(val.node != nullptr);
|
||||
map_set(&m->values, e, val);
|
||||
rw_mutex_unlock(&m->values_mutex);
|
||||
}
|
||||
@@ -744,7 +786,7 @@ gb_internal bool cg_generate_code(Checker *c) {
|
||||
}
|
||||
|
||||
TB_DebugFormat debug_format = TB_DEBUGFMT_NONE;
|
||||
if (build_context.ODIN_DEBUG) {
|
||||
if (build_context.ODIN_DEBUG || true) {
|
||||
switch (build_context.metrics.os) {
|
||||
case TargetOs_windows:
|
||||
debug_format = TB_DEBUGFMT_CODEVIEW;
|
||||
|
||||
+7
-2
@@ -272,6 +272,7 @@ gb_internal void cg_build_when_stmt(cgProcedure *p, AstWhenStmt *ws);
|
||||
gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr);
|
||||
gb_internal cgAddr cg_build_addr(cgProcedure *p, Ast *expr);
|
||||
gb_internal cgValue cg_build_addr_ptr(cgProcedure *p, Ast *expr);
|
||||
gb_internal cgValue cg_build_cond(cgProcedure *p, Ast *cond, TB_Node *true_block, TB_Node *false_block);
|
||||
|
||||
gb_internal Type * cg_addr_type(cgAddr const &addr);
|
||||
gb_internal cgValue cg_addr_load(cgProcedure *p, cgAddr addr);
|
||||
@@ -279,13 +280,15 @@ gb_internal void cg_addr_store(cgProcedure *p, cgAddr addr, cgValue value);
|
||||
gb_internal cgValue cg_addr_get_ptr(cgProcedure *p, cgAddr const &addr);
|
||||
|
||||
gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_volatile=false);
|
||||
gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue const &src, bool is_volatile=false);
|
||||
gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue src, bool is_volatile=false);
|
||||
|
||||
gb_internal cgAddr cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero_init);
|
||||
gb_internal cgValue cg_address_from_load_or_generate_local(cgProcedure *p, cgValue value);
|
||||
gb_internal cgValue cg_copy_value_to_ptr(cgProcedure *p, cgValue value, Type *original_type, isize min_alignment);
|
||||
|
||||
gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr);
|
||||
gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return_results);
|
||||
gb_internal void cg_build_return_stmt_internal(cgProcedure *p, Slice<cgValue> const &results);
|
||||
|
||||
gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e);
|
||||
|
||||
@@ -300,6 +303,7 @@ gb_internal cgValue cg_emit_array_ep(cgProcedure *p, cgValue s, cgValue index);
|
||||
gb_internal cgValue cg_emit_array_epi(cgProcedure *p, cgValue s, i64 index);
|
||||
gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index);
|
||||
gb_internal cgValue cg_emit_deep_field_gep(cgProcedure *p, cgValue e, Selection const &sel);
|
||||
gb_internal cgValue cg_emit_struct_ev(cgProcedure *p, cgValue s, i64 index);
|
||||
|
||||
gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *t);
|
||||
gb_internal cgValue cg_emit_comp_against_nil(cgProcedure *p, TokenKind op_kind, cgValue x);
|
||||
@@ -315,4 +319,5 @@ gb_internal isize cg_append_tuple_values(cgProcedure *p, Array<cgValue> *dst_val
|
||||
gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TokenPos const &pos);
|
||||
|
||||
gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value);
|
||||
gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &x);
|
||||
gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &x);
|
||||
|
||||
|
||||
Binary file not shown.
@@ -61,6 +61,7 @@ gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &value) {
|
||||
cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type));
|
||||
cgValue data_ptr = cg_emit_struct_ep(p, ptr, 0);
|
||||
res = cg_emit_load(p, data_ptr);
|
||||
GB_ASSERT(is_type_multi_pointer(res.type));
|
||||
}
|
||||
break;
|
||||
case Type_DynamicArray:
|
||||
@@ -82,7 +83,12 @@ gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &value) {
|
||||
}
|
||||
break;
|
||||
case Type_Pointer:
|
||||
GB_ASSERT(is_type_array_like(t->Pointer.elem));
|
||||
GB_ASSERT(value.kind == cgValue_Value);
|
||||
res = cg_value(value.node, alloc_type_multi_pointer(base_array_type(t->Pointer.elem)));
|
||||
break;
|
||||
case Type_MultiPointer:
|
||||
|
||||
GB_PANIC("TODO(bill) %s", type_to_string(value.type));
|
||||
// res = cg_emit_conv(p, value, tv.type);
|
||||
break;
|
||||
@@ -102,6 +108,37 @@ gb_internal cgValue cg_builtin_max(cgProcedure *p, Type *t, cgValue x, cgValue y
|
||||
return cg_emit_select(p, cg_emit_comp(p, Token_Gt, x, y), x, y);
|
||||
}
|
||||
|
||||
gb_internal cgValue cg_builtin_abs(cgProcedure *p, cgValue x) {
|
||||
if (is_type_unsigned(x.type)) {
|
||||
return x;
|
||||
}
|
||||
|
||||
if (is_type_quaternion(x.type)) {
|
||||
GB_PANIC("TODO(bill): abs quaternion");
|
||||
} else if (is_type_complex(x.type)) {
|
||||
GB_PANIC("TODO(bill): abs complex");
|
||||
}
|
||||
|
||||
TB_DataType dt = cg_data_type(x.type);
|
||||
GB_ASSERT(!TB_IS_VOID_TYPE(dt));
|
||||
TB_Node *zero = nullptr;
|
||||
if (dt.type == TB_FLOAT) {
|
||||
if (dt.data == 32) {
|
||||
zero = tb_inst_float32(p->func, 0);
|
||||
} else if (dt.data == 64) {
|
||||
zero = tb_inst_float64(p->func, 0);
|
||||
}
|
||||
} else {
|
||||
zero = tb_inst_uint(p->func, dt, 0);
|
||||
}
|
||||
GB_ASSERT(zero != nullptr);
|
||||
|
||||
cgValue cond = cg_emit_comp(p, Token_Lt, x, cg_value(zero, x.type));
|
||||
cgValue neg = cg_emit_unary_arith(p, Token_Sub, x, x.type);
|
||||
return cg_emit_select(p, cond, neg, x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr) {
|
||||
ast_node(ce, CallExpr, expr);
|
||||
@@ -149,6 +186,12 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
|
||||
return cg_builtin_len(p, v);
|
||||
}
|
||||
|
||||
case BuiltinProc_raw_data:
|
||||
{
|
||||
cgValue v = cg_build_expr(p, ce->args[0]);
|
||||
return cg_builtin_raw_data(p, v);
|
||||
}
|
||||
|
||||
case BuiltinProc_min:
|
||||
if (ce->args.count == 2) {
|
||||
Type *t = type_of_expr(expr);
|
||||
@@ -176,6 +219,96 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
|
||||
}
|
||||
break;
|
||||
|
||||
case BuiltinProc_abs:
|
||||
{
|
||||
cgValue x = cg_build_expr(p, ce->args[0]);
|
||||
return cg_builtin_abs(p, x);
|
||||
}
|
||||
|
||||
case BuiltinProc_debug_trap:
|
||||
tb_inst_debugbreak(p->func);
|
||||
return {};
|
||||
case BuiltinProc_trap:
|
||||
tb_inst_trap(p->func);
|
||||
return {};
|
||||
|
||||
case BuiltinProc_mem_zero:
|
||||
{
|
||||
cgValue ptr = cg_build_expr(p, ce->args[0]);
|
||||
cgValue len = cg_build_expr(p, ce->args[1]);
|
||||
GB_ASSERT(ptr.kind == cgValue_Value);
|
||||
GB_ASSERT(len.kind == cgValue_Value);
|
||||
tb_inst_memzero(p->func, ptr.node, len.node, 1, false);
|
||||
return {};
|
||||
}
|
||||
|
||||
case BuiltinProc_mem_copy:
|
||||
{
|
||||
cgValue dst = cg_build_expr(p, ce->args[0]);
|
||||
cgValue src = cg_build_expr(p, ce->args[1]);
|
||||
cgValue len = cg_build_expr(p, ce->args[2]);
|
||||
GB_ASSERT(dst.kind == cgValue_Value);
|
||||
GB_ASSERT(src.kind == cgValue_Value);
|
||||
GB_ASSERT(len.kind == cgValue_Value);
|
||||
// TODO(bill): This needs to be memmove
|
||||
tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1, false);
|
||||
return {};
|
||||
}
|
||||
|
||||
case BuiltinProc_mem_copy_non_overlapping:
|
||||
{
|
||||
cgValue dst = cg_build_expr(p, ce->args[0]);
|
||||
cgValue src = cg_build_expr(p, ce->args[1]);
|
||||
cgValue len = cg_build_expr(p, ce->args[2]);
|
||||
GB_ASSERT(dst.kind == cgValue_Value);
|
||||
GB_ASSERT(src.kind == cgValue_Value);
|
||||
GB_ASSERT(len.kind == cgValue_Value);
|
||||
tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1, false);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
case BuiltinProc_overflow_add:
|
||||
{
|
||||
Type *res_type = type_of_expr(expr);
|
||||
GB_ASSERT(res_type->kind == Type_Tuple);
|
||||
GB_ASSERT(res_type->Tuple.variables.count == 2);
|
||||
// TODO(bill): do a proper overflow add
|
||||
Type *type = res_type->Tuple.variables[0]->type;
|
||||
Type *ok_type = res_type->Tuple.variables[1]->type;
|
||||
cgValue x = cg_build_expr(p, ce->args[0]);
|
||||
cgValue y = cg_build_expr(p, ce->args[1]);
|
||||
x = cg_emit_conv(p, x, type);
|
||||
y = cg_emit_conv(p, y, type);
|
||||
cgValue res = cg_emit_arith(p, Token_Add, x, y, type);
|
||||
cgValue ok = cg_const_int(p, ok_type, false);
|
||||
|
||||
return cg_value_multi2(res, ok, res_type);
|
||||
}
|
||||
|
||||
|
||||
case BuiltinProc_ptr_offset:
|
||||
{
|
||||
cgValue ptr = cg_build_expr(p, ce->args[0]);
|
||||
cgValue len = cg_build_expr(p, ce->args[1]);
|
||||
len = cg_emit_conv(p, len, t_int);
|
||||
return cg_emit_ptr_offset(p, ptr, len);
|
||||
}
|
||||
case BuiltinProc_ptr_sub:
|
||||
{
|
||||
Type *elem0 = type_deref(type_of_expr(ce->args[0]));
|
||||
Type *elem1 = type_deref(type_of_expr(ce->args[1]));
|
||||
GB_ASSERT(are_types_identical(elem0, elem1));
|
||||
Type *elem = elem0;
|
||||
|
||||
cgValue ptr0 = cg_emit_conv(p, cg_build_expr(p, ce->args[0]), t_uintptr);
|
||||
cgValue ptr1 = cg_emit_conv(p, cg_build_expr(p, ce->args[1]), t_uintptr);
|
||||
|
||||
cgValue diff = cg_emit_arith(p, Token_Sub, ptr0, ptr1, t_uintptr);
|
||||
diff = cg_emit_conv(p, diff, t_int);
|
||||
return cg_emit_arith(p, Token_Quo, diff, cg_const_int(p, t_int, type_size_of(elem)), t_int);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+78
-31
@@ -52,6 +52,13 @@ gb_internal cgValue cg_const_nil(cgProcedure *p, Type *type) {
|
||||
}
|
||||
|
||||
|
||||
gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, String const &proc_name, TokenPos pos) {
|
||||
// TODO(bill): cg_emit_source_code_location_as_global
|
||||
return cg_const_nil(p, t_source_code_location);
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_internal void cg_write_big_int_at_ptr(void *dst, BigInt const *a, Type *original_type) {
|
||||
GB_ASSERT(build_context.endian_kind == TargetEndian_Little);
|
||||
size_t sz = cast(size_t)type_size_of(original_type);
|
||||
@@ -109,7 +116,6 @@ gb_internal TB_Global *cg_global_const_string(cgModule *m, String const &str, Ty
|
||||
|
||||
char name[32] = {};
|
||||
gb_snprintf(name, 31, "csb$%u", 1+m->const_nil_guid.fetch_add(1));
|
||||
|
||||
TB_Global *str_global = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE);
|
||||
i64 size = str.len+1;
|
||||
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), str_global, size, 1, 1);
|
||||
@@ -125,6 +131,7 @@ gb_internal TB_Global *cg_global_const_string(cgModule *m, String const &str, Ty
|
||||
}
|
||||
|
||||
if (global == nullptr) {
|
||||
gb_snprintf(name, 31, "cstr$%u", 1+m->const_nil_guid.fetch_add(1));
|
||||
global = tb_global_create(m->mod, -1, name, cg_debug_type(m, type), TB_LINKAGE_PRIVATE);
|
||||
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, type_size_of(type), type_align_of(type), 2);
|
||||
}
|
||||
@@ -778,18 +785,47 @@ gb_internal TB_Global *cg_global_const_comp_literal(cgModule *m, Type *original_
|
||||
}
|
||||
|
||||
|
||||
gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, ExactValue const &value) {
|
||||
gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const &value) {
|
||||
GB_ASSERT(p != nullptr);
|
||||
TB_Node *node = nullptr;
|
||||
|
||||
if (is_type_untyped(type)) {
|
||||
// TODO(bill): THIS IS A COMPLETE HACK, WHY DOES THIS NOT A TYPE?
|
||||
GB_ASSERT(type->kind == Type_Basic);
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_UntypedBool:
|
||||
type = t_bool;
|
||||
break;
|
||||
case Basic_UntypedInteger:
|
||||
type = t_i64;
|
||||
break;
|
||||
case Basic_UntypedFloat:
|
||||
type = t_f64;
|
||||
break;
|
||||
case Basic_UntypedComplex:
|
||||
type = t_complex128;
|
||||
break;
|
||||
case Basic_UntypedQuaternion:
|
||||
type = t_quaternion256;
|
||||
break;
|
||||
case Basic_UntypedString:
|
||||
type = t_string;
|
||||
break;
|
||||
case Basic_UntypedRune:
|
||||
type = t_rune;
|
||||
break;
|
||||
case Basic_UntypedNil:
|
||||
case Basic_UntypedUninit:
|
||||
return cg_value(cast(TB_Node *)nullptr, type);
|
||||
}
|
||||
}
|
||||
TB_DataType dt = cg_data_type(type);
|
||||
|
||||
switch (value.kind) {
|
||||
case ExactValue_Invalid:
|
||||
GB_ASSERT(p != nullptr);
|
||||
return cg_const_nil(p, type);
|
||||
|
||||
case ExactValue_Typeid:
|
||||
GB_ASSERT(p != nullptr);
|
||||
return cg_typeid(p, value.value_typeid);
|
||||
|
||||
case ExactValue_Procedure:
|
||||
@@ -797,13 +833,13 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
|
||||
Ast *expr = unparen_expr(value.value_procedure);
|
||||
Entity *e = entity_of_node(expr);
|
||||
if (e != nullptr) {
|
||||
cgValue found = cg_find_procedure_value_from_entity(m, e);
|
||||
GB_ASSERT(are_types_identical(type, found.type));
|
||||
cgValue found = cg_find_procedure_value_from_entity(p->module, e);
|
||||
GB_ASSERT_MSG(are_types_identical(type, found.type),
|
||||
"%.*s %s == %s",
|
||||
LIT(p->name),
|
||||
type_to_string(type), type_to_string(found.type));
|
||||
GB_ASSERT(found.kind == cgValue_Symbol);
|
||||
if (p) {
|
||||
return cg_flatten_value(p, found);
|
||||
}
|
||||
return found;
|
||||
return cg_flatten_value(p, found);
|
||||
}
|
||||
GB_PANIC("TODO(bill): cg_const_value ExactValue_Procedure");
|
||||
}
|
||||
@@ -812,12 +848,10 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
|
||||
|
||||
switch (value.kind) {
|
||||
case ExactValue_Bool:
|
||||
GB_ASSERT(p != nullptr);
|
||||
GB_ASSERT(!TB_IS_VOID_TYPE(dt));
|
||||
return cg_value(tb_inst_uint(p->func, dt, value.value_bool), type);
|
||||
|
||||
case ExactValue_Integer:
|
||||
GB_ASSERT(p != nullptr);
|
||||
GB_ASSERT(!TB_IS_VOID_TYPE(dt));
|
||||
// GB_ASSERT(dt.raw != TB_TYPE_I128.raw);
|
||||
if (is_type_unsigned(type)) {
|
||||
@@ -830,7 +864,6 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
|
||||
break;
|
||||
|
||||
case ExactValue_Float:
|
||||
GB_ASSERT(p != nullptr);
|
||||
GB_ASSERT(!TB_IS_VOID_TYPE(dt));
|
||||
GB_ASSERT(dt.raw != TB_TYPE_F16.raw);
|
||||
GB_ASSERT(!is_type_different_to_arch_endianness(type));
|
||||
@@ -846,13 +879,36 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
|
||||
|
||||
case ExactValue_String:
|
||||
{
|
||||
TB_Symbol *symbol = cast(TB_Symbol *)cg_global_const_string(m, value.value_string, type, nullptr, 0);
|
||||
if (p) {
|
||||
TB_Node *node = tb_inst_get_symbol_address(p->func, symbol);
|
||||
return cg_lvalue_addr(node, type);
|
||||
} else {
|
||||
return cg_value(symbol, alloc_type_pointer(type));
|
||||
GB_ASSERT(is_type_string(type));
|
||||
cgModule *m = p->module;
|
||||
|
||||
String str = value.value_string;
|
||||
|
||||
char name[32] = {};
|
||||
gb_snprintf(name, 31, "csb$%u", 1+m->const_nil_guid.fetch_add(1));
|
||||
TB_Global *cstr_global = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE);
|
||||
i64 size = str.len+1;
|
||||
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), cstr_global, size, 1, 1);
|
||||
u8 *data = cast(u8 *)tb_global_add_region(m->mod, cstr_global, 0, size);
|
||||
gb_memcopy(data, str.text, str.len);
|
||||
data[str.len] = 0;
|
||||
|
||||
if (is_type_cstring(type)) {
|
||||
cgValue s = cg_value(cstr_global, type);
|
||||
return cg_flatten_value(p, s);
|
||||
}
|
||||
|
||||
gb_snprintf(name, 31, "str$%u", 1+m->const_nil_guid.fetch_add(1));
|
||||
TB_Global *str_global = tb_global_create(m->mod, -1, name, cg_debug_type(m, type), TB_LINKAGE_PRIVATE);
|
||||
tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), str_global, type_size_of(type), type_align_of(type), 2);
|
||||
|
||||
tb_global_add_symbol_reloc(m->mod, str_global, 0, cast(TB_Symbol *)cstr_global);
|
||||
void *len_ptr = tb_global_add_region(m->mod, str_global, build_context.int_size, build_context.int_size);
|
||||
cg_write_int_at_ptr(len_ptr, str.len, t_int);
|
||||
|
||||
TB_Node *s = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)str_global);
|
||||
return cg_lvalue_addr(s, type);
|
||||
|
||||
}
|
||||
|
||||
case ExactValue_Pointer:
|
||||
@@ -860,13 +916,9 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
|
||||
|
||||
case ExactValue_Compound:
|
||||
{
|
||||
TB_Symbol *symbol = cast(TB_Symbol *)cg_global_const_comp_literal(m, type, value, nullptr, 0);
|
||||
if (p) {
|
||||
TB_Node *node = tb_inst_get_symbol_address(p->func, symbol);
|
||||
return cg_lvalue_addr(node, type);
|
||||
} else {
|
||||
return cg_value(symbol, type);
|
||||
}
|
||||
TB_Symbol *symbol = cast(TB_Symbol *)cg_global_const_comp_literal(p->module, type, value, nullptr, 0);
|
||||
TB_Node *node = tb_inst_get_symbol_address(p->func, symbol);
|
||||
return cg_lvalue_addr(node, type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -876,11 +928,6 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
|
||||
return cg_value(node, type);
|
||||
}
|
||||
|
||||
gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const &value) {
|
||||
GB_ASSERT(p != nullptr);
|
||||
return cg_const_value(p->module, p, type, value);
|
||||
}
|
||||
|
||||
gb_internal cgValue cg_const_int(cgProcedure *p, Type *type, i64 i) {
|
||||
return cg_const_value(p, type, exact_value_i64(i));
|
||||
}
|
||||
|
||||
+5
-1
@@ -368,7 +368,11 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) {
|
||||
param_count += 1;
|
||||
}
|
||||
|
||||
TB_DebugType *func = tb_debug_create_func(m->mod, TB_CDECL, param_count, return_count, pt->c_vararg);
|
||||
TB_CallingConv tb_cc = TB_CDECL;
|
||||
if (pt->calling_convention == ProcCC_StdCall) {
|
||||
tb_cc = TB_STDCALL;
|
||||
}
|
||||
TB_DebugType *func = tb_debug_create_func(m->mod, tb_cc, param_count, return_count, pt->c_vararg);
|
||||
|
||||
map_set(&m->proc_debug_type_map, original_type, func);
|
||||
map_set(&m->proc_debug_type_map, type, func);
|
||||
|
||||
+801
-131
File diff suppressed because it is too large
Load Diff
+68
-36
@@ -86,6 +86,10 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i
|
||||
}
|
||||
p->symbol = cast(TB_Symbol *)tb_extern_create(m->mod, link_name.len, cast(char const *)link_name.text, TB_EXTERNAL_SO_LOCAL);
|
||||
}
|
||||
if (p->name == "main") {
|
||||
// TODO(bill): figure out when this should be public or not
|
||||
linkage = TB_LINKAGE_PUBLIC;
|
||||
}
|
||||
|
||||
if (p->symbol == nullptr) {
|
||||
p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE);
|
||||
@@ -97,9 +101,9 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i
|
||||
p->symbol = cast(TB_Symbol *)p->func;
|
||||
}
|
||||
|
||||
cgValue proc_value = cg_value(p->symbol, p->type);
|
||||
cg_add_entity(m, entity, proc_value);
|
||||
cg_add_member(m, p->name, proc_value);
|
||||
p->value = cg_value(p->symbol, p->type);
|
||||
cg_add_entity(m, entity, p->value);
|
||||
cg_add_member(m, p->name, p->value);
|
||||
cg_add_procedure_value(m, p);
|
||||
|
||||
|
||||
@@ -275,7 +279,9 @@ gb_internal void cg_procedure_begin(cgProcedure *p) {
|
||||
// }
|
||||
}
|
||||
|
||||
p->split_returns_index = param_index;
|
||||
if (is_odin_like_cc) {
|
||||
p->split_returns_index = param_index;
|
||||
}
|
||||
|
||||
if (pt->calling_convention == ProcCC_Odin) {
|
||||
// NOTE(bill): Push context on to stack from implicit parameter
|
||||
@@ -323,9 +329,15 @@ gb_internal void cg_procedure_end(cgProcedure *p) {
|
||||
return;
|
||||
}
|
||||
if (tb_inst_get_control(p->func)) {
|
||||
GB_ASSERT(p->type->Proc.result_count == 0);
|
||||
tb_inst_ret(p->func, 0, nullptr);
|
||||
}
|
||||
bool emit_asm = false;
|
||||
|
||||
if (string_starts_with(p->name, str_lit("bug@main"))) {
|
||||
// emit_asm = true;
|
||||
}
|
||||
|
||||
TB_FunctionOutput *output = tb_module_compile_function(p->module->mod, p->func, TB_ISEL_FAST, emit_asm);
|
||||
if (emit_asm) {
|
||||
TB_Assembly *assembly = tb_output_get_asm(output);
|
||||
@@ -336,45 +348,68 @@ gb_internal void cg_procedure_end(cgProcedure *p) {
|
||||
}
|
||||
}
|
||||
|
||||
gb_global String procedures_to_generate_list[] = {
|
||||
str_lit("bug" ABI_PKG_NAME_SEPARATOR "main"),
|
||||
str_lit("main"),
|
||||
};
|
||||
|
||||
gb_internal void cg_procedure_generate(cgProcedure *p) {
|
||||
if (p->body == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool build_body = false;
|
||||
|
||||
if (
|
||||
string_starts_with(p->name, str_lit("runtime" ABI_PKG_NAME_SEPARATOR "_os_write")) ||
|
||||
// p->name == "bug" ABI_PKG_NAME_SEPARATOR "main" ||
|
||||
// p->name == "main" ||
|
||||
false
|
||||
) {
|
||||
build_body = true;
|
||||
}
|
||||
|
||||
if (build_body) {
|
||||
cg_procedure_begin(p);
|
||||
cg_build_stmt(p, p->body);
|
||||
}
|
||||
cg_procedure_begin(p);
|
||||
cg_build_stmt(p, p->body);
|
||||
cg_procedure_end(p);
|
||||
|
||||
if (build_body) {
|
||||
if (string_starts_with(p->name, str_lit("bug@main"))) { // IR Printing
|
||||
TB_Arena *arena = tb_default_arena();
|
||||
defer (arena->free(arena));
|
||||
TB_FuncOpt *opt = tb_funcopt_enter(p->func, arena);
|
||||
defer (tb_funcopt_exit(opt));
|
||||
tb_funcopt_print(opt);
|
||||
|
||||
// GraphViz printing
|
||||
// tb_function_print(p->func, tb_default_print_callback, stdout);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
if (false) { // GraphViz printing
|
||||
tb_function_print(p->func, tb_default_print_callback, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal void cg_build_nested_proc(cgProcedure *p, AstProcLit *pd, Entity *e) {
|
||||
GB_ASSERT(pd->body != nullptr);
|
||||
cgModule *m = p->module;
|
||||
auto *min_dep_set = &m->info->minimum_dependency_set;
|
||||
|
||||
if (ptr_set_exists(min_dep_set, e) == false) {
|
||||
// NOTE(bill): Nothing depends upon it so doesn't need to be built
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent.name-guid
|
||||
String original_name = e->token.string;
|
||||
String pd_name = original_name;
|
||||
if (e->Procedure.link_name.len > 0) {
|
||||
pd_name = e->Procedure.link_name;
|
||||
}
|
||||
|
||||
|
||||
isize name_len = p->name.len + 1 + pd_name.len + 1 + 10 + 1;
|
||||
char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
|
||||
|
||||
i32 guid = cast(i32)p->children.count;
|
||||
name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%d", LIT(p->name), LIT(pd_name), guid);
|
||||
String name = make_string(cast(u8 *)name_text, name_len-1);
|
||||
|
||||
e->Procedure.link_name = name;
|
||||
|
||||
cgProcedure *nested_proc = cg_procedure_create(p->module, e);
|
||||
e->cg_procedure = nested_proc;
|
||||
|
||||
cgValue value = nested_proc->value;
|
||||
|
||||
cg_add_entity(m, e, value);
|
||||
array_add(&p->children, nested_proc);
|
||||
array_add(&m->procedures_to_generate, nested_proc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e) {
|
||||
@@ -388,6 +423,7 @@ gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e)
|
||||
found = map_get(&m->values, e);
|
||||
rw_mutex_shared_unlock(&m->values_mutex);
|
||||
if (found) {
|
||||
GB_ASSERT(found->node != nullptr);
|
||||
return *found;
|
||||
}
|
||||
|
||||
@@ -408,9 +444,6 @@ gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr) {
|
||||
GB_ASSERT(res.kind == cgValue_Multi);
|
||||
GB_ASSERT(res.multi->values.count == 2);
|
||||
return res.multi->values[0];
|
||||
// GB_ASSERT(is_type_tuple(res.type));
|
||||
// GB_ASSERT(res.type->Tuple.variables.count == 2);
|
||||
// return cg_emit_struct_ev(p, res, 0);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -470,8 +503,9 @@ gb_internal cgValue cg_emit_call(cgProcedure * p, cgValue value, Slice<cgValue>
|
||||
params[param_index++] = local;
|
||||
}
|
||||
}
|
||||
for (cgValue arg : args) {
|
||||
Type *param_type = param_entities[param_index]->type;
|
||||
for_array(i, args) {
|
||||
Type *param_type = param_entities[i]->type;
|
||||
cgValue arg = args[i];
|
||||
arg = cg_emit_conv(p, arg, param_type);
|
||||
arg = cg_flatten_value(p, arg);
|
||||
|
||||
@@ -629,9 +663,7 @@ gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type,
|
||||
if (p->entity != nullptr) {
|
||||
proc_name = p->entity->token.string;
|
||||
}
|
||||
GB_PANIC("TODO(bill): cg_emit_source_code_location_as_global");
|
||||
// return cg_emit_source_code_location_as_global(p, proc_name, pos);
|
||||
break;
|
||||
return cg_emit_source_code_location_as_global(p, proc_name, pos);
|
||||
}
|
||||
case ParameterValue_Value:
|
||||
return cg_build_expr(p, param_value.ast_value);
|
||||
|
||||
+230
-67
@@ -65,7 +65,7 @@ gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_vol
|
||||
return cg_value(tb_inst_load(p->func, dt, the_ptr, alignment, is_volatile), type);
|
||||
}
|
||||
|
||||
gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue const &src, bool is_volatile) {
|
||||
gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue src, bool is_volatile) {
|
||||
GB_ASSERT_MSG(dst.kind != cgValue_Multi, "cannot store to multiple values at once");
|
||||
|
||||
if (dst.kind == cgValue_Addr) {
|
||||
@@ -122,10 +122,14 @@ gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue const &src,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (dst.kind) {
|
||||
case cgValue_Value:
|
||||
switch (dst.kind) {
|
||||
switch (src.kind) {
|
||||
case cgValue_Value:
|
||||
if (src.node->dt.type == TB_INT && src.node->dt.data == 1) {
|
||||
src.node = tb_inst_zxt(p->func, src.node, dt);
|
||||
}
|
||||
tb_inst_store(p->func, dt, dst.node, src.node, alignment, is_volatile);
|
||||
return;
|
||||
case cgValue_Addr:
|
||||
@@ -367,8 +371,7 @@ gb_internal cgValue cg_emit_ptr_offset(cgProcedure *p, cgValue ptr, cgValue inde
|
||||
|
||||
Type *elem = type_deref(ptr.type, true);
|
||||
i64 stride = type_size_of(elem);
|
||||
ptr.node = tb_inst_array_access(p->func, ptr.node, index.node, stride);
|
||||
return ptr;
|
||||
return cg_value(tb_inst_array_access(p->func, ptr.node, index.node, stride), alloc_type_pointer(elem));
|
||||
}
|
||||
gb_internal cgValue cg_emit_array_ep(cgProcedure *p, cgValue s, cgValue index) {
|
||||
GB_ASSERT(s.kind == cgValue_Value);
|
||||
@@ -383,8 +386,7 @@ gb_internal cgValue cg_emit_array_ep(cgProcedure *p, cgValue s, cgValue index) {
|
||||
|
||||
Type *elem = base_array_type(st);
|
||||
i64 stride = type_size_of(elem);
|
||||
s.node = tb_inst_array_access(p->func, s.node, index.node, stride);
|
||||
return s;
|
||||
return cg_value(tb_inst_array_access(p->func, s.node, index.node, stride), alloc_type_pointer(elem));
|
||||
}
|
||||
gb_internal cgValue cg_emit_array_epi(cgProcedure *p, cgValue s, i64 index) {
|
||||
return cg_emit_array_ep(p, s, cg_const_int(p, t_int, index));
|
||||
@@ -425,7 +427,7 @@ gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) {
|
||||
case Type_Slice:
|
||||
switch (index) {
|
||||
case 0:
|
||||
result_type = alloc_type_pointer(t->Slice.elem);
|
||||
result_type = alloc_type_multi_pointer(t->Slice.elem);
|
||||
offset = 0;
|
||||
break;
|
||||
case 1:
|
||||
@@ -439,7 +441,7 @@ gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) {
|
||||
case Basic_string:
|
||||
switch (index) {
|
||||
case 0:
|
||||
result_type = t_u8_ptr;
|
||||
result_type = t_u8_multi_ptr;
|
||||
offset = 0;
|
||||
break;
|
||||
case 1:
|
||||
@@ -494,7 +496,7 @@ gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) {
|
||||
case Type_DynamicArray:
|
||||
switch (index) {
|
||||
case 0:
|
||||
result_type = alloc_type_pointer(t->DynamicArray.elem);
|
||||
result_type = alloc_type_multi_pointer(t->DynamicArray.elem);
|
||||
offset = index*int_size;
|
||||
break;
|
||||
case 1: case 2:
|
||||
@@ -564,6 +566,14 @@ gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
gb_internal cgValue cg_emit_struct_ev(cgProcedure *p, cgValue s, i64 index) {
|
||||
s = cg_address_from_load_or_generate_local(p, s);
|
||||
cgValue ptr = cg_emit_struct_ep(p, s, index);
|
||||
return cg_flatten_value(p, cg_emit_load(p, ptr));
|
||||
}
|
||||
|
||||
|
||||
gb_internal cgValue cg_emit_deep_field_gep(cgProcedure *p, cgValue e, Selection const &sel) {
|
||||
GB_ASSERT(sel.index.count > 0);
|
||||
Type *type = type_deref(e.type);
|
||||
@@ -1008,6 +1018,110 @@ gb_internal void cg_build_assign_stmt(cgProcedure *p, AstAssignStmt *as) {
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal void cg_build_return_stmt_internal(cgProcedure *p, Slice<cgValue> const &results) {
|
||||
TypeTuple *tuple = &p->type->Proc.results->Tuple;
|
||||
isize return_count = p->type->Proc.result_count;
|
||||
|
||||
if (return_count == 0) {
|
||||
tb_inst_ret(p->func, 0, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->split_returns_index >= 0) {
|
||||
GB_ASSERT(is_calling_convention_odin(p->type->Proc.calling_convention));
|
||||
|
||||
for (isize i = 0; i < return_count-1; i++) {
|
||||
Entity *e = tuple->variables[i];
|
||||
TB_Node *ret_ptr = tb_inst_param(p->func, cast(int)(p->split_returns_index+i));
|
||||
cgValue ptr = cg_value(ret_ptr, alloc_type_pointer(e->type));
|
||||
cg_emit_store(p, ptr, results[i]);
|
||||
}
|
||||
|
||||
if (p->return_by_ptr) {
|
||||
Entity *e = tuple->variables[return_count-1];
|
||||
TB_Node *ret_ptr = tb_inst_param(p->func, 0);
|
||||
cgValue ptr = cg_value(ret_ptr, alloc_type_pointer(e->type));
|
||||
cg_emit_store(p, ptr, results[return_count-1]);
|
||||
|
||||
tb_inst_ret(p->func, 0, nullptr);
|
||||
return;
|
||||
} else {
|
||||
GB_ASSERT(p->proto->return_count == 1);
|
||||
TB_DataType dt = TB_PROTOTYPE_RETURNS(p->proto)->dt;
|
||||
|
||||
cgValue result = results[return_count-1];
|
||||
result = cg_flatten_value(p, result);
|
||||
TB_Node *final_res = nullptr;
|
||||
if (result.kind == cgValue_Addr) {
|
||||
TB_CharUnits align = cast(TB_CharUnits)type_align_of(result.type);
|
||||
final_res = tb_inst_load(p->func, dt, result.node, align, false);
|
||||
} else {
|
||||
GB_ASSERT(result.kind == cgValue_Value);
|
||||
TB_DataType st = result.node->dt;
|
||||
GB_ASSERT(st.type == dt.type);
|
||||
if (st.raw == dt.raw) {
|
||||
final_res = result.node;
|
||||
} else if (st.type == TB_INT && st.data == 1) {
|
||||
final_res = tb_inst_zxt(p->func, result.node, dt);
|
||||
} else {
|
||||
final_res = tb_inst_bitcast(p->func, result.node, dt);
|
||||
}
|
||||
}
|
||||
GB_ASSERT(final_res != nullptr);
|
||||
|
||||
tb_inst_ret(p->func, 1, &final_res);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
GB_ASSERT(!is_calling_convention_odin(p->type->Proc.calling_convention));
|
||||
|
||||
if (p->return_by_ptr) {
|
||||
Entity *e = tuple->variables[return_count-1];
|
||||
TB_Node *ret_ptr = tb_inst_param(p->func, 0);
|
||||
cgValue ptr = cg_value(ret_ptr, alloc_type_pointer(e->type));
|
||||
cg_emit_store(p, ptr, results[return_count-1]);
|
||||
|
||||
tb_inst_ret(p->func, 0, nullptr);
|
||||
return;
|
||||
} else {
|
||||
GB_ASSERT(p->proto->return_count == 1);
|
||||
TB_DataType dt = TB_PROTOTYPE_RETURNS(p->proto)->dt;
|
||||
if (results.count == 1) {
|
||||
cgValue result = results[0];
|
||||
result = cg_flatten_value(p, result);
|
||||
|
||||
TB_Node *final_res = nullptr;
|
||||
if (result.kind == cgValue_Addr) {
|
||||
TB_CharUnits align = cast(TB_CharUnits)type_align_of(result.type);
|
||||
final_res = tb_inst_load(p->func, dt, result.node, align, false);
|
||||
} else {
|
||||
GB_ASSERT(result.kind == cgValue_Value);
|
||||
TB_DataType st = result.node->dt;
|
||||
GB_ASSERT(st.type == dt.type);
|
||||
if (st.raw == dt.raw) {
|
||||
final_res = result.node;
|
||||
} else if (st.type == TB_INT && st.data == 1) {
|
||||
final_res = tb_inst_zxt(p->func, result.node, dt);
|
||||
} else {
|
||||
final_res = tb_inst_bitcast(p->func, result.node, dt);
|
||||
}
|
||||
}
|
||||
|
||||
GB_ASSERT(final_res != nullptr);
|
||||
|
||||
tb_inst_ret(p->func, 1, &final_res);
|
||||
return;
|
||||
} else {
|
||||
GB_ASSERT_MSG(results.count == 1, "TODO(bill): multi-return values for the return");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return_results) {
|
||||
TypeTuple *tuple = &p->type->Proc.results->Tuple;
|
||||
isize return_count = p->type->Proc.result_count;
|
||||
@@ -1048,54 +1162,7 @@ gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return
|
||||
results[i] = cg_emit_conv(p, results[i], e->type);
|
||||
}
|
||||
|
||||
|
||||
if (p->split_returns_index >= 0) {
|
||||
GB_ASSERT(is_calling_convention_odin(p->type->Proc.calling_convention));
|
||||
|
||||
for (isize i = 0; i < return_count-1; i++) {
|
||||
Entity *e = tuple->variables[i];
|
||||
TB_Node *ret_ptr = tb_inst_param(p->func, cast(int)(p->split_returns_index+i));
|
||||
cgValue ptr = cg_value(ret_ptr, alloc_type_pointer(e->type));
|
||||
cg_emit_store(p, ptr, results[i]);
|
||||
}
|
||||
|
||||
if (p->return_by_ptr) {
|
||||
Entity *e = tuple->variables[return_count-1];
|
||||
TB_Node *ret_ptr = tb_inst_param(p->func, 0);
|
||||
cgValue ptr = cg_value(ret_ptr, alloc_type_pointer(e->type));
|
||||
cg_emit_store(p, ptr, results[return_count-1]);
|
||||
|
||||
tb_inst_ret(p->func, 0, nullptr);
|
||||
return;
|
||||
} else {
|
||||
GB_ASSERT(p->proto->return_count == 1);
|
||||
TB_DataType dt = TB_PROTOTYPE_RETURNS(p->proto)->dt;
|
||||
|
||||
cgValue result = cg_flatten_value(p, results[0]);
|
||||
TB_Node *final_res = nullptr;
|
||||
if (result.kind == cgValue_Addr) {
|
||||
TB_CharUnits align = cast(TB_CharUnits)type_align_of(result.type);
|
||||
final_res = tb_inst_load(p->func, dt, result.node, align, false);
|
||||
} else {
|
||||
GB_ASSERT(result.kind == cgValue_Value);
|
||||
if (result.node->dt.raw == dt.raw) {
|
||||
final_res = result.node;
|
||||
} else {
|
||||
final_res = tb_inst_bitcast(p->func, result.node, dt);
|
||||
}
|
||||
}
|
||||
GB_ASSERT(final_res != nullptr);
|
||||
|
||||
tb_inst_ret(p->func, 1, &final_res);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
GB_ASSERT(!is_calling_convention_odin(p->type->Proc.calling_convention));
|
||||
}
|
||||
|
||||
|
||||
GB_PANIC("TODO(bill): %.*s MUTLIPLE RETURN VALUES %td %td", LIT(p->name), results.count, return_results.count);
|
||||
cg_build_return_stmt_internal(p, slice_from_array(results));
|
||||
}
|
||||
|
||||
gb_internal void cg_build_if_stmt(cgProcedure *p, Ast *node) {
|
||||
@@ -1673,13 +1740,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
|
||||
|
||||
// TODO(bill): check if last instruction was a terminating one or not
|
||||
|
||||
{
|
||||
TokenPos pos = ast_token(node).pos;
|
||||
TB_FileID *file_id = map_get(&p->module->file_id_map, cast(uintptr)pos.file_id);
|
||||
if (file_id) {
|
||||
tb_inst_set_location(p->func, *file_id, pos.line);
|
||||
}
|
||||
}
|
||||
cg_set_debug_pos_from_node(p, node);
|
||||
|
||||
u16 prev_state_flags = p->state_flags;
|
||||
defer (p->state_flags = prev_state_flags);
|
||||
@@ -1838,7 +1899,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(rs, RangeStmt, node);
|
||||
GB_PANIC("TODO(bill): cg_build_range_stmt");
|
||||
GB_PANIC("TODO(bill): cg_build_range_stmt %.*s", LIT(p->name));
|
||||
// cg_build_range_stmt(p, rs, rs->scope);
|
||||
case_end;
|
||||
|
||||
@@ -1879,13 +1940,115 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal void cg_build_constant_value_decl(cgProcedure *p, AstValueDecl *vd) {
|
||||
if (vd == nullptr || vd->is_mutable) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto *min_dep_set = &p->module->info->minimum_dependency_set;
|
||||
|
||||
static i32 global_guid = 0;
|
||||
|
||||
for (Ast *ident : vd->names) {
|
||||
GB_ASSERT(ident->kind == Ast_Ident);
|
||||
Entity *e = entity_of_node(ident);
|
||||
GB_ASSERT(e != nullptr);
|
||||
if (e->kind != Entity_TypeName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool polymorphic_struct = false;
|
||||
if (e->type != nullptr && e->kind == Entity_TypeName) {
|
||||
Type *bt = base_type(e->type);
|
||||
if (bt->kind == Type_Struct) {
|
||||
polymorphic_struct = bt->Struct.is_polymorphic;
|
||||
}
|
||||
}
|
||||
|
||||
if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->TypeName.ir_mangled_name.len != 0) {
|
||||
// NOTE(bill): Already set
|
||||
continue;
|
||||
}
|
||||
|
||||
cg_set_nested_type_name_ir_mangled_name(e, p);
|
||||
}
|
||||
|
||||
for_array(i, vd->names) {
|
||||
Ast *ident = vd->names[i];
|
||||
GB_ASSERT(ident->kind == Ast_Ident);
|
||||
Entity *e = entity_of_node(ident);
|
||||
GB_ASSERT(e != nullptr);
|
||||
if (e->kind != Entity_Procedure) {
|
||||
continue;
|
||||
}
|
||||
GB_ASSERT (vd->values[i] != nullptr);
|
||||
|
||||
Ast *value = unparen_expr(vd->values[i]);
|
||||
if (value->kind != Ast_ProcLit) {
|
||||
continue; // It's an alias
|
||||
}
|
||||
|
||||
DeclInfo *decl = decl_info_of_entity(e);
|
||||
ast_node(pl, ProcLit, decl->proc_lit);
|
||||
if (pl->body != nullptr) {
|
||||
GenProcsData *gpd = e->Procedure.gen_procs;
|
||||
if (gpd) {
|
||||
rw_mutex_shared_lock(&gpd->mutex);
|
||||
for (Entity *e : gpd->procs) {
|
||||
if (!ptr_set_exists(min_dep_set, e)) {
|
||||
continue;
|
||||
}
|
||||
DeclInfo *d = decl_info_of_entity(e);
|
||||
cg_build_nested_proc(p, &d->proc_lit->ProcLit, e);
|
||||
}
|
||||
rw_mutex_shared_unlock(&gpd->mutex);
|
||||
} else {
|
||||
cg_build_nested_proc(p, pl, e);
|
||||
}
|
||||
} else {
|
||||
|
||||
// FFI - Foreign function interace
|
||||
String original_name = e->token.string;
|
||||
String name = original_name;
|
||||
|
||||
if (e->Procedure.is_foreign) {
|
||||
GB_PANIC("cg_add_foreign_library_path");
|
||||
// cg_add_foreign_library_path(p->module, e->Procedure.foreign_library);
|
||||
}
|
||||
|
||||
if (e->Procedure.link_name.len > 0) {
|
||||
name = e->Procedure.link_name;
|
||||
}
|
||||
|
||||
cgValue *prev_value = string_map_get(&p->module->members, name);
|
||||
if (prev_value != nullptr) {
|
||||
// NOTE(bill): Don't do mutliple declarations in the IR
|
||||
return;
|
||||
}
|
||||
|
||||
e->Procedure.link_name = name;
|
||||
|
||||
cgProcedure *nested_proc = cg_procedure_create(p->module, e);
|
||||
|
||||
cgValue value = p->value;
|
||||
|
||||
array_add(&p->module->procedures_to_generate, nested_proc);
|
||||
array_add(&p->children, nested_proc);
|
||||
string_map_set(&p->module->members, name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gb_internal void cg_build_stmt_list(cgProcedure *p, Slice<Ast *> const &stmts) {
|
||||
for (Ast *stmt : stmts) {
|
||||
switch (stmt->kind) {
|
||||
case_ast_node(vd, ValueDecl, stmt);
|
||||
// TODO(bill)
|
||||
// cg_build_constant_value_decl(p, vd);
|
||||
cg_build_constant_value_decl(p, vd);
|
||||
case_end;
|
||||
case_ast_node(fb, ForeignBlockDecl, stmt);
|
||||
ast_node(block, BlockStmt, fb->body);
|
||||
|
||||
Reference in New Issue
Block a user