aboutsummaryrefslogtreecommitdiff
path: root/src/check_decl.cpp
diff options
context:
space:
mode:
authorFourteenBrush <naessensarthur2@protonmail.com>2024-01-25 10:15:25 +0100
committerFourteenBrush <naessensarthur2@protonmail.com>2024-01-25 10:15:25 +0100
commit967ccfc7ccc0f76c653ff4bb625bac60e89a7904 (patch)
treef989a0f99337c7a0c93ee84249d73ec0c33e306d /src/check_decl.cpp
parent712ae1c5ac73493498aa8e5076d91a6558337117 (diff)
parent9cfd4a953e2a7d19237891993b643b2d1477f8b3 (diff)
Merge branch 'master' of https://github.com/FourteenBrush/Odin
Diffstat (limited to 'src/check_decl.cpp')
-rw-r--r--src/check_decl.cpp91
1 files changed, 87 insertions, 4 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index 71b897a84..ed3a109c2 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -138,11 +138,10 @@ gb_internal void check_init_variables(CheckerContext *ctx, Entity **lhs, isize l
}
if (o->type && is_type_no_copy(o->type)) {
- begin_error_block();
+ ERROR_BLOCK();
if (check_no_copy_assignment(*o, str_lit("initialization"))) {
error_line("\tInitialization of a #no_copy type must be either implicitly zero, a constant literal, or a return value from a call expression");
}
- end_error_block();
}
}
if (rhs_count > 0 && lhs_count != rhs_count) {
@@ -908,7 +907,91 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
break;
}
+ e->Procedure.entry_point_only = ac.entry_point_only;
e->Procedure.is_export = ac.is_export;
+
+ bool has_instrumentation = false;
+ if (pl->body == nullptr) {
+ has_instrumentation = false;
+ if (ac.no_instrumentation != Instrumentation_Default) {
+ error(e->token, "@(no_instrumentation) is not allowed on foreign procedures");
+ }
+ } else {
+ AstFile *file = e->token.pos.file_id ? global_files[e->token.pos.file_id] : nullptr;
+ if (file) {
+ has_instrumentation = (file->flags & AstFile_NoInstrumentation) == 0;
+ }
+
+ switch (ac.no_instrumentation) {
+ case Instrumentation_Enabled: has_instrumentation = true; break;
+ case Instrumentation_Default: break;
+ case Instrumentation_Disabled: has_instrumentation = false; break;
+ }
+ }
+
+ auto const is_valid_instrumentation_call = [](Type *type) -> bool {
+ if (type == nullptr || type->kind != Type_Proc) {
+ return false;
+ }
+ if (type->Proc.calling_convention != ProcCC_Contextless) {
+ return false;
+ }
+ if (type->Proc.result_count != 0) {
+ return false;
+ }
+ if (type->Proc.param_count != 3) {
+ return false;
+ }
+ Type *p0 = type->Proc.params->Tuple.variables[0]->type;
+ Type *p1 = type->Proc.params->Tuple.variables[1]->type;
+ Type *p3 = type->Proc.params->Tuple.variables[2]->type;
+ return is_type_rawptr(p0) && is_type_rawptr(p1) && are_types_identical(p3, t_source_code_location);
+ };
+
+ static char const *instrumentation_proc_type_str = "proc \"contextless\" (proc_address: rawptr, call_site_return_address: rawptr, loc: runtime.Source_Code_Location)";
+
+ if (ac.instrumentation_enter && ac.instrumentation_exit) {
+ error(e->token, "A procedure cannot be marked with both @(instrumentation_enter) and @(instrumentation_exit)");
+
+ has_instrumentation = false;
+ e->flags |= EntityFlag_Require;
+ } else if (ac.instrumentation_enter) {
+ if (!is_valid_instrumentation_call(e->type)) {
+ init_core_source_code_location(ctx->checker);
+ gbString s = type_to_string(e->type);
+ error(e->token, "@(instrumentation_enter) procedures must have the type '%s', got %s", instrumentation_proc_type_str, s);
+ gb_string_free(s);
+ }
+ MUTEX_GUARD(&ctx->info->instrumentation_mutex);
+ if (ctx->info->instrumentation_enter_entity != nullptr) {
+ error(e->token, "@(instrumentation_enter) has already been set");
+ } else {
+ ctx->info->instrumentation_enter_entity = e;
+ }
+
+ has_instrumentation = false;
+ e->flags |= EntityFlag_Require;
+ } else if (ac.instrumentation_exit) {
+ init_core_source_code_location(ctx->checker);
+ if (!is_valid_instrumentation_call(e->type)) {
+ gbString s = type_to_string(e->type);
+ error(e->token, "@(instrumentation_exit) procedures must have the type '%s', got %s", instrumentation_proc_type_str, s);
+ gb_string_free(s);
+ }
+ MUTEX_GUARD(&ctx->info->instrumentation_mutex);
+ if (ctx->info->instrumentation_exit_entity != nullptr) {
+ error(e->token, "@(instrumentation_exit) has already been set");
+ } else {
+ ctx->info->instrumentation_exit_entity = e;
+ }
+
+ has_instrumentation = false;
+ e->flags |= EntityFlag_Require;
+ }
+
+ e->Procedure.has_instrumentation = has_instrumentation;
+
+
e->deprecated_message = ac.deprecated_message;
e->warning_message = ac.warning_message;
ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix);
@@ -1300,8 +1383,8 @@ gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, D
continue;
}
- begin_error_block();
- defer (end_error_block());
+
+ ERROR_BLOCK();
ProcTypeOverloadKind kind = are_proc_types_overload_safe(p->type, q->type);
bool both_have_where_clauses = false;