aboutsummaryrefslogtreecommitdiff
path: root/src/check_builtin.cpp
diff options
context:
space:
mode:
authorFeoramund <161657516+Feoramund@users.noreply.github.com>2024-06-12 13:07:13 -0400
committerFeoramund <161657516+Feoramund@users.noreply.github.com>2024-06-12 13:07:13 -0400
commit5b5402fb23d0902810f18f805a72120f5243bddd (patch)
tree00b96cdffdb1e630fce6137a8cb2d5dd55f929e9 /src/check_builtin.cpp
parent35a845b93f11b152879bd08f90d196afcb7b8b25 (diff)
Add `intrinsics.syscall_bsd`
This is a BSD-style syscall that checks for a high Carry Flag as the error state. If the CF is high, the boolean return value is false, and if it is low (no errors) then the boolean return value is true.
Diffstat (limited to 'src/check_builtin.cpp')
-rw-r--r--src/check_builtin.cpp58
1 files changed, 52 insertions, 6 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 3aee804df..396a8bd80 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -5089,15 +5089,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
isize max_arg_count = 32;
switch (build_context.metrics.os) {
- case TargetOs_windows:
- case TargetOs_freestanding:
- error(call, "'%.*s' is not supported on this platform (%.*s)", LIT(builtin_name), LIT(target_os_names[build_context.metrics.os]));
- break;
case TargetOs_darwin:
case TargetOs_linux:
case TargetOs_essence:
- case TargetOs_freebsd:
- case TargetOs_openbsd:
case TargetOs_haiku:
switch (build_context.metrics.arch) {
case TargetArch_i386:
@@ -5107,6 +5101,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
break;
}
break;
+ default:
+ error(call, "'%.*s' is not supported on this platform (%.*s)", LIT(builtin_name), LIT(target_os_names[build_context.metrics.os]));
+ break;
}
if (ce->args.count > max_arg_count) {
@@ -5120,6 +5117,55 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
return true;
}
break;
+ case BuiltinProc_syscall_bsd:
+ {
+ convert_to_typed(c, operand, t_uintptr);
+ if (!is_type_uintptr(operand->type)) {
+ gbString t = type_to_string(operand->type);
+ error(operand->expr, "Argument 0 must be of type 'uintptr', got %s", t);
+ gb_string_free(t);
+ }
+ for (isize i = 1; i < ce->args.count; i++) {
+ Operand x = {};
+ check_expr(c, &x, ce->args[i]);
+ if (x.mode != Addressing_Invalid) {
+ convert_to_typed(c, &x, t_uintptr);
+ }
+ convert_to_typed(c, &x, t_uintptr);
+ if (!is_type_uintptr(x.type)) {
+ gbString t = type_to_string(x.type);
+ error(x.expr, "Argument %td must be of type 'uintptr', got %s", i, t);
+ gb_string_free(t);
+ }
+ }
+
+ isize max_arg_count = 32;
+
+ switch (build_context.metrics.os) {
+ case TargetOs_freebsd:
+ case TargetOs_netbsd:
+ case TargetOs_openbsd:
+ switch (build_context.metrics.arch) {
+ case TargetArch_amd64:
+ case TargetArch_arm64:
+ max_arg_count = 7;
+ break;
+ }
+ break;
+ default:
+ error(call, "'%.*s' is not supported on this platform (%.*s)", LIT(builtin_name), LIT(target_os_names[build_context.metrics.os]));
+ break;
+ }
+
+ if (ce->args.count > max_arg_count) {
+ error(ast_end_token(call), "'%.*s' has a maximum of %td arguments on this platform (%.*s), got %td", LIT(builtin_name), max_arg_count, LIT(target_os_names[build_context.metrics.os]), ce->args.count);
+ }
+
+ operand->mode = Addressing_Value;
+ operand->type = make_optional_ok_type(t_uintptr);
+ return true;
+ }
+ break;
case BuiltinProc_type_base_type: