aboutsummaryrefslogtreecommitdiff
path: root/AGENTS/CONVENTIONS/CALLS.md
diff options
context:
space:
mode:
Diffstat (limited to 'AGENTS/CONVENTIONS/CALLS.md')
-rw-r--r--AGENTS/CONVENTIONS/CALLS.md60
1 files changed, 60 insertions, 0 deletions
diff --git a/AGENTS/CONVENTIONS/CALLS.md b/AGENTS/CONVENTIONS/CALLS.md
new file mode 100644
index 0000000..261b06f
--- /dev/null
+++ b/AGENTS/CONVENTIONS/CALLS.md
@@ -0,0 +1,60 @@
+# Conventions: calls, parameters and builtins
+
+Part of [Load-bearing conventions](../CONVENTIONS.md). Templates and operator
+overloads, which build on call resolution, are in [TEMPLATES_AND_OPERATORS.md](TEMPLATES_AND_OPERATORS.md).
+
+**Calls share argument marshalling.** `CodeGen::emitCall` handles global expression
+calls, CALL statements and bare `name(args)` statements; `emitMemberCall` resolves
+member access and adds a hidden receiver address. Both use `marshalCallArgs` and
+FunctionGen for user calls; statement calls discard results. Explicit casts may
+bridge C void* and nominal pseudocode pointer types.
+
+**User calls dispatch on the declared signature.**
+
+- `FunctionGen::emitPrototype` records every function's pseudocode signature
+ (`FuncSig`: return type name + per-param `ParamSig` {type name, mode, array
+ rank/bounds}).
+- `CodeGen::marshalCallArgs` — the single call-marshalling path for both call-expr
+ and call-stmt — requires BYREF arguments to be bare variables of *exactly* the
+ declared type (their `symbolAddress` is passed), admits BYVAL arguments through
+ `emitOwnedValue`, and dispatches whole-array arguments to
+ `ArrayHandler::emitArrayArgument`.
+- RETURN also uses `emitOwnedValue` against the declared return type. Class lvalues
+ invoke a same-class BYREF OVERLOAD NEW when defined; STRING-bearing aggregates
+ clone their owned fields. Other classes without a copy constructor copy bits; class
+ rvalues transfer ownership. Other values use `emitCoercedExpr`.
+- Top-level prototypes are pre-registered (after the TYPE pre-pass) before statement
+ emission, so call-before-definition is fine; a call with no registered signature is
+ a compile error. Method prototypes are pre-registered too.
+- OVERLOAD signatures append canonical parameter types to the link name; ordinary
+ names except MAIN get no mangling. `getOverloads` filters by visibility and
+ `resolveCall` selects exact static types/ranks. Return types, modes and bounds
+ never distinguish overloads.
+- In all cases, `emitPrototype` rejects names that collide with runtime/libc symbols
+ (`isReservedRuntimeName`), builtins, or enum values. Signatures retain the first
+ declaration spelling for LLVM lookup, independently of call-site casing.
+- Methods use `Class.Method` names and a hidden leading receiver address; their
+ FuncSig parameters contain only explicit source parameters.
+
+**Parameter modes are sticky and BYREF is procedure-only (guide §8.3).** In
+`(BYREF a : T, b : T)` the `b` is BYREF too; unannotated parameters default to BYVAL
+(§8.1). A BYREF parameter in a FUNCTION is a parse error.
+
+**Array parameters**: `ARRAY OF T` (rank 1, bounds travel with the argument) or
+`ARRAY[l:u,...] OF T` (literal bounds, any rank, a contract checked at compile time
+when the caller's bounds are constants, else at run time by throwing an exception).
+The LLVM ABI flattens each rank-R array parameter into a data `ptr` plus
+`kBoundArgsPerDim` (=2) i64 bounds per dimension; the callee rebuilds its
+`ArrayMetadata` from those (`ArrayHandler::bindArrayParameter` via the binder
+callback CodeGen injects into FunctionGen). BYVAL arrays copy their buffer at callee
+entry and clone STRING-bearing elements; BYREF binds the caller's buffer.
+
+**Builtins are plain identifiers backed by one table.** Builtins
+(EOF/MALLOC/FREE/REALLOC) parse as ordinary calls — no lexer/parser support, and the
+names are not reserved words. The inline constexpr `Builtins` table in the internal
+`lib/CodeGen/Builtins.h` ({Name, Arity, ReturnTypeName}) is the single source of
+truth: `emitCall` checks arity against it before dispatching to the per-builtin emit
+branches (still an if-chain, ahead of the user-function fallback), and
+`getExprTypeInfo` reads return types from it. EOF and the memory builtins consume the
+call source line for runtime diagnostics; they touch mutable runtime state and can
+throw.