diff options
| author | gingerBill <bill@gingerbill.org> | 2023-07-22 10:16:28 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2023-07-22 10:16:28 +0100 |
| commit | eec3b3009f0005090ddd5a7901e5f3c38cf31ce1 (patch) | |
| tree | 696b4ddfd242fcbb3f7655dc7272a2197ac785fa /src/tilde_expr.cpp | |
| parent | 4654b41c3e6a01118e28e6297b2de97bd0a8cd42 (diff) | |
Begin work on builtin procedures
Diffstat (limited to 'src/tilde_expr.cpp')
| -rw-r--r-- | src/tilde_expr.cpp | 486 |
1 files changed, 479 insertions, 7 deletions
diff --git a/src/tilde_expr.cpp b/src/tilde_expr.cpp index 2d4b11336..c0ddc4e70 100644 --- a/src/tilde_expr.cpp +++ b/src/tilde_expr.cpp @@ -179,7 +179,7 @@ gb_internal cgValue cg_emit_transmute(cgProcedure *p, cgValue value, Type *type) TB_DataType dt = cg_data_type(type); switch (value.kind) { case cgValue_Value: - GB_ASSERT(!TB_IS_VOID_TYPE(dt)); + GB_ASSERT_MSG(!TB_IS_VOID_TYPE(dt), "%s", type_to_string(type)); value.type = type; if (value.node->dt.raw != dt.raw) { value.node = tb_inst_bitcast(p->func, value.node, dt); @@ -1959,6 +1959,255 @@ gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr) { } +gb_internal cgValue cg_find_ident(cgProcedure *p, Entity *e, Ast *expr) { + cgAddr *found_addr = map_get(&p->variable_map, e); + if (found_addr) { + return cg_addr_load(p, *found_addr); + } + + cgValue *found = nullptr; + rw_mutex_shared_lock(&p->module->values_mutex); + found = map_get(&p->module->values, e); + rw_mutex_shared_unlock(&p->module->values_mutex); + + if (found) { + + auto v = *found; + // NOTE(bill): This is because pointers are already pointers in LLVM + if (is_type_proc(v.type)) { + return v; + } + return cg_emit_load(p, v); + } else if (e != nullptr && e->kind == Entity_Variable) { + return cg_addr_load(p, cg_build_addr(p, expr)); + } + + if (e->kind == Entity_Procedure) { + return cg_find_procedure_value_from_entity(p->module, e); + } + + String pkg = {}; + if (e->pkg) { + pkg = e->pkg->name; + } + gb_printf_err("Error in: %s\n", token_pos_to_string(ast_token(expr).pos)); + GB_PANIC("nullptr value for expression from identifier: %.*s.%.*s (%p) : %s @ %p", LIT(pkg), LIT(e->token.string), e, type_to_string(e->type), expr); + return {}; +} + +gb_internal cgValue cg_build_unary_and(cgProcedure *p, Ast *expr) { + ast_node(ue, UnaryExpr, expr); + auto tv = type_and_value_of_expr(expr); + + + Ast *ue_expr = unparen_expr(ue->expr); + if (ue_expr->kind == Ast_IndexExpr && tv.mode == Addressing_OptionalOkPtr && is_type_tuple(tv.type)) { + GB_PANIC("TODO(bill): &m[k]"); + // Type *tuple = tv.type; + + // Type *map_type = type_of_expr(ue_expr->IndexExpr.expr); + // Type *ot = base_type(map_type); + // Type *t = base_type(type_deref(ot)); + // bool deref = t != ot; + // GB_ASSERT(t->kind == Type_Map); + // ast_node(ie, IndexExpr, ue_expr); + + // lbValue map_val = lb_build_addr_ptr(p, ie->expr); + // if (deref) { + // map_val = lb_emit_load(p, map_val); + // } + + // lbValue key = lb_build_expr(p, ie->index); + // key = lb_emit_conv(p, key, t->Map.key); + + // lbAddr addr = lb_addr_map(map_val, key, t, alloc_type_pointer(t->Map.value)); + // lbValue ptr = lb_addr_get_ptr(p, addr); + + // lbValue ok = lb_emit_comp_against_nil(p, Token_NotEq, ptr); + // ok = lb_emit_conv(p, ok, tuple->Tuple.variables[1]->type); + + // lbAddr res = lb_add_local_generated(p, tuple, false); + // lbValue gep0 = lb_emit_struct_ep(p, res.addr, 0); + // lbValue gep1 = lb_emit_struct_ep(p, res.addr, 1); + // lb_emit_store(p, gep0, ptr); + // lb_emit_store(p, gep1, ok); + // return lb_addr_load(p, res); + + } else if (is_type_soa_pointer(tv.type)) { + GB_PANIC("TODO(bill): &soa[i]"); + // ast_node(ie, IndexExpr, ue_expr); + // lbValue addr = lb_build_addr_ptr(p, ie->expr); + // lbValue index = lb_build_expr(p, ie->index); + + // if (!build_context.no_bounds_check) { + // // TODO(bill): soa bounds checking + // } + + // return lb_make_soa_pointer(p, tv.type, addr, index); + } else if (ue_expr->kind == Ast_CompoundLit) { + cgValue v = cg_build_expr(p, ue->expr); + + Type *type = v.type; + cgAddr addr = {}; + // if (p->is_startup) { + // addr = cg_add_global_generated(p->module, type, v); + // } else { + addr = cg_add_local(p, type, nullptr, false); + // } + cg_addr_store(p, addr, v); + return addr.addr; + + } else if (ue_expr->kind == Ast_TypeAssertion) { + GB_PANIC("TODO(bill): &v.(T)"); + // if (is_type_tuple(tv.type)) { + // Type *tuple = tv.type; + // Type *ptr_type = tuple->Tuple.variables[0]->type; + // Type *ok_type = tuple->Tuple.variables[1]->type; + + // ast_node(ta, TypeAssertion, ue_expr); + // TokenPos pos = ast_token(expr).pos; + // Type *type = type_of_expr(ue_expr); + // GB_ASSERT(!is_type_tuple(type)); + + // lbValue e = lb_build_expr(p, ta->expr); + // Type *t = type_deref(e.type); + // if (is_type_union(t)) { + // lbValue v = e; + // if (!is_type_pointer(v.type)) { + // v = lb_address_from_load_or_generate_local(p, v); + // } + // Type *src_type = type_deref(v.type); + // Type *dst_type = type; + + // lbValue src_tag = {}; + // lbValue dst_tag = {}; + // if (is_type_union_maybe_pointer(src_type)) { + // src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v); + // dst_tag = lb_const_bool(p->module, t_bool, true); + // } else { + // src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v)); + // dst_tag = lb_const_union_tag(p->module, src_type, dst_type); + // } + + // lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag); + + // lbValue data_ptr = lb_emit_conv(p, v, ptr_type); + // lbAddr res = lb_add_local_generated(p, tuple, true); + // lbValue gep0 = lb_emit_struct_ep(p, res.addr, 0); + // lbValue gep1 = lb_emit_struct_ep(p, res.addr, 1); + // lb_emit_store(p, gep0, lb_emit_select(p, ok, data_ptr, lb_const_nil(p->module, ptr_type))); + // lb_emit_store(p, gep1, lb_emit_conv(p, ok, ok_type)); + // return lb_addr_load(p, res); + // } else if (is_type_any(t)) { + // lbValue v = e; + // if (is_type_pointer(v.type)) { + // v = lb_emit_load(p, v); + // } + + // lbValue data_ptr = lb_emit_conv(p, lb_emit_struct_ev(p, v, 0), ptr_type); + // lbValue any_id = lb_emit_struct_ev(p, v, 1); + // lbValue id = lb_typeid(p->module, type); + + // lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id); + + // lbAddr res = lb_add_local_generated(p, tuple, false); + // lbValue gep0 = lb_emit_struct_ep(p, res.addr, 0); + // lbValue gep1 = lb_emit_struct_ep(p, res.addr, 1); + // lb_emit_store(p, gep0, lb_emit_select(p, ok, data_ptr, lb_const_nil(p->module, ptr_type))); + // lb_emit_store(p, gep1, lb_emit_conv(p, ok, ok_type)); + // return lb_addr_load(p, res); + // } else { + // GB_PANIC("TODO(bill): type assertion %s", type_to_string(type)); + // } + + // } else { + // GB_ASSERT(is_type_pointer(tv.type)); + + // ast_node(ta, TypeAssertion, ue_expr); + // TokenPos pos = ast_token(expr).pos; + // Type *type = type_of_expr(ue_expr); + // GB_ASSERT(!is_type_tuple(type)); + + // lbValue e = lb_build_expr(p, ta->expr); + // Type *t = type_deref(e.type); + // if (is_type_union(t)) { + // lbValue v = e; + // if (!is_type_pointer(v.type)) { + // v = lb_address_from_load_or_generate_local(p, v); + // } + // Type *src_type = type_deref(v.type); + // Type *dst_type = type; + + + // if ((p->state_flags & StateFlag_no_type_assert) == 0) { + // lbValue src_tag = {}; + // lbValue dst_tag = {}; + // if (is_type_union_maybe_pointer(src_type)) { + // src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v); + // dst_tag = lb_const_bool(p->module, t_bool, true); + // } else { + // src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v)); + // dst_tag = lb_const_union_tag(p->module, src_type, dst_type); + // } + + + // isize arg_count = 6; + // if (build_context.no_rtti) { + // arg_count = 4; + // } + + // lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag); + // auto args = array_make<lbValue>(permanent_allocator(), arg_count); + // args[0] = ok; + + // args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)); + // args[2] = lb_const_int(p->module, t_i32, pos.line); + // args[3] = lb_const_int(p->module, t_i32, pos.column); + + // if (!build_context.no_rtti) { + // args[4] = lb_typeid(p->module, src_type); + // args[5] = lb_typeid(p->module, dst_type); + // } + // lb_emit_runtime_call(p, "type_assertion_check", args); + // } + + // lbValue data_ptr = v; + // return lb_emit_conv(p, data_ptr, tv.type); + // } else if (is_type_any(t)) { + // lbValue v = e; + // if (is_type_pointer(v.type)) { + // v = lb_emit_load(p, v); + // } + // lbValue data_ptr = lb_emit_struct_ev(p, v, 0); + // if ((p->state_flags & StateFlag_no_type_assert) == 0) { + // GB_ASSERT(!build_context.no_rtti); + + // lbValue any_id = lb_emit_struct_ev(p, v, 1); + + // lbValue id = lb_typeid(p->module, type); + // lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id); + // auto args = array_make<lbValue>(permanent_allocator(), 6); + // args[0] = ok; + + // args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)); + // args[2] = lb_const_int(p->module, t_i32, pos.line); + // args[3] = lb_const_int(p->module, t_i32, pos.column); + + // args[4] = any_id; + // args[5] = id; + // lb_emit_runtime_call(p, "type_assertion_check", args); + // } + + // return lb_emit_conv(p, data_ptr, tv.type); + // } else { + // GB_PANIC("TODO(bill): type assertion %s", type_to_string(type)); + // } + // } + } + + return cg_build_addr_ptr(p, ue->expr); +} + gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { expr = unparen_expr(expr); @@ -2016,9 +2265,7 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { if (addr) { return cg_addr_load(p, *addr); } - // return cg_find_ident(p, m, e, expr); - GB_PANIC("TODO: cg_find_ident"); - return {}; + return cg_find_ident(p, e, expr); case_end; case_ast_node(i, Implicit, expr); @@ -2151,8 +2398,7 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { case_ast_node(ue, UnaryExpr, expr); if (ue->op.kind == Token_And) { - GB_PANIC("TODO(bill): cg_build_unary_and"); - // return cg_build_unary_and(p, expr); + return cg_build_unary_and(p, expr); } cgValue v = cg_build_expr(p, ue->expr); return cg_emit_unary_arith(p, ue->op.kind, v, type); @@ -2166,6 +2412,10 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { } +gb_internal cgValue cg_build_addr_ptr(cgProcedure *p, Ast *expr) { + cgAddr addr = cg_build_addr(p, expr); + return cg_addr_get_ptr(p, addr); +} gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr); gb_internal cgAddr cg_build_addr(cgProcedure *p, Ast *expr) { @@ -2193,6 +2443,225 @@ gb_internal cgAddr cg_build_addr(cgProcedure *p, Ast *expr) { return addr; } +gb_internal cgAddr cg_build_addr_index_expr(cgProcedure *p, Ast *expr) { + ast_node(ie, IndexExpr, expr); + + Type *t = base_type(type_of_expr(ie->expr)); + + bool deref = is_type_pointer(t); + t = base_type(type_deref(t)); + if (is_type_soa_struct(t)) { + GB_PANIC("TODO(bill): #soa"); + // // SOA STRUCTURES!!!! + // lbValue val = cg_build_addr_ptr(p, ie->expr); + // if (deref) { + // val = cg_emit_load(p, val); + // } + + // cgValue index = cg_build_expr(p, ie->index); + // return cg_addr_soa_variable(val, index, ie->index); + } + + if (ie->expr->tav.mode == Addressing_SoaVariable) { + GB_PANIC("TODO(bill): #soa"); + // // SOA Structures for slices/dynamic arrays + // GB_ASSERT(is_type_pointer(type_of_expr(ie->expr))); + + // lbValue field = lb_build_expr(p, ie->expr); + // lbValue index = lb_build_expr(p, ie->index); + + + // if (!build_context.no_bounds_check) { + // // TODO HACK(bill): Clean up this hack to get the length for bounds checking + // // GB_ASSERT(LLVMIsALoadInst(field.value)); + + // // lbValue a = {}; + // // a.value = LLVMGetOperand(field.value, 0); + // // a.type = alloc_type_pointer(field.type); + + // // irInstr *b = &a->Instr; + // // GB_ASSERT(b->kind == irInstr_StructElementPtr); + // // lbValue base_struct = b->StructElementPtr.address; + + // // GB_ASSERT(is_type_soa_struct(type_deref(ir_type(base_struct)))); + // // lbValue len = ir_soa_struct_len(p, base_struct); + // // lb_emit_bounds_check(p, ast_token(ie->index), index, len); + // } + // lbValue val = lb_emit_ptr_offset(p, field, index); + // return lb_addr(val); + } + + GB_ASSERT_MSG(is_type_indexable(t), "%s %s", type_to_string(t), expr_to_string(expr)); + + if (is_type_map(t)) { + GB_PANIC("TODO(bill): map indexing"); + // lbAddr map_addr = lb_build_addr(p, ie->expr); + // lbValue key = lb_build_expr(p, ie->index); + // key = lb_emit_conv(p, key, t->Map.key); + + // Type *result_type = type_of_expr(expr); + // lbValue map_ptr = lb_addr_get_ptr(p, map_addr); + // if (is_type_pointer(type_deref(map_ptr.type))) { + // map_ptr = lb_emit_load(p, map_ptr); + // } + // return lb_addr_map(map_ptr, key, t, result_type); + } + + switch (t->kind) { + case Type_Array: { + cgValue array = {}; + array = cg_build_addr_ptr(p, ie->expr); + if (deref) { + array = cg_emit_load(p, array); + } + cgValue index = cg_build_expr(p, ie->index); + index = cg_emit_conv(p, index, t_int); + cgValue elem = cg_emit_array_ep(p, array, index); + + auto index_tv = type_and_value_of_expr(ie->index); + if (index_tv.mode != Addressing_Constant) { + // cgValue len = cg_const_int(p->module, t_int, t->Array.count); + // cg_emit_bounds_check(p, ast_token(ie->index), index, len); + } + return cg_addr(elem); + } + + case Type_EnumeratedArray: { + cgValue array = {}; + array = cg_build_addr_ptr(p, ie->expr); + if (deref) { + array = cg_emit_load(p, array); + } + + Type *index_type = t->EnumeratedArray.index; + + auto index_tv = type_and_value_of_expr(ie->index); + + cgValue index = {}; + if (compare_exact_values(Token_NotEq, *t->EnumeratedArray.min_value, exact_value_i64(0))) { + if (index_tv.mode == Addressing_Constant) { + ExactValue idx = exact_value_sub(index_tv.value, *t->EnumeratedArray.min_value); + index = cg_const_value(p, index_type, idx); + } else { + index = cg_emit_arith(p, Token_Sub, + cg_build_expr(p, ie->index), + cg_const_value(p, index_type, *t->EnumeratedArray.min_value), + index_type); + index = cg_emit_conv(p, index, t_int); + } + } else { + index = cg_emit_conv(p, cg_build_expr(p, ie->index), t_int); + } + + cgValue elem = cg_emit_array_ep(p, array, index); + + if (index_tv.mode != Addressing_Constant) { + // cgValue len = cg_const_int(p->module, t_int, t->EnumeratedArray.count); + // cg_emit_bounds_check(p, ast_token(ie->index), index, len); + } + return cg_addr(elem); + } + + case Type_Slice: { + cgValue slice = {}; + slice = cg_build_expr(p, ie->expr); + if (deref) { + slice = cg_emit_load(p, slice); + } + cgValue elem = cg_builtin_raw_data(p, slice); + cgValue index = cg_emit_conv(p, cg_build_expr(p, ie->index), t_int); + // cgValue len = cg_builtin_len(p, slice); + // cg_emit_bounds_check(p, ast_token(ie->index), index, len); + cgValue v = cg_emit_ptr_offset(p, elem, index); + return cg_addr(v); + } + + case Type_MultiPointer: { + cgValue multi_ptr = {}; + multi_ptr = cg_build_expr(p, ie->expr); + if (deref) { + multi_ptr = cg_emit_load(p, multi_ptr); + } + cgValue index = cg_build_expr(p, ie->index); + index = cg_emit_conv(p, index, t_int); + + return cg_addr(cg_emit_ptr_offset(p, multi_ptr, index)); + } + + case Type_RelativeSlice: { + GB_PANIC("TODO(bill): relative slice"); + // lbAddr slice_addr = {}; + // if (deref) { + // slice_addr = lb_addr(lb_build_expr(p, ie->expr)); + // } else { + // slice_addr = lb_build_addr(p, ie->expr); + // } + // lbValue slice = lb_addr_load(p, slice_addr); + + // lbValue elem = lb_slice_elem(p, slice); + // lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int); + // lbValue len = lb_slice_len(p, slice); + // lb_emit_bounds_check(p, ast_token(ie->index), index, len); + // lbValue v = lb_emit_ptr_offset(p, elem, index); + // return lb_addr(v); + } + + case Type_DynamicArray: { + cgValue dynamic_array = {}; + dynamic_array = cg_build_expr(p, ie->expr); + if (deref) { + dynamic_array = cg_emit_load(p, dynamic_array); + } + cgValue elem = cg_builtin_raw_data(p, dynamic_array); + cgValue index = cg_emit_conv(p, cg_build_expr(p, ie->index), t_int); + // cgValue len = cg_dynamic_array_len(p, dynamic_array); + // cg_emit_bounds_check(p, ast_token(ie->index), index, len); + cgValue v = cg_emit_ptr_offset(p, elem, index); + return cg_addr(v); + } + + case Type_Matrix: { + GB_PANIC("TODO(bill): matrix"); + // lbValue matrix = {}; + // matrix = lb_build_addr_ptr(p, ie->expr); + // if (deref) { + // matrix = lb_emit_load(p, matrix); + // } + // lbValue index = lb_build_expr(p, ie->index); + // index = lb_emit_conv(p, index, t_int); + // lbValue elem = lb_emit_matrix_ep(p, matrix, lb_const_int(p->module, t_int, 0), index); + // elem = lb_emit_conv(p, elem, alloc_type_pointer(type_of_expr(expr))); + + // auto index_tv = type_and_value_of_expr(ie->index); + // if (index_tv.mode != Addressing_Constant) { + // lbValue len = lb_const_int(p->module, t_int, t->Matrix.column_count); + // lb_emit_bounds_check(p, ast_token(ie->index), index, len); + // } + // return lb_addr(elem); + } + + + case Type_Basic: { // Basic_string + cgValue str; + cgValue elem; + cgValue len; + cgValue index; + + str = cg_build_expr(p, ie->expr); + if (deref) { + str = cg_emit_load(p, str); + } + elem = cg_builtin_raw_data(p, str); + len = cg_builtin_len(p, str); + + index = cg_emit_conv(p, cg_build_expr(p, ie->index), t_int); + // cg_emit_bounds_check(p, ast_token(ie->index), index, len); + + return cg_addr(cg_emit_ptr_offset(p, elem, index)); + } + } + return {}; +} gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr) { switch (expr->kind) { @@ -2218,6 +2687,10 @@ gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr) { return cg_build_addr_from_entity(p, e, expr); case_end; + case_ast_node(ie, IndexExpr, expr); + return cg_build_addr_index_expr(p, expr); + case_end; + case_ast_node(se, SliceExpr, expr); return cg_build_addr_slice_expr(p, expr); case_end; @@ -2350,6 +2823,5 @@ gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr) { LIT(ast_strings[expr->kind]), token_pos_to_string(token_pos)); - return {}; }
\ No newline at end of file |