From ee3b3fe6a3424d84cda26b1cddc764694ac49e7a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 10 Nov 2020 14:48:57 +0000 Subject: [PATCH] Fix `typeid_of` bug --- src/check_expr.cpp | 26 +++++++++++++++++++++----- src/llvm_backend.cpp | 30 ++++++++++++------------------ src/llvm_backend.hpp | 2 +- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 01e971ac7..a8e7550a1 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4343,7 +4343,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 add_type_info_type(c, t); - t = base_type(t); if (o.mode != Addressing_Type) { error(expr, "Expected a type for 'typeid_of'"); return false; @@ -4351,6 +4350,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->mode = Addressing_Value; operand->type = t_typeid; + operand->value = exact_value_typeid(t); break; } @@ -7843,7 +7843,7 @@ void check_expr_with_type_hint(CheckerContext *c, Operand *o, Ast *e, Type *t) { err_str = "used as a value"; break; case Addressing_Type: - err_str = "is not an expression but a"; + err_str = "is not an expression but a type"; break; case Addressing_Builtin: err_str = "must be called"; @@ -9108,6 +9108,9 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type } is_constant = false; { // Checker values + bool key_is_typeid = is_type_typeid(t->Map.key); + bool value_is_typeid = is_type_typeid(t->Map.value); + for_array(i, cl->elems) { Ast *elem = cl->elems[i]; if (elem->kind != Ast_FieldValue) { @@ -9115,13 +9118,22 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type continue; } ast_node(fv, FieldValue, elem); - check_expr_with_type_hint(c, o, fv->field, t->Map.key); + + if (key_is_typeid) { + check_expr_or_type(c, o, fv->field, t->Map.key); + } else { + check_expr_with_type_hint(c, o, fv->field, t->Map.key); + } check_assignment(c, o, t->Map.key, str_lit("map literal")); if (o->mode == Addressing_Invalid) { continue; } - check_expr_with_type_hint(c, o, fv->value, t->Map.value); + if (value_is_typeid) { + check_expr_or_type(c, o, fv->value, t->Map.value); + } else { + check_expr_with_type_hint(c, o, fv->value, t->Map.value); + } check_assignment(c, o, t->Map.value, str_lit("map literal")); } } @@ -9677,7 +9689,11 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type if (is_type_map(t)) { Operand key = {}; - check_expr_with_type_hint(c, &key, ie->index, t->Map.key); + if (is_type_typeid(t->Map.key)) { + check_expr_or_type(c, &key, ie->index, t->Map.key); + } else { + check_expr_with_type_hint(c, &key, ie->index, t->Map.key); + } check_assignment(c, &key, t->Map.key, str_lit("map index")); if (key.mode == Addressing_Invalid) { o->mode = Addressing_Invalid; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index c6fee8ab8..aab2248d9 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -4635,7 +4635,7 @@ isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=tr return -1; } -lbValue lb_typeid(lbModule *m, Type *type, Type *typeid_type) { +lbValue lb_typeid(lbModule *m, Type *type) { type = default_type(type); u64 id = cast(u64)lb_type_info_index(m->info, type); @@ -4687,6 +4687,7 @@ lbValue lb_typeid(lbModule *m, Type *type, Type *typeid_type) { u64 data = 0; if (build_context.word_size == 4) { + GB_ASSERT(id <= (1u<<24u)); data |= (id &~ (1u<<24)) << 0u; // index data |= (kind &~ (1u<<5)) << 24u; // kind data |= (named &~ (1u<<1)) << 29u; // kind @@ -4694,6 +4695,7 @@ lbValue lb_typeid(lbModule *m, Type *type, Type *typeid_type) { data |= (reserved &~ (1u<<1)) << 31u; // kind } else { GB_ASSERT(build_context.word_size == 8); + GB_ASSERT(id <= (1ull<<56u)); data |= (id &~ (1ull<<56)) << 0ul; // index data |= (kind &~ (1ull<<5)) << 56ull; // kind data |= (named &~ (1ull<<1)) << 61ull; // kind @@ -4701,10 +4703,9 @@ lbValue lb_typeid(lbModule *m, Type *type, Type *typeid_type) { data |= (reserved &~ (1ull<<1)) << 63ull; // kind } - lbValue res = {}; - res.value = LLVMConstInt(lb_type(m, typeid_type), data, false); - res.type = typeid_type; + res.value = LLVMConstInt(lb_type(m, t_typeid), data, false); + res.type = t_typeid; return res; } @@ -4739,7 +4740,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc value = convert_exact_value_for_type(value, type); if (value.kind == ExactValue_Typeid) { - return lb_typeid(m, value.value_typeid, original_type); + return lb_typeid(m, value.value_typeid); } if (value.kind == ExactValue_Invalid) { @@ -5294,7 +5295,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc } break; case ExactValue_Typeid: - return lb_typeid(m, value.value_typeid, original_type); + return lb_typeid(m, value.value_typeid); } return lb_const_nil(m, original_type); @@ -5804,10 +5805,10 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { lbValue right = {}; if (be->left->tav.mode == Addressing_Type) { - left = lb_typeid(p->module, be->left->tav.type, t_typeid); + left = lb_typeid(p->module, be->left->tav.type); } if (be->right->tav.mode == Addressing_Type) { - right = lb_typeid(p->module, be->right->tav.type, t_typeid); + right = lb_typeid(p->module, be->right->tav.type); } if (left.value == nullptr) left = lb_build_expr(p, be->left); if (right.value == nullptr) right = lb_build_expr(p, be->right); @@ -7467,16 +7468,9 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, case BuiltinProc_typeid_of: { Ast *arg = ce->args[0]; TypeAndValue tav = type_and_value_of_expr(arg); - if (tav.mode == Addressing_Type) { - Type *t = default_type(type_of_expr(arg)); - return lb_typeid(p->module, t); - } - Type *t = base_type(tav.type); - GB_ASSERT(are_types_identical(t, t_type_info_ptr)); - - auto args = array_make(heap_allocator(), 1); - args[0] = lb_emit_conv(p, lb_build_expr(p, arg), t_type_info_ptr); - return lb_emit_runtime_call(p, "__typeid_of", args); + GB_ASSERT(tav.mode == Addressing_Type); + Type *t = default_type(type_of_expr(arg)); + return lb_typeid(p->module, t); } case BuiltinProc_len: { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 23b2c7654..4a0816e62 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -301,7 +301,7 @@ lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e=nullptr, bool zero_ini void lb_add_foreign_library_path(lbModule *m, Entity *e); -lbValue lb_typeid(lbModule *m, Type *type, Type *typeid_type=t_typeid); +lbValue lb_typeid(lbModule *m, Type *type); lbValue lb_address_from_load_or_generate_local(lbProcedure *p, lbValue value); lbValue lb_address_from_load(lbProcedure *p, lbValue value);