comptime compiler-API: Phase 1 foundation + Phase 2.1 weld plan
Introduce the welded comptime `compiler` library (`#library "compiler"` +
`abi(.zig) extern compiler`), per design/comptime-compiler-api.md, and unify
`callconv(...)` into the new `abi(...)` annotation.
abi(...) replaces callconv(...):
- New ABI enum { default, c, zig, pure }; `abi(.c|.zig|.pure)` parses in the
postfix slot before extern/export (and standalone). `kw_callconv` -> `kw_abi`.
- Migrated 52 sx files, the call-convention-mismatch diagnostic, and docs
(readme/specs) from `callconv(.c)` to `abi(.c)`.
Phase 1 — welded compiler library (parse -> registry -> validation -> bridge):
- `abi(.zig) extern compiler` parses on fn decls (carries abi/extern_lib) and
struct decls (StructDecl.abi/extern_lib).
- `#library "compiler"` is the comptime-only internal surface — never dlopen'd.
- src/ir/compiler_lib.zig: the binding registry (the safety boundary). `Field`
welded to StructInfo.Field with layout baked from the real Zig type
(@offsetOf/@sizeOf); `findType`/`findFn`. Welded structs are layout-validated
at registration (field set + total size) as a header checked against the impl.
- Host-call bridge: a `fn abi(.zig) extern compiler` dispatches under the
comptime interp to its registered Zig handler (intern/text_of round-trip),
never dlsym. IR Function.compiler_welded; validated in declareFunction.
- Comptime-only enforcement: a runtime call to a welded fn is a clean
build-gating error (emitCall), not an undefined-symbol link failure.
Phase 2.1 — byte-layout weld foundation:
- Decision: full byte-layout weld (sx struct laid out byte-identically to the
bound Zig type). Registered StructInfo (first non-natural / Zig-reordered
layout). `computeWeldPlan` — pure offset-ordered element plan + padding +
sx-field->LLVM-element remap; unit-tested. Emit/interp wiring is the next
sub-step (2.2+, see current/CHECKPOINT-COMPILER-API.md).
Examples: 0625/0626 (welded struct + fn round-trip), 1183/1184/1185
(layout-mismatch, unexported-fn, runtime-call diagnostics).
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// Generic `Into(Block)` impl with a `string`-typed arg in the
|
||||
// closure signature. The block trampoline declares the param with
|
||||
// callconv(.c); without the abi-collapse fix, sx `string` got
|
||||
// abi(.c); without the abi-collapse fix, sx `string` got
|
||||
// silently collapsed to `ptr` (the libc `char *` heuristic) and
|
||||
// the caller's 16-byte `{ptr, len}` value mismatched the
|
||||
// trampoline's 8-byte `ptr` slot. Result: segfault inside the
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// The fix lives in `abiCoerceParamTypeEx`: the `string`/`slice` →
|
||||
// `ptr` collapse only applies to `is_extern` extern decls (libc
|
||||
// interop). sx-internal `callconv(.c)` keeps the full slice
|
||||
// interop). sx-internal `abi(.c)` keeps the full slice
|
||||
// shape, which lands as `[2 x i64]` at the LLVM signature site
|
||||
// and matches the caller's two-register pass on AArch64.
|
||||
|
||||
@@ -20,7 +20,7 @@ g_s: string = "";
|
||||
main :: () -> i32 {
|
||||
cl := (s: string) => { g_s = s; };
|
||||
b : Block = xx cl;
|
||||
invoke_fn : (*Block, string) -> void callconv(.c) = xx b.invoke;
|
||||
invoke_fn : (*Block, string) -> void abi(.c) = xx b.invoke;
|
||||
invoke_fn(@b, "hello");
|
||||
if g_s.len == 0 { print("FAIL: empty\n"); return 1; }
|
||||
print("got: <{}>\n", g_s);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// FFI plan step 5.2 — generic `Into(Block) for Closure(..$args) ->
|
||||
// $R` impl. One impl in stdlib covers every closure shape; the
|
||||
// compiler monomorphises the impl body per call shape and emits a
|
||||
// dedicated `__invoke` `callconv(.c)` trampoline + Block literal
|
||||
// dedicated `__invoke` `abi(.c)` trampoline + Block literal
|
||||
// (via `#insert build_block_convert($args, $R);`).
|
||||
//
|
||||
// This test exercises a closure shape (`Closure(i64, i64) -> void`)
|
||||
@@ -13,7 +13,7 @@
|
||||
// the per-shape trampoline ferries control back to the sx closure.
|
||||
//
|
||||
// The block is invoked directly through `b.invoke` (a typed
|
||||
// `callconv(.c)` fn-pointer) — the same shape the Apple Block
|
||||
// `abi(.c)` fn-pointer) — the same shape the Apple Block
|
||||
// runtime calls when a UIKit/Foundation API hands the block back
|
||||
// to its registered invoke.
|
||||
|
||||
@@ -27,7 +27,7 @@ main :: () -> i32 {
|
||||
cl := (a: i64, b: i64) => { g_a = a; g_b = b; };
|
||||
blk : Block = xx cl;
|
||||
|
||||
invoke_fn : (*Block, i64, i64) -> void callconv(.c) = xx blk.invoke;
|
||||
invoke_fn : (*Block, i64, i64) -> void abi(.c) = xx blk.invoke;
|
||||
invoke_fn(@blk, 10, 20);
|
||||
|
||||
if g_a != 10 { print("FAIL: g_a={}\n", g_a); return 1; }
|
||||
|
||||
24
examples/0625-comptime-weld-struct-field.sx
Normal file
24
examples/0625-comptime-weld-struct-field.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
// Comptime compiler API — a layout-welded struct binding.
|
||||
//
|
||||
// `Field :: struct abi(.zig) extern compiler { … }` binds the sx struct to the
|
||||
// compiler's real internal Zig type (`StructInfo.Field`, two u32s) via the
|
||||
// `compiler` library. The compiler validates the sx declaration against the
|
||||
// welded type's layout at registration time (the sx side is a header checked
|
||||
// against the implementation) — a faithful declaration validates clean and the
|
||||
// struct is otherwise ordinary data. The `compiler` library is the comptime-only
|
||||
// internal surface, so `#library "compiler"` is NOT dlopen'd.
|
||||
//
|
||||
// Phase 1 (foundation): the weld is layout-validated; field offsets coincide with
|
||||
// the natural layout for `Field` (two u32s). Welded host-call functions land in a
|
||||
// later phase.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
compiler :: #library "compiler";
|
||||
|
||||
Field :: struct abi(.zig) extern compiler { name: u32; ty: u32; }
|
||||
|
||||
main :: () {
|
||||
f := Field.{ name = 7, ty = 3 };
|
||||
print("name={} ty={}\n", f.name, f.ty);
|
||||
}
|
||||
24
examples/0626-comptime-weld-fn-intern-text-of.sx
Normal file
24
examples/0626-comptime-weld-fn-intern-text-of.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
// Comptime compiler API — welded compiler FUNCTIONS over the host-call bridge.
|
||||
//
|
||||
// `intern` / `text_of` are bound to the `compiler` library via
|
||||
// `abi(.zig) extern compiler`. They have no real symbol — under the comptime
|
||||
// interpreter the call dispatches to the compiler's registered Zig handler
|
||||
// (the string pool), never dlsym. Comptime-only: here they run inside `#run`,
|
||||
// folding to a plain string constant the runtime `main` prints.
|
||||
//
|
||||
// Round-trip: `text_of(intern(s)) == s` — interning a string yields a handle,
|
||||
// and resolving the handle gives the text back.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
compiler :: #library "compiler";
|
||||
|
||||
StringId :: u32;
|
||||
intern :: (s: string) -> StringId abi(.zig) extern compiler;
|
||||
text_of :: (id: StringId) -> string abi(.zig) extern compiler;
|
||||
|
||||
greeting :: #run text_of(intern("hello, compiler"));
|
||||
|
||||
main :: () {
|
||||
print("{}\n", greeting);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Passing a default-conv sx function as a callconv(.c) fn-pointer
|
||||
// Passing a default-conv sx function as a abi(.c) fn-pointer
|
||||
// silently mismatches ABIs — historically that meant the C-side caller
|
||||
// supplied no `__sx_ctx` slot 0 and the sx-side body read garbage.
|
||||
// The compiler now rejects the coercion outright with a "call-convention
|
||||
@@ -9,6 +9,6 @@
|
||||
sx_handler :: (arg: *void) -> *void { return arg; }
|
||||
|
||||
main :: () -> i32 {
|
||||
fp : (*void) -> *void callconv(.c) = sx_handler;
|
||||
fp : (*void) -> *void abi(.c) = sx_handler;
|
||||
return 0;
|
||||
}
|
||||
|
||||
17
examples/1183-diagnostics-weld-struct-field-count.sx
Normal file
17
examples/1183-diagnostics-weld-struct-field-count.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
// Diagnostic: a layout-welded struct whose sx declaration does NOT faithfully
|
||||
// mirror the compiler's real Zig type is a build error — the sx side is a header
|
||||
// checked against the implementation, not a free reinterpretation.
|
||||
//
|
||||
// `Field` is two u32s (`name`, `ty`) in the compiler library; declaring it with a
|
||||
// single field must be rejected at registration with a clear field-count message.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
compiler :: #library "compiler";
|
||||
|
||||
Field :: struct abi(.zig) extern compiler { name: u32; }
|
||||
|
||||
main :: () {
|
||||
f := Field.{ name = 1 };
|
||||
print("{}\n", f.name);
|
||||
}
|
||||
11
examples/1184-diagnostics-weld-fn-unexported.sx
Normal file
11
examples/1184-diagnostics-weld-fn-unexported.sx
Normal file
@@ -0,0 +1,11 @@
|
||||
// Diagnostic: a `fn abi(.zig) extern compiler` whose name is NOT on the compiler
|
||||
// library's function-export list is a build error — the export list is the
|
||||
// safety boundary, so an unbound name can't silently fall through to dlsym.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
compiler :: #library "compiler";
|
||||
|
||||
not_a_real_compiler_fn :: (x: i64) -> i64 abi(.zig) extern compiler;
|
||||
|
||||
main :: () { print("unreached\n"); }
|
||||
17
examples/1185-diagnostics-weld-fn-runtime-call.sx
Normal file
17
examples/1185-diagnostics-weld-fn-runtime-call.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
// Diagnostic: a welded `compiler`-library function is comptime-only — it has no
|
||||
// runtime symbol (the comptime interpreter dispatches it to a Zig handler).
|
||||
// Calling one from runtime code is a build error with a clear message, NOT an
|
||||
// undefined-symbol link failure. (A comptime use — inside `#run` or a `::` —
|
||||
// is fine; see examples/0626.)
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
compiler :: #library "compiler";
|
||||
|
||||
StringId :: u32;
|
||||
intern :: (s: string) -> StringId abi(.zig) extern compiler;
|
||||
|
||||
main :: () {
|
||||
id := intern("called at runtime");
|
||||
print("{}\n", id);
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
// `callconv(.c)` on function pointers passed to extern callbacks — ensures
|
||||
// `abi(.c)` on function pointers passed to extern callbacks — ensures
|
||||
// the function uses C ABI so it can be safely invoked from `extern`
|
||||
// functions like SDL_AddEventWatch.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
// A function with C calling convention
|
||||
add_c :: (a: i64, b: i64) -> i64 callconv(.c) {
|
||||
add_c :: (a: i64, b: i64) -> i64 abi(.c) {
|
||||
a + b
|
||||
}
|
||||
|
||||
main :: () {
|
||||
// Call it directly — should work like any other function
|
||||
result := add_c(10, 32);
|
||||
print("callconv(.c): {}\n", result);
|
||||
print("abi(.c): {}\n", result);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// `callconv(.c)` callbacks accessing struct methods on global pointers —
|
||||
// `abi(.c)` callbacks accessing struct methods on global pointers —
|
||||
// regression coverage for prior data-corruption when the callback dispatches
|
||||
// through a global pointer to a method on the pointed-to struct.
|
||||
|
||||
@@ -29,7 +29,7 @@ do_render :: () {
|
||||
print("wrapper: pw={}, ph={}, frame={}\n", g_pipe.pw, g_pipe.ph, g_pipe.frame);
|
||||
}
|
||||
|
||||
callback_inline :: (userdata: *void, code: i64) -> bool callconv(.c) {
|
||||
callback_inline :: (userdata: *void, code: i64) -> bool abi(.c) {
|
||||
g_width = xx code;
|
||||
g_height = xx (code + 1);
|
||||
g_pipe.resize(xx g_width, xx g_height);
|
||||
@@ -38,7 +38,7 @@ callback_inline :: (userdata: *void, code: i64) -> bool callconv(.c) {
|
||||
true
|
||||
}
|
||||
|
||||
callback_wrapper :: (userdata: *void, code: i64) -> bool callconv(.c) {
|
||||
callback_wrapper :: (userdata: *void, code: i64) -> bool abi(.c) {
|
||||
g_width = xx code;
|
||||
g_height = xx (code + 1);
|
||||
do_render();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Regression test for issue-0025 path A.
|
||||
//
|
||||
// sx functions declared with `callconv(.c)` that take a composite > 16 bytes
|
||||
// sx functions declared with `abi(.c)` that take a composite > 16 bytes
|
||||
// by value must marshal the arg through `ptr byval(<T>)` per AAPCS64 / SysV
|
||||
// AArch64: the caller copies the struct to an alloca, passes the alloca
|
||||
// pointer with a `byval(<T>)` attribute, and the callee's entry block loads
|
||||
@@ -20,7 +20,7 @@ Wide :: struct {
|
||||
d: i64;
|
||||
}
|
||||
|
||||
accept_c :: (w: Wide) -> i64 callconv(.c) {
|
||||
accept_c :: (w: Wide) -> i64 abi(.c) {
|
||||
w.a + w.b + w.c + w.d
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Regression test for issue-0025 path B.
|
||||
//
|
||||
// When a fn-pointer's type is spelled with `callconv(.c)`, the indirect
|
||||
// When a fn-pointer's type is spelled with `abi(.c)`, the indirect
|
||||
// call must apply the same C-ABI byval coercion that direct C-ABI calls
|
||||
// do at the call site (path A): >16-byte non-HFA aggregates are passed
|
||||
// as `ptr byval(<T>)`. Without the fix, the indirect call site builds
|
||||
@@ -9,8 +9,8 @@
|
||||
// ways that don't match the byval-attributed callee signature — the
|
||||
// callee then reads garbage out of the wrong machine-state slots.
|
||||
//
|
||||
// The opt-in is the `callconv(.c)` on the fn-pointer type spelling.
|
||||
// Pure-sx fn-pointer casts (no callconv suffix) keep their default
|
||||
// The opt-in is the `abi(.c)` on the fn-pointer type spelling.
|
||||
// Pure-sx fn-pointer casts (no abi suffix) keep their default
|
||||
// calling convention — verified by examples/87-fnptr-cast-large-aggregate.sx.
|
||||
|
||||
#import "modules/std.sx";
|
||||
@@ -22,7 +22,7 @@ Wide :: struct {
|
||||
d: i64;
|
||||
}
|
||||
|
||||
accept_c :: (w: Wide) -> i64 callconv(.c) {
|
||||
accept_c :: (w: Wide) -> i64 abi(.c) {
|
||||
w.a + w.b + w.c + w.d
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ main :: () -> i32 {
|
||||
w := Wide.{ a = 1, b = 10, c = 100, d = 1000 };
|
||||
if accept_c(w) != 1111 { return 1; }
|
||||
|
||||
fn_ptr : (Wide) -> i64 callconv(.c) = xx accept_c;
|
||||
fn_ptr : (Wide) -> i64 abi(.c) = xx accept_c;
|
||||
if fn_ptr(w) != 1111 { return 2; }
|
||||
|
||||
0
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Pure-sx fn-pointer cast: a function-pointer typed without `callconv(.c)`
|
||||
// Pure-sx fn-pointer cast: a function-pointer typed without `abi(.c)`
|
||||
// keeps the default (sx) calling convention. Passing a >16-byte aggregate
|
||||
// through that pointer must not get the C-ABI byval coercion — the sx-CC
|
||||
// callee expects the struct as an SSA value, not as a `ptr byval(<T>)`.
|
||||
//
|
||||
// Pair with examples/86-callconv-c-fnptr-large-aggregate.sx, which covers
|
||||
// the opposite arm (fn-pointer typed `callconv(.c)` does get byval).
|
||||
// Pair with examples/86-abi-c-fnptr-large-aggregate.sx, which covers
|
||||
// the opposite arm (fn-pointer typed `abi(.c)` does get byval).
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
|
||||
@@ -16,19 +16,19 @@
|
||||
#source "1214-ffi-06-callback.c";
|
||||
};
|
||||
|
||||
ffi_apply_callback :: (cb: (i32) -> i32 callconv(.c), value: i32) -> i32 extern;
|
||||
ffi_apply_callback2 :: (cb: (*void, i32) -> i32 callconv(.c), ctx: *void, v: i32) -> i32 extern;
|
||||
ffi_apply_callback :: (cb: (i32) -> i32 abi(.c), value: i32) -> i32 extern;
|
||||
ffi_apply_callback2 :: (cb: (*void, i32) -> i32 abi(.c), ctx: *void, v: i32) -> i32 extern;
|
||||
|
||||
g_callback_hits : i32 = 0;
|
||||
g_callback_sum : i32 = 0;
|
||||
|
||||
double_it :: (x: i32) -> i32 callconv(.c) {
|
||||
double_it :: (x: i32) -> i32 abi(.c) {
|
||||
g_callback_hits += 1;
|
||||
g_callback_sum += x;
|
||||
x * 2
|
||||
}
|
||||
|
||||
add_with_ctx :: (ctx: *void, v: i32) -> i32 callconv(.c) {
|
||||
add_with_ctx :: (ctx: *void, v: i32) -> i32 abi(.c) {
|
||||
g_callback_hits += 1;
|
||||
// Pass a sentinel via ctx to prove the pointer arg also survives the
|
||||
// round-trip — read it back as an i32 through *i32.
|
||||
|
||||
@@ -18,10 +18,10 @@ main :: () -> i32 {
|
||||
sel_with_utf8 := sel_registerName("stringWithUTF8String:".ptr);
|
||||
sel_utf8 := sel_registerName("UTF8String".ptr);
|
||||
|
||||
msg_3 : (*void, *void, [*]u8) -> *void callconv(.c) = xx objc_msgSend;
|
||||
msg_3 : (*void, *void, [*]u8) -> *void abi(.c) = xx objc_msgSend;
|
||||
ns_str := msg_3(ns_class, sel_with_utf8, "hi".ptr);
|
||||
|
||||
msg_2 : (*void, *void) -> [*]u8 callconv(.c) = xx objc_msgSend;
|
||||
msg_2 : (*void, *void) -> [*]u8 abi(.c) = xx objc_msgSend;
|
||||
back := msg_2(ns_str, sel_utf8);
|
||||
|
||||
return xx (back[0] + back[1]); // 'h' + 'i' = 104 + 105 = 209
|
||||
|
||||
@@ -17,7 +17,7 @@ g_marker : i32 = 0;
|
||||
|
||||
// IMP for `hello`. Must use C calling convention so `self` and `_cmd` land in
|
||||
// x0 and x1 the way the Obj-C runtime expects.
|
||||
hello_imp :: (self: *void, _cmd: *void) callconv(.c) {
|
||||
hello_imp :: (self: *void, _cmd: *void) abi(.c) {
|
||||
g_marker = 42;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ main :: () -> i32 {
|
||||
if obj == xx 0 { return 2; }
|
||||
|
||||
// [obj hello]
|
||||
msg : (*void, *void) -> void callconv(.c) = xx objc_msgSend;
|
||||
msg : (*void, *void) -> void abi(.c) = xx objc_msgSend;
|
||||
msg(obj, sel_hello);
|
||||
|
||||
return g_marker; // 42 if hello_imp ran
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
main :: () -> i32 {
|
||||
cl := () => { print("noop block ran\n"); };
|
||||
b : Block = xx cl;
|
||||
invoke_fn : (*Block) -> void callconv(.c) = xx b.invoke;
|
||||
invoke_fn : (*Block) -> void abi(.c) = xx b.invoke;
|
||||
invoke_fn(@b);
|
||||
0
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ main :: () -> i32 {
|
||||
y : i64 = 100;
|
||||
cl := () => { print("x + y = {}\n", x + y); };
|
||||
b : Block = xx cl;
|
||||
invoke_fn : (*Block) -> void callconv(.c) = xx b.invoke;
|
||||
invoke_fn : (*Block) -> void abi(.c) = xx b.invoke;
|
||||
invoke_fn(@b);
|
||||
0
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// Trampoline matching `void (^)(int, void*)` — the C ABI Apple's
|
||||
// runtime calls. Forwards through to the sx closure with the
|
||||
// standard `(__sx_ctx, env, ...args)` shape.
|
||||
__block_invoke_void_i32_p :: (block_self: *Block, arg0: i32, arg1: *void) callconv(.c) {
|
||||
__block_invoke_void_i32_p :: (block_self: *Block, arg0: i32, arg1: *void) abi(.c) {
|
||||
typed_fn : (*void, i32, *void) -> void = xx block_self.sx_fn;
|
||||
typed_fn(block_self.sx_env, arg0, arg1);
|
||||
}
|
||||
@@ -49,7 +49,7 @@ main :: () -> i32 {
|
||||
};
|
||||
b : Block = xx cl;
|
||||
|
||||
invoke_fn : (*Block, i32, *void) -> void callconv(.c) = xx b.invoke;
|
||||
invoke_fn : (*Block, i32, *void) -> void abi(.c) = xx b.invoke;
|
||||
sentinel: i32 = 42;
|
||||
invoke_fn(@b, 41, xx @sentinel);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#import "modules/ffi/objc_block.sx";
|
||||
|
||||
invoke_once :: (b: *Block) {
|
||||
invoke_fn : (*Block) -> void callconv(.c) = xx b.invoke;
|
||||
invoke_fn : (*Block) -> void abi(.c) = xx b.invoke;
|
||||
invoke_fn(b);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ main :: () -> i32 {
|
||||
|
||||
// [SxFoo alloc] — invokes the synthesized +alloc IMP.
|
||||
sel_alloc : SEL = sel_registerName("alloc".ptr);
|
||||
msg_fn : (cls: *void, sel: *void) -> *void callconv(.c) = xx objc_msgSend;
|
||||
msg_fn : (cls: *void, sel: *void) -> *void abi(.c) = xx objc_msgSend;
|
||||
instance : *void = msg_fn(cls, sel_alloc);
|
||||
if instance == null { print("FAIL: +alloc returned null\n"); return 1; }
|
||||
|
||||
|
||||
@@ -39,12 +39,12 @@ main :: () -> i32 {
|
||||
|
||||
// alloc + release — synthesized -dealloc IMP fires inside.
|
||||
sel_alloc : SEL = sel_registerName("alloc".ptr);
|
||||
alloc_fn : (cls: *void, sel: *void) -> *void callconv(.c) = xx objc_msgSend;
|
||||
alloc_fn : (cls: *void, sel: *void) -> *void abi(.c) = xx objc_msgSend;
|
||||
instance : *void = alloc_fn(cls, sel_alloc);
|
||||
if instance == null { print("FAIL: +alloc returned null\n"); return 1; }
|
||||
|
||||
sel_release : SEL = sel_registerName("release".ptr);
|
||||
release_fn : (obj: *void, sel: *void) -> void callconv(.c) = xx objc_msgSend;
|
||||
release_fn : (obj: *void, sel: *void) -> void abi(.c) = xx objc_msgSend;
|
||||
release_fn(instance, sel_release);
|
||||
|
||||
// Run another cycle to confirm dealloc didn't corrupt runtime state.
|
||||
|
||||
@@ -35,7 +35,7 @@ main :: () -> i32 {
|
||||
if method == null { print("FAIL: class method not on metaclass\n"); return 1; }
|
||||
|
||||
// Invoke via objc_msgSend: [SxFoo answer] → 42.
|
||||
msg_fn : (cls: *void, sel: *void) -> i32 callconv(.c) = xx objc_msgSend;
|
||||
msg_fn : (cls: *void, sel: *void) -> i32 abi(.c) = xx objc_msgSend;
|
||||
result : i32 = msg_fn(cls, sel_answer);
|
||||
if result != 42 { print("FAIL: expected 42, got {}\n", result); return 1; }
|
||||
|
||||
|
||||
@@ -38,13 +38,13 @@ main :: () -> i32 {
|
||||
|
||||
// [SxThing answer] → 42
|
||||
sel_answer : SEL = sel_registerName("answer".ptr);
|
||||
msg_int : (cls: *void, sel: *void) -> i32 callconv(.c) = xx objc_msgSend;
|
||||
msg_int : (cls: *void, sel: *void) -> i32 abi(.c) = xx objc_msgSend;
|
||||
r := msg_int(cls, sel_answer);
|
||||
if r != 42 { print("FAIL: answer expected 42, got {}\n", r); return 1; }
|
||||
|
||||
// [SxThing seedClass] returns a non-null NSObject.
|
||||
sel_seed : SEL = sel_registerName("seedClass".ptr);
|
||||
msg_ptr : (cls: *void, sel: *void) -> *void callconv(.c) = xx objc_msgSend;
|
||||
msg_ptr : (cls: *void, sel: *void) -> *void abi(.c) = xx objc_msgSend;
|
||||
seed := msg_ptr(cls, sel_seed);
|
||||
if seed == null { print("FAIL: seedClass returned null\n"); return 1; }
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
// runtime ivar. Property dispatch should round-trip through them.
|
||||
g_probe_tag: i32 = 0;
|
||||
|
||||
probe_get_tag :: (self: *void, _cmd: *void) -> i32 callconv(.c) {
|
||||
probe_get_tag :: (self: *void, _cmd: *void) -> i32 abi(.c) {
|
||||
return g_probe_tag;
|
||||
}
|
||||
probe_set_tag :: (self: *void, _cmd: *void, v: i32) callconv(.c) {
|
||||
probe_set_tag :: (self: *void, _cmd: *void, v: i32) abi(.c) {
|
||||
g_probe_tag = v;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// through it and returns void.
|
||||
//
|
||||
// Register a runtime-built Obj-C class with a method that returns
|
||||
// a fixed `Triple`. The IMP is a plain sx fn (callconv .c) — its
|
||||
// a fixed `Triple`. The IMP is a plain sx fn (abi .c) — its
|
||||
// sret-shaped lowering already works (Phase 0.3 fix for plain
|
||||
// `extern` returns). The `#objc_call` dispatch side now produces
|
||||
// the matching call shape: `call void @objc_msgSend(ptr sret %slot,
|
||||
@@ -20,7 +20,7 @@ Triple :: struct { a: i64; b: i64; c: i64; }
|
||||
|
||||
// IMP for the runtime-installed method. Obj-C convention: implicit
|
||||
// (self, _cmd) prefix, then declared args. Returns the value bytes.
|
||||
triple_imp :: (self: *void, _cmd: *void) -> Triple callconv(.c) {
|
||||
triple_imp :: (self: *void, _cmd: *void) -> Triple abi(.c) {
|
||||
Triple.{ a = 11, b = 22, c = 33 }
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ UIEdgeInsets :: struct {
|
||||
right: f64;
|
||||
}
|
||||
|
||||
insets_imp :: (self: *void, _cmd: *void) -> UIEdgeInsets callconv(.c) {
|
||||
insets_imp :: (self: *void, _cmd: *void) -> UIEdgeInsets abi(.c) {
|
||||
UIEdgeInsets.{ top = 1.5, left = 2.5, bottom = 3.5, right = 4.5 }
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#import "modules/build.sx";
|
||||
#import "modules/ffi/objc.sx";
|
||||
|
||||
combine_imp :: (self: *void, _cmd: *void, a: i32, b: i32) -> i32 callconv(.c) {
|
||||
combine_imp :: (self: *void, _cmd: *void, a: i32, b: i32) -> i32 abi(.c) {
|
||||
a * 100 + b
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
#import "modules/build.sx";
|
||||
#import "modules/ffi/objc.sx";
|
||||
|
||||
yes_imp :: (self: *void, _cmd: *void) -> bool callconv(.c) { true }
|
||||
no_imp :: (self: *void, _cmd: *void) -> bool callconv(.c) { false }
|
||||
yes_imp :: (self: *void, _cmd: *void) -> bool abi(.c) { true }
|
||||
no_imp :: (self: *void, _cmd: *void) -> bool abi(.c) { false }
|
||||
|
||||
main :: () -> i32 {
|
||||
inline if OS == .macos {
|
||||
|
||||
@@ -20,11 +20,11 @@ CGRect :: struct {
|
||||
height: f64;
|
||||
}
|
||||
|
||||
rect_imp :: (self: *void, _cmd: *void) -> CGRect callconv(.c) {
|
||||
rect_imp :: (self: *void, _cmd: *void) -> CGRect abi(.c) {
|
||||
CGRect.{ x = 10.5, y = 20.5, width = 30.5, height = 40.5 }
|
||||
}
|
||||
|
||||
u64_imp :: (self: *void, _cmd: *void) -> u64 callconv(.c) {
|
||||
u64_imp :: (self: *void, _cmd: *void) -> u64 abi(.c) {
|
||||
// sx integer-literal parser rejects values ≥ 2^63 even when the
|
||||
// receiving type is u64, so the leading bit stays clear.
|
||||
0x7FEDCBA987654321
|
||||
|
||||
@@ -51,7 +51,7 @@ main :: () -> i32 {
|
||||
|
||||
// release
|
||||
sel_release : SEL = sel_registerName("release".ptr);
|
||||
release_fn : (obj: *void, sel: *void) -> void callconv(.c) = xx objc_msgSend;
|
||||
release_fn : (obj: *void, sel: *void) -> void abi(.c) = xx objc_msgSend;
|
||||
release_fn(xx f, sel_release);
|
||||
}
|
||||
inline if OS != .macos {
|
||||
|
||||
@@ -52,7 +52,7 @@ main :: () -> i32 {
|
||||
print("at: ({}, {})\n", p.x, p.y); // expected: at: (7.500000, 8.250000)
|
||||
|
||||
sel_release : SEL = sel_registerName("release".ptr);
|
||||
release_fn : (obj: *void, sel: *void) -> void callconv(.c) = xx objc_msgSend;
|
||||
release_fn : (obj: *void, sel: *void) -> void abi(.c) = xx objc_msgSend;
|
||||
release_fn(xx m, sel_release);
|
||||
}
|
||||
inline if OS != .macos {
|
||||
|
||||
@@ -20,7 +20,7 @@ SxProbeNiladic :: #objc_class("SxProbeNiladic") extern {
|
||||
length :: (self: *Self) -> i32;
|
||||
}
|
||||
|
||||
length_imp :: (self: *void, _cmd: *void) -> i32 callconv(.c) {
|
||||
length_imp :: (self: *void, _cmd: *void) -> i32 abi(.c) {
|
||||
42
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ SxProbeOneArg :: #objc_class("SxProbeOneArg") extern {
|
||||
addObject :: (self: *Self, val: i32) -> i32;
|
||||
}
|
||||
|
||||
addObject_imp :: (self: *void, _cmd: *void, val: i32) -> i32 callconv(.c) {
|
||||
addObject_imp :: (self: *void, _cmd: *void, val: i32) -> i32 abi(.c) {
|
||||
val * 2
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ SxProbeMultiKeyword :: #objc_class("SxProbeMultiKeyword") extern {
|
||||
combine_and :: (self: *Self, a: i32, b: i32) -> i32;
|
||||
}
|
||||
|
||||
combine_imp :: (self: *void, _cmd: *void, a: i32, b: i32) -> i32 callconv(.c) {
|
||||
combine_imp :: (self: *void, _cmd: *void, a: i32, b: i32) -> i32 abi(.c) {
|
||||
a * 100 + b
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ SxManglingProbe :: #objc_class("SxManglingProbe") extern {
|
||||
custom_name :: (self: *Self) -> i32 #selector("actualSelectorName");
|
||||
}
|
||||
|
||||
universal_imp :: (self: *void, _cmd: *void, a: i32, b: i32, c: i32, d: i32) -> i32 callconv(.c) {
|
||||
universal_imp :: (self: *void, _cmd: *void, a: i32, b: i32, c: i32, d: i32) -> i32 abi(.c) {
|
||||
// Returns the arg count's witness; the test doesn't check return
|
||||
// values, only that dispatch succeeds for each selector shape.
|
||||
a + b + c + d
|
||||
|
||||
@@ -31,7 +31,7 @@ main :: () -> i32 {
|
||||
print("counter: {}\n", b.get()); // expected: 2
|
||||
|
||||
sel_release : SEL = sel_registerName("release".ptr);
|
||||
release_fn : (obj: *void, sel: *void) -> void callconv(.c) = xx objc_msgSend;
|
||||
release_fn : (obj: *void, sel: *void) -> void abi(.c) = xx objc_msgSend;
|
||||
release_fn(xx b, sel_release);
|
||||
}
|
||||
inline if OS != .macos {
|
||||
|
||||
@@ -21,7 +21,7 @@ UIApplicationMain :: (argc: i32, argv: *void, principal_class: *NSString, delega
|
||||
// IMP for application:didFinishLaunchingWithOptions:
|
||||
// Obj-C: -(BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)opts
|
||||
// Type encoding: "c@:@@" -- BOOL (signed char), self, _cmd, id, id
|
||||
did_finish_launching :: (self: *void, _cmd: *void, app: *void, opts: *void) -> u8 callconv(.c) {
|
||||
did_finish_launching :: (self: *void, _cmd: *void, app: *void, opts: *void) -> u8 abi(.c) {
|
||||
NSLog(xx "[sx] application:didFinishLaunchingWithOptions: called\n");
|
||||
return 1; // YES
|
||||
}
|
||||
|
||||
@@ -25,14 +25,14 @@ g_window : *void = ---;
|
||||
// AppDelegate's `window` property. iOS queries this getter to discover the
|
||||
// app's key window; without it, the legacy code path creates its own empty
|
||||
// window and ignores anything we configure.
|
||||
window_getter :: (self: *void, _cmd: *void) -> *void callconv(.c) {
|
||||
window_getter :: (self: *void, _cmd: *void) -> *void abi(.c) {
|
||||
return g_window;
|
||||
}
|
||||
window_setter :: (self: *void, _cmd: *void, w: *void) callconv(.c) {
|
||||
window_setter :: (self: *void, _cmd: *void, w: *void) abi(.c) {
|
||||
g_window = w;
|
||||
}
|
||||
|
||||
did_finish_launching :: (self: *void, _cmd: *void, app: *void, opts: *void) -> u8 callconv(.c) {
|
||||
did_finish_launching :: (self: *void, _cmd: *void, app: *void, opts: *void) -> u8 abi(.c) {
|
||||
UIWindow := objc_getClass("UIWindow".ptr);
|
||||
UIViewController := objc_getClass("UIViewController".ptr);
|
||||
UIColor := objc_getClass("UIColor".ptr);
|
||||
@@ -48,10 +48,10 @@ did_finish_launching :: (self: *void, _cmd: *void, app: *void, opts: *void) -> u
|
||||
sel_connected_scenes := sel_registerName("connectedScenes".ptr);
|
||||
sel_any_object := sel_registerName("anyObject".ptr);
|
||||
|
||||
msg_o : (*void, *void) -> *void callconv(.c) = xx objc_msgSend;
|
||||
msg_v : (*void, *void) -> void callconv(.c) = xx objc_msgSend;
|
||||
msg_oo : (*void, *void, *void) -> void callconv(.c) = xx objc_msgSend;
|
||||
msg_ooo : (*void, *void, *void) -> *void callconv(.c) = xx objc_msgSend;
|
||||
msg_o : (*void, *void) -> *void abi(.c) = xx objc_msgSend;
|
||||
msg_v : (*void, *void) -> void abi(.c) = xx objc_msgSend;
|
||||
msg_oo : (*void, *void, *void) -> void abi(.c) = xx objc_msgSend;
|
||||
msg_ooo : (*void, *void, *void) -> *void abi(.c) = xx objc_msgSend;
|
||||
|
||||
// Modern iOS path: get the connected windowScene, then construct the
|
||||
// window via initWithWindowScene: so UIKit auto-sizes it and attaches
|
||||
|
||||
@@ -39,7 +39,7 @@ configure :: () {
|
||||
// IMP for application:didFinishLaunchingWithOptions:
|
||||
// Obj-C: -(BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)opts
|
||||
// Type encoding: "c@:@@" -- BOOL (signed char), self, _cmd, id, id
|
||||
did_finish_launching :: (self: *void, _cmd: *void, app: *void, opts: *void) -> u8 callconv(.c) {
|
||||
did_finish_launching :: (self: *void, _cmd: *void, app: *void, opts: *void) -> u8 abi(.c) {
|
||||
NSLog(xx "[sx-device-probe] launched\n");
|
||||
return 1; // YES
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// PLAN-HTTPZ C2: an sx `callconv(.c)` function passes by name as a
|
||||
// PLAN-HTTPZ C2: an sx `abi(.c)` function passes by name as a
|
||||
// typed C function pointer — libc qsort drives an sx comparator.
|
||||
#import "modules/std.sx";
|
||||
|
||||
clib :: #library "c";
|
||||
qsort :: (base: [*]u8, nel: usize, width: usize, compar: (*void, *void) -> i32 callconv(.c)) extern clib;
|
||||
qsort :: (base: [*]u8, nel: usize, width: usize, compar: (*void, *void) -> i32 abi(.c)) extern clib;
|
||||
|
||||
cmp_i32 :: (a: *void, b: *void) -> i32 callconv(.c) {
|
||||
cmp_i32 :: (a: *void, b: *void) -> i32 abi(.c) {
|
||||
pa : *i32 = xx a;
|
||||
pb : *i32 = xx b;
|
||||
if pa.* < pb.* { return -1; }
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// PLAN-HTTPZ C2: the C->sx re-entry contract. A real OS thread enters
|
||||
// sx through a `callconv(.c)` entry (which has NO implicit context),
|
||||
// sx through a `abi(.c)` entry (which has NO implicit context),
|
||||
// fabricates its own Context via `push Context.{ allocator = xx gpa }`,
|
||||
// and calls default-conv sx code that allocates through it.
|
||||
#import "modules/std.sx";
|
||||
|
||||
clib :: #library "c";
|
||||
pthread_create :: (thread: *usize, attr: *void, start: (*void) -> *void callconv(.c), arg: *void) -> i32 extern clib;
|
||||
pthread_create :: (thread: *usize, attr: *void, start: (*void) -> *void abi(.c), arg: *void) -> i32 extern clib;
|
||||
pthread_join :: (thread: usize, retval: **void) -> i32 extern clib;
|
||||
|
||||
entry :: (arg: *void) -> *void callconv(.c) {
|
||||
entry :: (arg: *void) -> *void abi(.c) {
|
||||
p : *i64 = xx arg;
|
||||
gpa := GPA.init();
|
||||
push Context.{ allocator = xx gpa } {
|
||||
|
||||
@@ -11,7 +11,7 @@ Shared :: struct {
|
||||
}
|
||||
|
||||
// Raw-thread entry: C->sx boundary, own fabricated context.
|
||||
bump_entry :: (arg: *void) -> *void callconv(.c) {
|
||||
bump_entry :: (arg: *void) -> *void abi(.c) {
|
||||
sh : *Shared = xx arg;
|
||||
gpa := GPA.init();
|
||||
push Context.{ allocator = xx gpa } {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// CALLS BACK into an sx function (`cb`) by its symbol, then returns. For the asm
|
||||
// `bl _cb` to resolve, the sx callback needs EXTERNAL LINKAGE and a stable C
|
||||
// symbol — that is exactly what `export` provides (it also implies the C ABI, so
|
||||
// no hidden context parameter). `callconv(.c)` alone is NOT enough: it sets the
|
||||
// no hidden context parameter). `abi(.c)` alone is NOT enough: it sets the
|
||||
// ABI but leaves the function `internal`, so it is dead-code-eliminated (nothing
|
||||
// in the IR references it — the `bl` is opaque to the optimizer) and `_cb` is
|
||||
// undefined at link. macOS gives `export "cb"` the symbol `_cb` (leading
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
--- void / 0 args ---
|
||||
__invoke :: (block_self: *Block) -> void callconv(.c) { typed_fn : (*void) -> void = xx block_self.sx_fn; typed_fn(block_self.sx_env); } return .{ isa = @_NSConcreteStackBlock, flags = 0, reserved = 0, invoke = xx @__invoke, descriptor = xx @__sx_block_descriptor, sx_env = self.env, sx_fn = self.fn_ptr, };
|
||||
__invoke :: (block_self: *Block) -> void abi(.c) { typed_fn : (*void) -> void = xx block_self.sx_fn; typed_fn(block_self.sx_env); } return .{ isa = @_NSConcreteStackBlock, flags = 0, reserved = 0, invoke = xx @__invoke, descriptor = xx @__sx_block_descriptor, sx_env = self.env, sx_fn = self.fn_ptr, };
|
||||
--- void / bool ---
|
||||
__invoke :: (block_self: *Block, arg0: bool) -> void callconv(.c) { typed_fn : (*void, bool) -> void = xx block_self.sx_fn; typed_fn(block_self.sx_env, arg0); } return .{ isa = @_NSConcreteStackBlock, flags = 0, reserved = 0, invoke = xx @__invoke, descriptor = xx @__sx_block_descriptor, sx_env = self.env, sx_fn = self.fn_ptr, };
|
||||
__invoke :: (block_self: *Block, arg0: bool) -> void abi(.c) { typed_fn : (*void, bool) -> void = xx block_self.sx_fn; typed_fn(block_self.sx_env, arg0); } return .{ isa = @_NSConcreteStackBlock, flags = 0, reserved = 0, invoke = xx @__invoke, descriptor = xx @__sx_block_descriptor, sx_env = self.env, sx_fn = self.fn_ptr, };
|
||||
--- void / i64, string ---
|
||||
__invoke :: (block_self: *Block, arg0: i64, arg1: string) -> void callconv(.c) { typed_fn : (*void, i64, string) -> void = xx block_self.sx_fn; typed_fn(block_self.sx_env, arg0, arg1); } return .{ isa = @_NSConcreteStackBlock, flags = 0, reserved = 0, invoke = xx @__invoke, descriptor = xx @__sx_block_descriptor, sx_env = self.env, sx_fn = self.fn_ptr, };
|
||||
__invoke :: (block_self: *Block, arg0: i64, arg1: string) -> void abi(.c) { typed_fn : (*void, i64, string) -> void = xx block_self.sx_fn; typed_fn(block_self.sx_env, arg0, arg1); } return .{ isa = @_NSConcreteStackBlock, flags = 0, reserved = 0, invoke = xx @__invoke, descriptor = xx @__sx_block_descriptor, sx_env = self.env, sx_fn = self.fn_ptr, };
|
||||
--- i32 / f64 ---
|
||||
__invoke :: (block_self: *Block, arg0: f64) -> i32 callconv(.c) { typed_fn : (*void, f64) -> i32 = xx block_self.sx_fn; return typed_fn(block_self.sx_env, arg0); } return .{ isa = @_NSConcreteStackBlock, flags = 0, reserved = 0, invoke = xx @__invoke, descriptor = xx @__sx_block_descriptor, sx_env = self.env, sx_fn = self.fn_ptr, };
|
||||
__invoke :: (block_self: *Block, arg0: f64) -> i32 abi(.c) { typed_fn : (*void, f64) -> i32 = xx block_self.sx_fn; return typed_fn(block_self.sx_env, arg0); } return .{ isa = @_NSConcreteStackBlock, flags = 0, reserved = 0, invoke = xx @__invoke, descriptor = xx @__sx_block_descriptor, sx_env = self.env, sx_fn = self.fn_ptr, };
|
||||
--- build done ---
|
||||
rt
|
||||
|
||||
1
examples/expected/0625-comptime-weld-struct-field.exit
Normal file
1
examples/expected/0625-comptime-weld-struct-field.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/expected/0625-comptime-weld-struct-field.stderr
Normal file
1
examples/expected/0625-comptime-weld-struct-field.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
1
examples/expected/0625-comptime-weld-struct-field.stdout
Normal file
1
examples/expected/0625-comptime-weld-struct-field.stdout
Normal file
@@ -0,0 +1 @@
|
||||
name=7 ty=3
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
hello, compiler
|
||||
@@ -1,5 +1,5 @@
|
||||
error: call-convention mismatch: 'sx_handler' is declared with default sx convention but the target type expects callconv(.c)
|
||||
--> examples/1104-diagnostics-callconv-mismatch-diagnostic.sx:12:42
|
||||
error: call-convention mismatch: 'sx_handler' is declared with default sx convention but the target type expects abi(.c)
|
||||
--> examples/1104-diagnostics-callconv-mismatch-diagnostic.sx:12:37
|
||||
|
|
||||
12 | fp : (*void) -> *void callconv(.c) = sx_handler;
|
||||
| ^^^^^^^^^^
|
||||
12 | fp : (*void) -> *void abi(.c) = sx_handler;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: welded type 'Field' has 2 field(s) in the compiler library but the declaration has 1
|
||||
--> examples/1183-diagnostics-weld-struct-field-count.sx:12:51
|
||||
|
|
||||
12 | Field :: struct abi(.zig) extern compiler { name: u32; }
|
||||
| ^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: 'not_a_real_compiler_fn' is not a function exported by the 'compiler' library
|
||||
--> examples/1184-diagnostics-weld-fn-unexported.sx:9:1
|
||||
|
|
||||
9 | not_a_real_compiler_fn :: (x: i64) -> i64 abi(.zig) extern compiler;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
error: 'intern' is a comptime-only compiler-library function — it cannot be called at runtime (use it inside #run or a comptime '::')
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1 +1 @@
|
||||
callconv(.c): 42
|
||||
abi(.c): 42
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
Reference in New Issue
Block a user