# emit_intrin2.ludic — the rest of the low-level intrinsics: raw memory, fixed # memory access, pointer arithmetic, stdio, time, and the windowing hooks. # Matches compiler/back/ir_intrin.c. Reached from emit_intrinsic's fall-through. var g_windowed: bool = false # headless by default (games read stdin / dump PPM) var g_target_win: bool = false # a Windows target: the header emits emit_win_prelude and the libSystem declares are skipped # the IR that loads stdout (fd 1) or stderr (fd 2) as a FILE*. macOS names them as # globals; the UCRT hands them out through a function (see emit_win.ludic). function stdstream_rhs(fd: int) -> pointer { if g_target_win { return `call ptr @lp_win_stdio(i32 {itoa(fd)})` } if fd == 2 { return "load ptr, ptr @__stderrp" } return "load ptr, ptr @__stdoutp" } function is_intrinsic2(name: pointer) -> bool { if (name == "free") or (name == "fill") { return true } if (name == "offset") or (name == "read_char") { return true } if (name == "as_fixed") or (name == "as_int") { return true } if (name == "is_windowed") or (name == "game_title") { return true } if (name == "win_open") or (name == "win_poll") or (name == "win_present") { return true } if (name == "win_running") or (name == "win_close") { return true } if (name == "win_held") or (name == "win_mouse") { return true } # #50 device layer if (name == "win_key_char") { return true } # Input.key_label if (name == "win_pad") or (name == "win_touch") { return true } # #51 gamepad / touch if (name == "win_cursor_mode") { return true } # #89 cursor capture if (name == "snd_load") or (name == "snd_play") or (name == "snd_stop") { return true } # #22 audio if (name == "snd_playing") or (name == "snd_set_volume") or (name == "snd_set_rate") or (name == "snd_set_pan") { return true } if (name == "hs_req_new") or (name == "hs_req_header") or (name == "hs_req_body") { return true } # #6 HTTP if (name == "hs_send") or (name == "hs_done") or (name == "hs_status") or (name == "hs_body") { return true } if (name == "hs_blen") or (name == "hs_header") or (name == "hs_free") { return true } return false } function emit_intrinsic2(name: pointer, e: Node) -> Val { if (name == "free") { let p = arg_code(e, 0); emit(" call void @free(ptr "); emit(p); emit(")\n"); return val("0", "void") } if (name == "fill") { let p = arg_code(e, 0); let v = arg_code(e, 1); let n = arg_code(e, 2) let w = emit_bind(`zext i32 {n} to i64`) emit(" call ptr @memset(ptr "); emit(p); emit(", i32 "); emit(v); emit(", i64 "); emit(w); emit(")\n") return val("0", "void") } if (name == "offset") { let p = arg_code(e, 0); let n = arg_code(e, 1) let g = nreg() emit(" "); emit(g); emit(" = getelementptr inbounds i8, ptr "); emit(p); emit(", i32 "); emit(n); emit("\n") return val(g, "pointer") } if (name == "read_char") { return val(emit_bind("call i32 @getchar()"), "int") } if (name == "as_fixed") { let a = emit_expr(e.kids[0]); return val(a.code, "fixed") } if (name == "as_int") { let a = emit_expr(e.kids[0]); return val(a.code, "int") } if (name == "is_windowed") { if g_windowed { return val("1", "bool") }; return val("0", "bool") } if (name == "game_title") { return val("@.gametitle", "string") } # windowing hooks — declared external; only reached on the is_windowed() branch if (name == "win_poll") { return val(emit_bind("call i32 @win_poll()"), "int") } if (name == "win_running") { return val(emit_bind("call i32 @win_running()"), "bool") } if (name == "win_open") { let a = arg_code(e, 0); let b = arg_code(e, 1); let c = arg_code(e, 2); let d = arg_code(e, 3) emit(" call void @win_open(i32 "); emit(a); emit(", i32 "); emit(b); emit(", i32 "); emit(c); emit(", ptr "); emit(d); emit(")\n") return val("0", "void") } if (name == "win_present") { let a = arg_code(e, 0); let b = arg_code(e, 1); let c = arg_code(e, 2) emit(" call void @win_present(ptr "); emit(a); emit(", i32 "); emit(b); emit(", i32 "); emit(c); emit(")\n") return val("0", "void") } if (name == "win_close") { emit(" call void @win_close()\n"); return val("0", "void") } # #50 — fill a caller buffer with the platform device state (windowed only, # DCE'd headless). win_held: an 8-word held-key bitset; win_mouse: [x, y, # button-mask, wheel-delta]. if (name == "win_held") { let a = arg_code(e, 0); emit(" call void @win_held(ptr "); emit(a); emit(")\n"); return val("0", "void") } if (name == "win_mouse") { let a = arg_code(e, 0); emit(" call void @win_mouse(ptr "); emit(a); emit(")\n"); return val("0", "void") } # what the active keyboard layout types on a held-set key position (windowed only, # DCE'd headless): a code point, 0 for none. if (name == "win_key_char") { let a = arg_code(e, 0); return val(emit_bind(`call i32 @win_key_char(i32 {a})`), "int") } # #51 — win_pad: 6 words/pad [connected, mask, lx, ly, rx, ry]; win_touch: 3 # words/point [active, x, y]. Both windowed-only, DCE'd headless. if (name == "win_pad") { let a = arg_code(e, 0); emit(" call void @win_pad(ptr "); emit(a); emit(")\n"); return val("0", "void") } if (name == "win_touch") { let a = arg_code(e, 0); emit(" call void @win_touch(ptr "); emit(a); emit(")\n"); return val("0", "void") } # #89 — set the OS cursor capture mode (windowed only; DCE'd headless). if (name == "win_cursor_mode") { let a = arg_code(e, 0); emit(" call void @win_cursor_mode(i32 "); emit(a); emit(")\n"); return val("0", "void") } # #22 audio backend — AVAudioPlayer via audio.ll; windowed-only, DCE'd headless. if (name == "snd_load") { let a = arg_code(e, 0); return val(emit_bind(`call ptr @snd_load(ptr {a})`), "pointer") } if (name == "snd_play") { let a = arg_code(e, 0); let b = arg_code(e, 1); let c = arg_code(e, 2); let d = arg_code(e, 3) emit(" call void @snd_play(ptr "); emit(a); emit(", i32 "); emit(b); emit(", i32 "); emit(c); emit(", i32 "); emit(d); emit(")\n"); return val("0", "void") } if (name == "snd_stop") { let a = arg_code(e, 0); emit(" call void @snd_stop(ptr "); emit(a); emit(")\n"); return val("0", "void") } if (name == "snd_playing") { let a = arg_code(e, 0); return val(emit_bind(`call i32 @snd_playing(ptr {a})`), "int") } if (name == "snd_set_volume") { let a = arg_code(e, 0); let b = arg_code(e, 1); emit(" call void @snd_set_volume(ptr "); emit(a); emit(", i32 "); emit(b); emit(")\n"); return val("0", "void") } if (name == "snd_set_rate") { let a = arg_code(e, 0); let b = arg_code(e, 1); emit(" call void @snd_set_rate(ptr "); emit(a); emit(", i32 "); emit(b); emit(")\n"); return val("0", "void") } if (name == "snd_set_pan") { let a = arg_code(e, 0); let b = arg_code(e, 1); emit(" call void @snd_set_pan(ptr "); emit(a); emit(", i32 "); emit(b); emit(")\n"); return val("0", "void") } # #6 HTTP transport — NSURLConnection on a background thread (http.ll). if (name == "hs_req_new") { let a = arg_code(e, 0); let b = arg_code(e, 1); return val(emit_bind(`call ptr @hs_req_new(ptr {a}, ptr {b})`), "pointer") } if (name == "hs_req_header") { let a = arg_code(e, 0); let b = arg_code(e, 1); let c = arg_code(e, 2); emit(" call void @hs_req_header(ptr "); emit(a); emit(", ptr "); emit(b); emit(", ptr "); emit(c); emit(")\n"); return val("0", "void") } if (name == "hs_req_body") { let a = arg_code(e, 0); let b = arg_code(e, 1); let c = arg_code(e, 2); emit(" call void @hs_req_body(ptr "); emit(a); emit(", ptr "); emit(b); emit(", i32 "); emit(c); emit(")\n"); return val("0", "void") } if (name == "hs_send") { let a = arg_code(e, 0); let b = arg_code(e, 1); emit(" call void @hs_send(i32 "); emit(a); emit(", ptr "); emit(b); emit(")\n"); return val("0", "void") } if (name == "hs_done") { let a = arg_code(e, 0); return val(emit_bind(`call i32 @hs_done(i32 {a})`), "int") } if (name == "hs_status") { let a = arg_code(e, 0); return val(emit_bind(`call i32 @hs_status(i32 {a})`), "int") } if (name == "hs_body") { let a = arg_code(e, 0); return val(emit_bind(`call ptr @hs_body(i32 {a})`), "pointer") } if (name == "hs_blen") { let a = arg_code(e, 0); return val(emit_bind(`call i32 @hs_blen(i32 {a})`), "int") } if (name == "hs_header") { let a = arg_code(e, 0); let b = arg_code(e, 1); return val(emit_bind(`call ptr @hs_header(i32 {a}, ptr {b})`), "pointer") } if (name == "hs_free") { let a = arg_code(e, 0); emit(" call void @hs_free(i32 "); emit(a); emit(")\n"); return val("0", "void") } return val("0", "void") }