|
@@ -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_u8_ptr = alloc_type_pointer(t_u8);
|
|
t_int_ptr = alloc_type_pointer(t_int);
|
|
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);
|
|
add_type_info_type(c, bt->Proc.results);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case Type_SimdVector:
|
|
|
|
+ add_type_info_type(c, bt->SimdVector.elem);
|
|
|
|
+ break;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind);
|
|
GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind);
|
|
break;
|
|
break;
|
|
@@ -1419,6 +1470,10 @@ void add_min_dep_type_info(Checker *c, Type *t) {
|
|
add_min_dep_type_info(c, bt->Proc.results);
|
|
add_min_dep_type_info(c, bt->Proc.results);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case Type_SimdVector:
|
|
|
|
+ add_min_dep_type_info(c, bt->SimdVector.elem);
|
|
|
|
+ break;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind]));
|
|
GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind]));
|
|
break;
|
|
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_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_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_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_named_ptr = alloc_type_pointer(t_type_info_named);
|
|
t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer);
|
|
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_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_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_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) {
|
|
void init_mem_allocator(Checker *c) {
|
|
@@ -1933,7 +1990,18 @@ DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) {
|
|
}
|
|
}
|
|
|
|
|
|
DECL_ATTRIBUTE_PROC(proc_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) {
|
|
if (value != nullptr) {
|
|
Operand o = {};
|
|
Operand o = {};
|
|
check_expr(c, &o, value);
|
|
check_expr(c, &o, value);
|
|
@@ -2040,12 +2108,33 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
|
DECL_ATTRIBUTE_PROC(var_decl_attribute) {
|
|
DECL_ATTRIBUTE_PROC(var_decl_attribute) {
|
|
ExactValue ev = check_decl_attribute_value(c, value);
|
|
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) {
|
|
if (c->curr_proc_decl != nullptr) {
|
|
error(elem, "Only a variable at file scope can have a '%.*s'", LIT(name));
|
|
error(elem, "Only a variable at file scope can have a '%.*s'", LIT(name));
|
|
return true;
|
|
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) {
|
|
if (ev.kind == ExactValue_String) {
|
|
ac->link_name = ev.value_string;
|
|
ac->link_name = ev.value_string;
|
|
if (!is_foreign_name_valid(ac->link_name)) {
|
|
if (!is_foreign_name_valid(ac->link_name)) {
|
|
@@ -2068,8 +2157,10 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) {
|
|
} else if (name == "thread_local") {
|
|
} else if (name == "thread_local") {
|
|
if (ac->init_expr_list_count > 0) {
|
|
if (ac->init_expr_list_count > 0) {
|
|
error(elem, "A thread local variable declaration cannot have initialization values");
|
|
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");
|
|
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) {
|
|
} else if (ev.kind == ExactValue_Invalid) {
|
|
ac->thread_local_model = str_lit("default");
|
|
ac->thread_local_model = str_lit("default");
|
|
} else if (ev.kind == ExactValue_String) {
|
|
} 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);
|
|
case_ast_node(i, Ident, elem);
|
|
name = i->token.string;
|
|
name = i->token.string;
|
|
case_end;
|
|
case_end;
|
|
|
|
+ case_ast_node(i, Implicit, elem);
|
|
|
|
+ name = i->string;
|
|
|
|
+ case_end;
|
|
case_ast_node(fv, FieldValue, elem);
|
|
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;
|
|
value = fv->value;
|
|
case_end;
|
|
case_end;
|
|
default:
|
|
default:
|
|
@@ -2372,10 +2471,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|
e->flags |= EntityFlag_NotExported;
|
|
e->flags |= EntityFlag_NotExported;
|
|
}
|
|
}
|
|
|
|
|
|
- if (vd->is_static) {
|
|
|
|
- e->flags |= EntityFlag_Static;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (vd->is_using) {
|
|
if (vd->is_using) {
|
|
vd->is_using = false; // NOTE(bill): This error will be only caught once
|
|
vd->is_using = false; // NOTE(bill): This error will be only caught once
|
|
error(name, "'using' is not allowed at the file scope");
|
|
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.foreign_library_ident = fl;
|
|
|
|
|
|
e->Variable.link_prefix = c->foreign_context.link_prefix;
|
|
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;
|
|
Ast *init_expr = value;
|
|
@@ -2456,9 +2548,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|
|
|
|
|
GB_ASSERT(cc != ProcCC_Invalid);
|
|
GB_ASSERT(cc != ProcCC_Invalid);
|
|
pl->type->ProcType.calling_convention = cc;
|
|
pl->type->ProcType.calling_convention = cc;
|
|
-
|
|
|
|
- } else if (c->foreign_context.in_export) {
|
|
|
|
- e->Procedure.is_export = true;
|
|
|
|
}
|
|
}
|
|
d->proc_lit = init;
|
|
d->proc_lit = init;
|
|
d->type_expr = pl->type;
|
|
d->type_expr = pl->type;
|
|
@@ -2480,14 +2569,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|
e->flags |= EntityFlag_NotExported;
|
|
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 (vd->is_using) {
|
|
if (e->kind == Entity_TypeName && init->kind == Ast_EnumType) {
|
|
if (e->kind == Entity_TypeName && init->kind == Ast_EnumType) {
|
|
d->is_using = true;
|
|
d->is_using = true;
|
|
@@ -2497,7 +2578,7 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|
}
|
|
}
|
|
|
|
|
|
if (e->kind != Entity_Procedure) {
|
|
if (e->kind != Entity_Procedure) {
|
|
- if (fl != nullptr || c->foreign_context.in_export) {
|
|
|
|
|
|
+ if (fl != nullptr) {
|
|
AstKind kind = init->kind;
|
|
AstKind kind = init->kind;
|
|
error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_strings[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) {
|
|
if (kind == Ast_ProcType) {
|
|
@@ -2525,8 +2606,6 @@ void check_add_foreign_block_decl(CheckerContext *ctx, Ast *decl) {
|
|
CheckerContext c = *ctx;
|
|
CheckerContext c = *ctx;
|
|
if (foreign_library->kind == Ast_Ident) {
|
|
if (foreign_library->kind == Ast_Ident) {
|
|
c.foreign_context.curr_library = foreign_library;
|
|
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 {
|
|
} else {
|
|
error(foreign_library, "Foreign block name must be an identifier or 'export'");
|
|
error(foreign_library, "Foreign block name must be an identifier or 'export'");
|
|
c.foreign_context.curr_library = nullptr;
|
|
c.foreign_context.curr_library = nullptr;
|