mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Move builtin directives to a separate procedure
This commit is contained in:
+114
-111
@@ -1075,118 +1075,8 @@ bool check_builtin_simd_operation(CheckerContext *c, Operand *operand, Ast *call
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) {
|
bool check_builtin_procedure_directive(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) {
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
if (ce->inlining != ProcInlining_none) {
|
|
||||||
error(call, "Inlining operators are not allowed on built-in procedures");
|
|
||||||
}
|
|
||||||
|
|
||||||
BuiltinProc *bp = &builtin_procs[id];
|
|
||||||
{
|
|
||||||
char const *err = nullptr;
|
|
||||||
if (ce->args.count < bp->arg_count) {
|
|
||||||
err = "Too few";
|
|
||||||
} else if (ce->args.count > bp->arg_count && !bp->variadic) {
|
|
||||||
err = "Too many";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err != nullptr) {
|
|
||||||
gbString expr = expr_to_string(ce->proc);
|
|
||||||
error(ce->close, "%s arguments for '%s', expected %td, got %td",
|
|
||||||
err, expr,
|
|
||||||
bp->arg_count, ce->args.count);
|
|
||||||
gb_string_free(expr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (id) {
|
|
||||||
case BuiltinProc_size_of:
|
|
||||||
case BuiltinProc_align_of:
|
|
||||||
case BuiltinProc_offset_of:
|
|
||||||
case BuiltinProc_offset_of_by_string:
|
|
||||||
case BuiltinProc_type_info_of:
|
|
||||||
case BuiltinProc_typeid_of:
|
|
||||||
case BuiltinProc_len:
|
|
||||||
case BuiltinProc_min:
|
|
||||||
case BuiltinProc_max:
|
|
||||||
case BuiltinProc_type_is_subtype_of:
|
|
||||||
case BuiltinProc_objc_send:
|
|
||||||
case BuiltinProc_objc_find_selector:
|
|
||||||
case BuiltinProc_objc_find_class:
|
|
||||||
case BuiltinProc_objc_register_selector:
|
|
||||||
case BuiltinProc_objc_register_class:
|
|
||||||
case BuiltinProc_atomic_type_is_lock_free:
|
|
||||||
// NOTE(bill): The first arg may be a Type, this will be checked case by case
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BuiltinProc_atomic_thread_fence:
|
|
||||||
case BuiltinProc_atomic_signal_fence:
|
|
||||||
// NOTE(bill): first type will require a type hint
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BuiltinProc_DIRECTIVE: {
|
|
||||||
ast_node(bd, BasicDirective, ce->proc);
|
|
||||||
String name = bd->name.string;
|
|
||||||
if (name == "defined") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (name == "config") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*fallthrough*/
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if (BuiltinProc__type_begin < id && id < BuiltinProc__type_end) {
|
|
||||||
check_expr_or_type(c, operand, ce->args[0]);
|
|
||||||
} else if (ce->args.count > 0) {
|
|
||||||
check_multi_expr(c, operand, ce->args[0]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
String const &builtin_name = builtin_procs[id].name;
|
|
||||||
|
|
||||||
|
|
||||||
if (ce->args.count > 0) {
|
|
||||||
if (ce->args[0]->kind == Ast_FieldValue) {
|
|
||||||
if (id != BuiltinProc_soa_zip) {
|
|
||||||
error(call, "'field = value' calling is not allowed on built-in procedures");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BuiltinProc__simd_begin < id && id < BuiltinProc__simd_end) {
|
|
||||||
bool ok = check_builtin_simd_operation(c, operand, call, id, type_hint);
|
|
||||||
if (!ok) {
|
|
||||||
operand->type = t_invalid;
|
|
||||||
}
|
|
||||||
operand->mode = Addressing_Value;
|
|
||||||
operand->value = {};
|
|
||||||
operand->expr = call;
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (id) {
|
|
||||||
default:
|
|
||||||
GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_name));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BuiltinProc_objc_send:
|
|
||||||
case BuiltinProc_objc_find_selector:
|
|
||||||
case BuiltinProc_objc_find_class:
|
|
||||||
case BuiltinProc_objc_register_selector:
|
|
||||||
case BuiltinProc_objc_register_class:
|
|
||||||
return check_builtin_objc_procedure(c, operand, call, id, type_hint);
|
|
||||||
|
|
||||||
case BuiltinProc___entry_point:
|
|
||||||
operand->mode = Addressing_NoValue;
|
|
||||||
operand->type = nullptr;
|
|
||||||
mpmc_enqueue(&c->info->intrinsics_entry_point_usage, call);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BuiltinProc_DIRECTIVE: {
|
|
||||||
ast_node(bd, BasicDirective, ce->proc);
|
ast_node(bd, BasicDirective, ce->proc);
|
||||||
String name = bd->name.string;
|
String name = bd->name.string;
|
||||||
if (name == "location") {
|
if (name == "location") {
|
||||||
@@ -1635,9 +1525,122 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|||||||
} else {
|
} else {
|
||||||
error(call, "Unknown directive call: #%.*s", LIT(name));
|
error(call, "Unknown directive call: #%.*s", LIT(name));
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) {
|
||||||
|
ast_node(ce, CallExpr, call);
|
||||||
|
if (ce->inlining != ProcInlining_none) {
|
||||||
|
error(call, "Inlining operators are not allowed on built-in procedures");
|
||||||
|
}
|
||||||
|
|
||||||
|
BuiltinProc *bp = &builtin_procs[id];
|
||||||
|
{
|
||||||
|
char const *err = nullptr;
|
||||||
|
if (ce->args.count < bp->arg_count) {
|
||||||
|
err = "Too few";
|
||||||
|
} else if (ce->args.count > bp->arg_count && !bp->variadic) {
|
||||||
|
err = "Too many";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != nullptr) {
|
||||||
|
gbString expr = expr_to_string(ce->proc);
|
||||||
|
error(ce->close, "%s arguments for '%s', expected %td, got %td",
|
||||||
|
err, expr,
|
||||||
|
bp->arg_count, ce->args.count);
|
||||||
|
gb_string_free(expr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case BuiltinProc_size_of:
|
||||||
|
case BuiltinProc_align_of:
|
||||||
|
case BuiltinProc_offset_of:
|
||||||
|
case BuiltinProc_offset_of_by_string:
|
||||||
|
case BuiltinProc_type_info_of:
|
||||||
|
case BuiltinProc_typeid_of:
|
||||||
|
case BuiltinProc_len:
|
||||||
|
case BuiltinProc_min:
|
||||||
|
case BuiltinProc_max:
|
||||||
|
case BuiltinProc_type_is_subtype_of:
|
||||||
|
case BuiltinProc_objc_send:
|
||||||
|
case BuiltinProc_objc_find_selector:
|
||||||
|
case BuiltinProc_objc_find_class:
|
||||||
|
case BuiltinProc_objc_register_selector:
|
||||||
|
case BuiltinProc_objc_register_class:
|
||||||
|
case BuiltinProc_atomic_type_is_lock_free:
|
||||||
|
// NOTE(bill): The first arg may be a Type, this will be checked case by case
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BuiltinProc_atomic_thread_fence:
|
||||||
|
case BuiltinProc_atomic_signal_fence:
|
||||||
|
// NOTE(bill): first type will require a type hint
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BuiltinProc_DIRECTIVE: {
|
||||||
|
ast_node(bd, BasicDirective, ce->proc);
|
||||||
|
String name = bd->name.string;
|
||||||
|
if (name == "defined") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (name == "config") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*fallthrough*/
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if (BuiltinProc__type_begin < id && id < BuiltinProc__type_end) {
|
||||||
|
check_expr_or_type(c, operand, ce->args[0]);
|
||||||
|
} else if (ce->args.count > 0) {
|
||||||
|
check_multi_expr(c, operand, ce->args[0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String const &builtin_name = builtin_procs[id].name;
|
||||||
|
|
||||||
|
|
||||||
|
if (ce->args.count > 0) {
|
||||||
|
if (ce->args[0]->kind == Ast_FieldValue) {
|
||||||
|
if (id != BuiltinProc_soa_zip) {
|
||||||
|
error(call, "'field = value' calling is not allowed on built-in procedures");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BuiltinProc__simd_begin < id && id < BuiltinProc__simd_end) {
|
||||||
|
bool ok = check_builtin_simd_operation(c, operand, call, id, type_hint);
|
||||||
|
if (!ok) {
|
||||||
|
operand->type = t_invalid;
|
||||||
|
}
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
operand->value = {};
|
||||||
|
operand->expr = call;
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
default:
|
||||||
|
GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_name));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BuiltinProc_objc_send:
|
||||||
|
case BuiltinProc_objc_find_selector:
|
||||||
|
case BuiltinProc_objc_find_class:
|
||||||
|
case BuiltinProc_objc_register_selector:
|
||||||
|
case BuiltinProc_objc_register_class:
|
||||||
|
return check_builtin_objc_procedure(c, operand, call, id, type_hint);
|
||||||
|
|
||||||
|
case BuiltinProc___entry_point:
|
||||||
|
operand->mode = Addressing_NoValue;
|
||||||
|
operand->type = nullptr;
|
||||||
|
mpmc_enqueue(&c->info->intrinsics_entry_point_usage, call);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BuiltinProc_DIRECTIVE:
|
||||||
|
return check_builtin_procedure_directive(c, operand, call, id, type_hint);
|
||||||
|
|
||||||
case BuiltinProc_len:
|
case BuiltinProc_len:
|
||||||
check_expr_or_type(c, operand, ce->args[0]);
|
check_expr_or_type(c, operand, ce->args[0]);
|
||||||
|
|||||||
Reference in New Issue
Block a user