The JIT that runs makepad apps from source: lexer, front end, type checker, lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and warm/cold caches keyed by compiler stamp, provided crates bound late, startup images, live patching. User-facing name is `makepad run` (binary `makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal library name. `makepad check` reports rustc-style diagnostics with rustc error codes and checks a whole workspace (`--workspace`). Runs on macOS, Linux, Windows and Android. makepad-remote: one tool schema for apps and the WM (app/1): grabs, captures, traces, frame profiles and tweaks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
113 lines
4.4 KiB
Rust
113 lines
4.4 KiB
Rust
// Narrow integer results (i8, i16, i32, u8, u16, bool) of C functions, called directly
|
|
// and through `extern "C" fn` pointers (from the libc symbol and from Relax's own
|
|
// `extern "C"` bodies): C leaves the upper register bits undefined, so the caller must
|
|
// re-extend them. Output matches rustc.
|
|
|
|
extern "C" {
|
|
fn abs(x: i32) -> i32;
|
|
fn atoi(s: *const u8) -> i32;
|
|
fn strtol(s: *const u8, end: *mut *const u8, base: i32) -> i64;
|
|
// libc functions as pointers, the way std's sys layer gets optional APIs
|
|
#[link_name = "dlsym"]
|
|
fn dlsym_atoi(h: *mut u8, name: *const u8) -> unsafe extern "C" fn(*const u8) -> i32;
|
|
#[link_name = "dlsym"]
|
|
fn dlsym_abs(h: *mut u8, name: *const u8) -> unsafe extern "C" fn(i32) -> i32;
|
|
// syscall wrappers typically return -1 in a 32-bit register (upper bits zero)
|
|
#[link_name = "dlsym"]
|
|
fn dlsym_close(h: *mut u8, name: *const u8) -> unsafe extern "C" fn(i32) -> i32;
|
|
#[link_name = "dlsym"]
|
|
fn dlsym_dup(h: *mut u8, name: *const u8) -> unsafe extern "C" fn(i32) -> i32;
|
|
fn close(fd: i32) -> i32;
|
|
fn dlsym(h: *mut u8, name: *const u8) -> *mut u8;
|
|
}
|
|
|
|
type IntFn = unsafe extern "C" fn(i32) -> i32;
|
|
type WakeFn = unsafe extern "C" fn(*mut u8, usize, u32) -> i32;
|
|
|
|
static mut WORD: u32 = 0;
|
|
|
|
/// os_sync_wake_by_address_any with no waiter returns -1 in w0 (x0's upper half zero).
|
|
#[cfg(target_os = "macos")]
|
|
fn os_sync_line() {
|
|
let raw = unsafe { dlsym(RTLD_DEFAULT as *mut u8, cstr("os_sync_wake_by_address_any\0")) } as usize;
|
|
if raw == 0 {
|
|
println!("os_sync -1 true");
|
|
return;
|
|
}
|
|
let wake: WakeFn = unsafe { core::mem::transmute(raw) };
|
|
let r = unsafe { wake(&mut WORD as *mut u32 as *mut u8, 4, 0) };
|
|
println!("os_sync {} {}", r, r < 0);
|
|
}
|
|
|
|
#[cfg(not(target_os = "macos"))]
|
|
fn os_sync_line() {
|
|
println!("os_sync -1 true");
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
const RTLD_DEFAULT: isize = -2;
|
|
#[cfg(not(target_os = "macos"))]
|
|
const RTLD_DEFAULT: isize = 0;
|
|
|
|
// C bodies whose results have garbage-prone upper bits after their own arithmetic
|
|
extern "C" fn neg_i8(x: i32) -> i8 {
|
|
(0 - x) as i8
|
|
}
|
|
extern "C" fn neg_i16(x: i32) -> i16 {
|
|
(0 - x) as i16
|
|
}
|
|
extern "C" fn neg_i32(x: i64) -> i32 {
|
|
(0 - x) as i32
|
|
}
|
|
extern "C" fn trunc_u8(x: i32) -> u8 {
|
|
x as u8
|
|
}
|
|
extern "C" fn trunc_u16(x: i32) -> u16 {
|
|
x as u16
|
|
}
|
|
extern "C" fn is_neg(x: i32) -> bool {
|
|
x < 0
|
|
}
|
|
|
|
fn via_ptr_i32(f: extern "C" fn(i64) -> i32, x: i64) -> i64 {
|
|
f(x) as i64
|
|
}
|
|
|
|
fn cstr(s: &str) -> *const u8 {
|
|
s as *const str as *const u8
|
|
}
|
|
|
|
#[test]
|
|
fn direct_and_pointer_narrow_returns() {
|
|
let a = unsafe { atoi(cstr("-1\0")) };
|
|
let b = unsafe { abs(-7) };
|
|
println!("direct {} {} {}", a, b, unsafe { strtol(cstr("-42\0"), 0 as *mut *const u8, 10) });
|
|
let p_atoi = unsafe { dlsym_atoi(RTLD_DEFAULT as *mut u8, cstr("atoi\0")) };
|
|
let p_abs = unsafe { dlsym_abs(RTLD_DEFAULT as *mut u8, cstr("abs\0")) };
|
|
let c = unsafe { p_atoi(cstr("-1\0")) };
|
|
let d = unsafe { p_atoi(cstr("-2147483648\0")) };
|
|
println!("ptr libc {} {} {} {}", c, d, unsafe { p_abs(-5) }, c < 0);
|
|
let p_close = unsafe { dlsym_close(RTLD_DEFAULT as *mut u8, cstr("close\0")) };
|
|
let p_dup = unsafe { dlsym_dup(RTLD_DEFAULT as *mut u8, cstr("dup\0")) };
|
|
let e1 = unsafe { p_close(-1) };
|
|
let e2 = unsafe { p_dup(-5) };
|
|
let e3 = unsafe { close(-1) };
|
|
println!("ptr syscall {} {} direct {} {} {}", e1, e2, e3, e1 < 0, e1 == -1);
|
|
// an untyped dlsym result transmuted to a fn pointer type (std's sys-layer pattern)
|
|
let raw = unsafe { dlsym(RTLD_DEFAULT as *mut u8, cstr("close\0")) } as usize;
|
|
let t_close: IntFn = unsafe { core::mem::transmute(raw) };
|
|
let e4 = unsafe { t_close(-1) };
|
|
println!("transmuted {} {} {}", e4, e4 < 0, e4 == -1);
|
|
os_sync_line();
|
|
let f8: extern "C" fn(i32) -> i8 = neg_i8;
|
|
let f16: extern "C" fn(i32) -> i16 = neg_i16;
|
|
let f32_: extern "C" fn(i64) -> i32 = neg_i32;
|
|
let fu8: extern "C" fn(i32) -> u8 = trunc_u8;
|
|
let fu16: extern "C" fn(i32) -> u16 = trunc_u16;
|
|
let fb: extern "C" fn(i32) -> bool = is_neg;
|
|
println!("ptr i8 {} {} i16 {} {}", f8(1), f8(-200), f16(1), f16(40000));
|
|
println!("ptr i32 {} {} {}", f32_(1), f32_(-2147483648), via_ptr_i32(neg_i32, 5));
|
|
println!("ptr u8 {} {} u16 {} {}", fu8(-1), fu8(300), fu16(-1), fu16(70000));
|
|
println!("ptr bool {} {} {}", fb(-3), fb(3), fb(-3) as i32 + fb(3) as i32);
|
|
println!("direct bodies {} {} {}", neg_i8(1), neg_i32(7), is_neg(-1));
|
|
}
|