diff options
Diffstat (limited to 'src/checker.cpp')
| -rw-r--r-- | src/checker.cpp | 131 |
1 files changed, 105 insertions, 26 deletions
diff --git a/src/checker.cpp b/src/checker.cpp index 9cac82911..0253bc86b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -712,6 +712,53 @@ void init_universal(void) { } } + // TODO(bill): Set the correct arch for this + if (bc->metrics.arch == TargetArch_amd64 || bc->metrics.arch == TargetArch_386) { + t_vector_x86_mmx = alloc_type(Type_SimdVector); + t_vector_x86_mmx->SimdVector.is_x86_mmx = true; + + Entity *entity = alloc_entity(Entity_TypeName, nullptr, make_token_ident(str_lit("x86_mmx")), t_vector_x86_mmx); + add_global_entity(entity, intrinsics_pkg->scope); + } + + bool defined_values_double_declaration = false; + for_array(i, bc->defined_values.entries) { + String name = bc->defined_values.entries[i].key.string; + ExactValue value = bc->defined_values.entries[i].value; + GB_ASSERT(value.kind != ExactValue_Invalid); + + Type *type = nullptr; + switch (value.kind) { + case ExactValue_Bool: + type = t_untyped_bool; + break; + case ExactValue_String: + type = t_untyped_string; + break; + case ExactValue_Integer: + type = t_untyped_integer; + break; + case ExactValue_Float: + type = t_untyped_float; + break; + } + GB_ASSERT(type != nullptr); + + + + Entity *entity = alloc_entity_constant(nullptr, make_token_ident(name), type, value); + entity->state = EntityState_Resolved; + if (scope_insert(builtin_pkg->scope, entity)) { + error(entity->token, "'%.*s' defined as an argument is already declared at the global scope", LIT(name)); + defined_values_double_declaration = true; + // NOTE(bill): Just exit early before anything, even though the compiler will do that anyway + } + } + + if (defined_values_double_declaration) { + gb_exit(1); + } + t_u8_ptr = alloc_type_pointer(t_u8); t_int_ptr = alloc_type_pointer(t_int); @@ -1248,6 +1295,10 @@ void add_type_info_type(CheckerContext *c, Type *t) { add_type_info_type(c, bt->Proc.results); break; + case Type_SimdVector: + add_type_info_type(c, bt->SimdVector.elem); + break; + default: GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind); break; @@ -1419,6 +1470,10 @@ void add_min_dep_type_info(Checker *c, Type *t) { add_min_dep_type_info(c, bt->Proc.results); break; + case Type_SimdVector: + add_min_dep_type_info(c, bt->SimdVector.elem); + break; + default: GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind])); break; @@ -1795,6 +1850,7 @@ void init_core_type_info(Checker *c) { t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field")); t_type_info_bit_set = find_core_type(c, str_lit("Type_Info_Bit_Set")); t_type_info_opaque = find_core_type(c, str_lit("Type_Info_Opaque")); + t_type_info_simd_vector = find_core_type(c, str_lit("Type_Info_Simd_Vector")); t_type_info_named_ptr = alloc_type_pointer(t_type_info_named); t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer); @@ -1818,6 +1874,7 @@ void init_core_type_info(Checker *c) { t_type_info_bit_field_ptr = alloc_type_pointer(t_type_info_bit_field); t_type_info_bit_set_ptr = alloc_type_pointer(t_type_info_bit_set); t_type_info_opaque_ptr = alloc_type_pointer(t_type_info_opaque); + t_type_info_simd_vector_ptr = alloc_type_pointer(t_type_info_simd_vector); } void init_mem_allocator(Checker *c) { @@ -1933,7 +1990,18 @@ DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) { } DECL_ATTRIBUTE_PROC(proc_decl_attribute) { - if (name == "deferred") { + if (name == "export") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_Invalid) { + ac->is_export = true; + } else if (ev.kind == ExactValue_Bool) { + ac->is_export = ev.value_bool; + } else { + error(value, "Expected either a boolean or no parameter for 'export'"); + return false; + } + return true; + } else if (name == "deferred") { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); @@ -2040,12 +2108,33 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { DECL_ATTRIBUTE_PROC(var_decl_attribute) { ExactValue ev = check_decl_attribute_value(c, value); + if (name == "static") { + if (value != nullptr) { + error(elem, "'static' does not have any parameters"); + } + ac->is_static = true; + return true; + } + if (c->curr_proc_decl != nullptr) { error(elem, "Only a variable at file scope can have a '%.*s'", LIT(name)); return true; } - if (name == "link_name") { + if (name == "export") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_Invalid) { + ac->is_export = true; + } else if (ev.kind == ExactValue_Bool) { + ac->is_export = ev.value_bool; + } else { + error(value, "Expected either a boolean or no parameter for 'export'"); + return false; + } + if (ac->thread_local_model != "") { + error(elem, "An exported variable cannot be thread local"); + } + } else if (name == "link_name") { if (ev.kind == ExactValue_String) { ac->link_name = ev.value_string; if (!is_foreign_name_valid(ac->link_name)) { @@ -2068,8 +2157,10 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) { } else if (name == "thread_local") { if (ac->init_expr_list_count > 0) { error(elem, "A thread local variable declaration cannot have initialization values"); - } else if (c->foreign_context.curr_library || c->foreign_context.in_export) { + } else if (c->foreign_context.curr_library) { error(elem, "A foreign block variable cannot be thread local"); + } else if (ac->is_export) { + error(elem, "An exported variable cannot be thread local"); } else if (ev.kind == ExactValue_Invalid) { ac->thread_local_model = str_lit("default"); } else if (ev.kind == ExactValue_String) { @@ -2132,9 +2223,17 @@ void check_decl_attributes(CheckerContext *c, Array<Ast *> const &attributes, De case_ast_node(i, Ident, elem); name = i->token.string; case_end; + case_ast_node(i, Implicit, elem); + name = i->string; + case_end; case_ast_node(fv, FieldValue, elem); - GB_ASSERT(fv->field->kind == Ast_Ident); - name = fv->field->Ident.token.string; + if (fv->field->kind == Ast_Ident) { + name = fv->field->Ident.token.string; + } else if (fv->field->kind == Ast_Implicit) { + name = fv->field->Implicit.string; + } else { + GB_PANIC("Unknown Field Value name"); + } value = fv->value; case_end; default: @@ -2372,10 +2471,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { e->flags |= EntityFlag_NotExported; } - if (vd->is_static) { - e->flags |= EntityFlag_Static; - } - if (vd->is_using) { vd->is_using = false; // NOTE(bill): This error will be only caught once error(name, "'using' is not allowed at the file scope"); @@ -2388,9 +2483,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { e->Variable.foreign_library_ident = fl; e->Variable.link_prefix = c->foreign_context.link_prefix; - - } else if (c->foreign_context.in_export) { - e->Variable.is_export = true; } Ast *init_expr = value; @@ -2456,9 +2548,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { GB_ASSERT(cc != ProcCC_Invalid); pl->type->ProcType.calling_convention = cc; - - } else if (c->foreign_context.in_export) { - e->Procedure.is_export = true; } d->proc_lit = init; d->type_expr = pl->type; @@ -2480,14 +2569,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { e->flags |= EntityFlag_NotExported; } - if (vd->is_static) { - if (e->kind == Entity_Constant) { - e->flags |= EntityFlag_Static; - } else { - error(name, "'static' is not allowed on this constant value declaration"); - } - } - if (vd->is_using) { if (e->kind == Entity_TypeName && init->kind == Ast_EnumType) { d->is_using = true; @@ -2497,7 +2578,7 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { } if (e->kind != Entity_Procedure) { - if (fl != nullptr || c->foreign_context.in_export) { + if (fl != nullptr) { AstKind kind = init->kind; error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_strings[kind])); if (kind == Ast_ProcType) { @@ -2525,8 +2606,6 @@ void check_add_foreign_block_decl(CheckerContext *ctx, Ast *decl) { CheckerContext c = *ctx; if (foreign_library->kind == Ast_Ident) { c.foreign_context.curr_library = foreign_library; - } else if (foreign_library->kind == Ast_Implicit && foreign_library->Implicit.kind == Token_export) { - c.foreign_context.in_export = true; } else { error(foreign_library, "Foreign block name must be an identifier or 'export'"); c.foreign_context.curr_library = nullptr; |