# Compile-time intrinsics

Every compiler-known builtin uses the `#name(...)` sigil: one uniform spelling, distinct from a regular function call. They fall into a few families.

| Family | Intrinsics |
|---|---|
| Typed queries | `#size_of::[T]()`, `#align_of::[T]()`, `#addr_of(place)`, `#zero::[T]()` |
| Data embedding | `#include_bytes("path")`, `#include_str("path")`, `#env("NAME")` |
| CPU hints | `#cpu_relax()` |
| ObjC + GPU FFI | `#selector("name")`, `#msg_send(recv, "sel", ...) -> RetTy`, `#compile_shader("file.metal", "msl")` |

## `#addr_of(place)`: address of a place as `*T`

Returns `*T` for the type of the addressed place. It is **unsafe** (wrap it in `unsafe`), because the returned pointer aliases existing storage and the borrow checker does not track its lifetime. Use it when a C function writes through a pointer.

```cplus
extern fn time(t: *i64) -> i64;

fn now() -> i64 {
    let mut t: i64 = 0;
    unsafe { time(#addr_of(t)); }
    return t;
}
```

The argument must be a place expression (an identifier, field access, index, or dereference chain). A call result or arithmetic temporary is rejected, there is no turbofish form (**E0501**), and using it outside `unsafe` is **E0801**.

## `#zero::[T]()`: an all-zero value

Safe, and useful for C-style aggregate initialization where you fill selected fields afterward. It is also accepted in `const` / `static` / `static mut` initializers.

```cplus
let mut p: Point = #zero::[Point]();
p.x = 10;
```

## `#size_of::[T]()` and `#align_of::[T]()`

Return `usize`. Safe, with no memory access; LLVM folds the call to a constant at `-O1` and above. Substitution propagates through monomorphization, so the value is correct for every instantiation of a generic.

```cplus
let bytes: usize = #size_of::[T]() *% (n as usize);
let p: *u8       = unsafe { malloc(bytes) };
```

## `#include_bytes` / `#include_str`: embed a file at compile time

`#include_bytes("path")` embeds a file as a `*[u8; N]` where `N` is the file length, known at compile time. `#include_str("path")` does the same but returns a `str` and requires valid UTF-8. Paths resolve relative to the source file containing the call.

```cplus
let shader: *[u8; 2048] = #include_bytes("../shaders/double.metallib");
let manifest: str       = #include_str("config.txt");
```

The bytes live in `.rodata`. Errors: **E0870** (path not found), **E0871** (non-literal argument), **E0872** (over the 64 MiB limit), and **E0875** (invalid UTF-8, for `#include_str`).

## `#env("NAME")`: read an environment variable at compile time

Returns a `str` pointing at a `.rodata` global with the value the compiler saw. Useful for baking build-time config into a binary.

```cplus
let greeting: str = #env("GREETING");   // resolved at sema time
```

Errors: **E0903** (non-literal argument), **E0876** (variable not set when `cpc` ran). There is no optional form; use a sentinel and check the length at runtime if you need "missing".

## `#cpu_relax()`

A spin-loop CPU hint. It lowers to the platform pause/yield instruction where available, and to nothing elsewhere. Safe, returns `()`.

## ObjC and GPU intrinsics

`#selector`, `#msg_send`, and `#compile_shader` are the load-bearing primitives the [appkit](/docs/packages/appkit) and [metal](/docs/packages/metal) bindings sit on. Direct use is rare; consume them through those packages. See [FFI](/docs/ffi) for the Objective-C mechanics.
