feat(windows): a window - win32.ll, WGL on it, and a windowed Windows build
win32.ll implements cocoa.ll's contracts over user32 and xinput: the message pump, the held-key set and frame key in Ludic codes, the mouse with raw input for cursor mode 2, clip-based cursor modes released on focus loss, XInput pads, and the software framebuffer present. win32_gl.ll puts the WGL 4.1 core context on that window (vsync, borderless full screen); gl_win.ll's context code is now lgl_wgl_core, shared with the headless hidden window, whose win_gl_* stubs move to gl_win_nowin.ll. audio_win.ll links Audio.* silently for now. Verified: macOS fixpoint, ludic-dev test 135/135, selfhost-test 32/32; on the PC gl_triangle renders identically headless and in a real window, and Maroon Lake builds windowed and runs a playtest to frame 240 in the desktop session. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
1bc255bc40
commit
00d25dcc3e
8 changed files with 1696 additions and 442 deletions
|
|
@ -16,8 +16,15 @@ type: feat
|
|||
- **The driver** — finds `C:\Program Files\LLVM\bin\clang.exe` when clang is not on
|
||||
`%PATH%`, writes `.exe` outputs, speaks cmd.exe for its directory and cleanup commands,
|
||||
and reads `argv[0]`, `%PATH%` and `$LUDIC_HOME` with either separator.
|
||||
- **Not yet** — a window, `Audio.*` and `Http.*` are still macOS platform layers;
|
||||
a Windows build that needs one stops with a message saying so.
|
||||
- **A window** — `win32.ll` is `cocoa.ll`'s contract over user32: the held-key set and frame
|
||||
key in Ludic codes, the mouse in framebuffer pixels with raw input for cursor mode 2,
|
||||
cursor hide/lock/confine that lets go when the window loses the foreground, XInput pads
|
||||
in SDL order with rescaled deadzones, and the software `win_present`. `win32_gl.ll` puts
|
||||
the WGL context on that window with vsync and borderless full screen; a headless build
|
||||
links `gl_win_nowin.ll` instead. The process is per-monitor DPI aware.
|
||||
- **Not yet** — `Audio.*` links and is silent (`audio_win.ll`), the splash and
|
||||
`App.set_icon` do nothing, and `Http.*` is still a macOS platform layer; a Windows build
|
||||
that uses it stops with a message saying so.
|
||||
- **`Gl.*` on Windows** — `gl_win.ll` makes a WGL 4.1 core context on a hidden window's DC,
|
||||
and `gl_thunks_win.ll` (generated by `ludic-dev glgen` beside `gl_thunks.ll`) calls
|
||||
every entry point through a table `@lgl_win_load` fills from `wglGetProcAddress`, falling
|
||||
|
|
|
|||
36
runtime/native/audio_win.ll
Normal file
36
runtime/native/audio_win.ll
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
; ============================================================================
|
||||
; audio_win.ll — the Windows sound backend (audio.ll's snd_* contract).
|
||||
;
|
||||
; Silent for now: every clip fails to load and every call is a no-op, which is the
|
||||
; contract a headless build already runs on, so a windowed game links and plays
|
||||
; without sound until the XAudio2 backend replaces this file.
|
||||
; ============================================================================
|
||||
|
||||
define ptr @snd_load(ptr %path) {
|
||||
entry:
|
||||
ret ptr null
|
||||
}
|
||||
define void @snd_play(ptr %p, i32 %loops, i32 %rate, i32 %vol) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @snd_stop(ptr %p) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define i32 @snd_playing(ptr %p) {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
define void @snd_set_volume(ptr %p, i32 %vol) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @snd_set_rate(ptr %p, i32 %rate) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @snd_set_pan(ptr %p, i32 %pan) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
|
@ -54,25 +54,16 @@ declare float @llvm.fabs.f32(float)
|
|||
@.wgl_attrs = private unnamed_addr constant [7 x i32] [i32 8337, i32 4, i32 8338, i32 1, i32 37158, i32 1, i32 0]
|
||||
|
||||
@L_wgl_hwnd = internal global ptr null
|
||||
@L_wgl_hdc = internal global ptr null
|
||||
@L_wgl_ctx = internal global ptr null
|
||||
|
||||
define i32 @cgl_offscreen() {
|
||||
; lgl_wgl_core(hdc, alpha bits) -> context: a pixel format on the DC, a legacy context
|
||||
; (wglCreateContextAttribsARB is only reachable through one), the 4.1 core context made
|
||||
; current in its place, and the entry-point table filled. Null when any step fails.
|
||||
; Shared by cgl_offscreen (a hidden window) and win32_gl.ll (the game's window).
|
||||
define ptr @lgl_wgl_core(ptr %hdc, i32 %alpha) {
|
||||
entry:
|
||||
%cur = load ptr, ptr @L_wgl_ctx
|
||||
%have = icmp ne ptr %cur, null
|
||||
br i1 %have, label %ok, label %win
|
||||
win:
|
||||
; WS_POPUP, never shown
|
||||
%w = call ptr @CreateWindowExA(i32 0, ptr @.wgl_class, ptr @.wgl_title, i32 -2147483648, i32 0, i32 0, i32 16, i32 16, ptr null, ptr null, ptr null, ptr null)
|
||||
%wn = icmp eq ptr %w, null
|
||||
br i1 %wn, label %fail, label %pf
|
||||
pf:
|
||||
store ptr %w, ptr @L_wgl_hwnd
|
||||
%hdc = call ptr @GetDC(ptr %w)
|
||||
store ptr %hdc, ptr @L_wgl_hdc
|
||||
; PIXELFORMATDESCRIPTOR: nSize 40, nVersion 1, PFD_DRAW_TO_WINDOW|SUPPORT_OPENGL|DOUBLEBUFFER,
|
||||
; 32-bit colour, 24 depth, 8 stencil
|
||||
; 32-bit colour, alpha at 16, 24 depth, 8 stencil
|
||||
%pfd = alloca [40 x i8], align 4
|
||||
call void @llvm.memset.p0.i64(ptr %pfd, i8 0, i64 40, i1 false)
|
||||
store i16 40, ptr %pfd
|
||||
|
|
@ -82,6 +73,9 @@ pf:
|
|||
store i32 37, ptr %fl
|
||||
%cb = getelementptr i8, ptr %pfd, i64 9
|
||||
store i8 32, ptr %cb
|
||||
%ab = getelementptr i8, ptr %pfd, i64 16
|
||||
%a8 = trunc i32 %alpha to i8
|
||||
store i8 %a8, ptr %ab
|
||||
%db = getelementptr i8, ptr %pfd, i64 23
|
||||
store i8 24, ptr %db
|
||||
%sb = getelementptr i8, ptr %pfd, i64 24
|
||||
|
|
@ -91,7 +85,6 @@ pf:
|
|||
%setz = icmp eq i32 %set, 0
|
||||
br i1 %setz, label %fail, label %legacy
|
||||
legacy:
|
||||
; a legacy context first: wglCreateContextAttribsARB is only reachable through one
|
||||
%old = call ptr @wglCreateContext(ptr %hdc)
|
||||
%oldn = icmp eq ptr %old, null
|
||||
br i1 %oldn, label %fail, label %arb
|
||||
|
|
@ -108,13 +101,35 @@ core:
|
|||
use:
|
||||
%m2 = call i32 @wglMakeCurrent(ptr %hdc, ptr %ctx)
|
||||
%d1 = call i32 @wglDeleteContext(ptr %old)
|
||||
store ptr %ctx, ptr @L_wgl_ctx
|
||||
%n = call i32 @lgl_win_load()
|
||||
br label %ok
|
||||
ret ptr %ctx
|
||||
drop:
|
||||
%m3 = call i32 @wglMakeCurrent(ptr null, ptr null)
|
||||
%d2 = call i32 @wglDeleteContext(ptr %old)
|
||||
br label %fail
|
||||
fail:
|
||||
ret ptr null
|
||||
}
|
||||
|
||||
define i32 @cgl_offscreen() {
|
||||
entry:
|
||||
%cur = load ptr, ptr @L_wgl_ctx
|
||||
%have = icmp ne ptr %cur, null
|
||||
br i1 %have, label %ok, label %win
|
||||
win:
|
||||
; WS_POPUP, never shown
|
||||
%w = call ptr @CreateWindowExA(i32 0, ptr @.wgl_class, ptr @.wgl_title, i32 -2147483648, i32 0, i32 0, i32 16, i32 16, ptr null, ptr null, ptr null, ptr null)
|
||||
%wn = icmp eq ptr %w, null
|
||||
br i1 %wn, label %fail, label %ctx
|
||||
ctx:
|
||||
store ptr %w, ptr @L_wgl_hwnd
|
||||
%hdc = call ptr @GetDC(ptr %w)
|
||||
%c = call ptr @lgl_wgl_core(ptr %hdc, i32 0)
|
||||
%cn = icmp eq ptr %c, null
|
||||
br i1 %cn, label %fail, label %keep
|
||||
keep:
|
||||
store ptr %c, ptr @L_wgl_ctx
|
||||
br label %ok
|
||||
ok:
|
||||
ret i32 1
|
||||
fail:
|
||||
|
|
@ -415,44 +430,3 @@ entry:
|
|||
%t = add i64 %sus, %frac
|
||||
ret i64 %t
|
||||
}
|
||||
|
||||
; ---- the window half, until there is one ------------------------------------
|
||||
; gl.ludic names these on its is_windowed() branch. A headless build compiles that
|
||||
; branch to nothing, but the names still have to resolve; a windowed Windows
|
||||
; build will define them in the Win32 platform layer instead of here.
|
||||
define i32 @win_gl_attach() {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
define void @win_gl_resize(i32 %w, i32 %h) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_gl_swap() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define i32 @win_gl_scale() {
|
||||
entry:
|
||||
ret i32 1
|
||||
}
|
||||
define void @win_gl_swap_interval(i32 %n) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_gl_drawable(ptr %out) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_gl_update() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_gl_retina(i32 %on) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_toggle_fullscreen() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
|
|
|||
44
runtime/native/gl_win_nowin.ll
Normal file
44
runtime/native/gl_win_nowin.ll
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
; ============================================================================
|
||||
; gl_win_nowin.ll — the window half of Gl.* in a headless Windows build.
|
||||
;
|
||||
; gl.ludic names win_gl_* on its is_windowed() branch. A headless build compiles that
|
||||
; branch to nothing, but the names still have to resolve; a windowed build links
|
||||
; win32_gl.ll, which defines them on the real window, in place of this file.
|
||||
; ============================================================================
|
||||
|
||||
define i32 @win_gl_attach() {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
define void @win_gl_resize(i32 %w, i32 %h) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_gl_swap() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define i32 @win_gl_scale() {
|
||||
entry:
|
||||
ret i32 1
|
||||
}
|
||||
define void @win_gl_swap_interval(i32 %n) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_gl_drawable(ptr %out) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_gl_update() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_gl_retina(i32 %on) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @win_toggle_fullscreen() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
867
runtime/native/win32.ll
Normal file
867
runtime/native/win32.ll
Normal file
|
|
@ -0,0 +1,867 @@
|
|||
; ============================================================================
|
||||
; win32.ll — the Windows window, written in LLVM IR.
|
||||
;
|
||||
; The counterpart of cocoa.ll, to the same contracts, spoken to user32 and
|
||||
; xinput through their C ABI. ludicc links it into a windowed Windows binary;
|
||||
; the GL half (win_gl_*) is win32_gl.ll, linked only when the program uses Gl.*,
|
||||
; so a software-framebuffer game never names a WGL function.
|
||||
;
|
||||
; win_open(w, h, scale, title) win_poll() -> key win_present(fb, w, h)
|
||||
; win_running() -> bool win_close()
|
||||
; win_held(out) win_mouse(out) win_pad(out) win_touch(out) win_cursor_mode(m)
|
||||
; splash_show(bytes, len, bg) splash_hide() app_set_icon(bytes, len)
|
||||
;
|
||||
; Units and conventions carried over from cocoa.ll, because the Ludic side reads
|
||||
; them without knowing which platform filled them:
|
||||
;
|
||||
; held keys a 256-bit set of Ludic key codes: letters lowercase, digits and
|
||||
; punctuation as their unshifted character, Space 32, Enter 10,
|
||||
; Esc 27, Backspace 8, Tab 9, Shift 16, Ctrl 17, Alt 18, and the
|
||||
; arrows at 128 129 130 131 (up down left right)
|
||||
; frame key the last key pressed this frame, arrows reported as w s a d
|
||||
; mouse framebuffer pixels (client pixels / scale), top-left origin;
|
||||
; buttons bit0 left, bit1 right; wheel in notches, up positive
|
||||
; pads SDL button order, Q16.16 axes with Y down
|
||||
;
|
||||
; The process is per-monitor DPI aware: a client pixel is a screen pixel, the
|
||||
; backing scale is 1, and a 1280x720 window is 1280x720 pixels on any display.
|
||||
;
|
||||
; Keys are read from the message queue before dispatch rather than from WM_CHAR:
|
||||
; TranslateMessage is never called, so no character messages are produced, and a
|
||||
; key's character comes from MapVirtualKeyA. The system keys (Alt, F10) are never
|
||||
; handed to DefWindowProc, whose menu loop would stall the game's frame loop -
|
||||
; Alt+F4 is honoured here instead.
|
||||
; ============================================================================
|
||||
|
||||
declare ptr @GetModuleHandleA(ptr)
|
||||
declare i16 @RegisterClassExA(ptr)
|
||||
declare ptr @CreateWindowExA(i32, ptr, ptr, i32, i32, i32, i32, i32, ptr, ptr, ptr, ptr)
|
||||
declare i64 @DefWindowProcA(ptr, i32, i64, i64)
|
||||
declare i32 @ShowWindow(ptr, i32)
|
||||
declare i32 @SetForegroundWindow(ptr)
|
||||
declare i32 @PeekMessageA(ptr, ptr, i32, i32, i32)
|
||||
declare i64 @DispatchMessageA(ptr)
|
||||
declare ptr @GetDC(ptr)
|
||||
declare i32 @AdjustWindowRectEx(ptr, i32, i32, i32)
|
||||
declare i32 @GetSystemMetrics(i32)
|
||||
declare i32 @GetClientRect(ptr, ptr)
|
||||
declare i32 @ClientToScreen(ptr, ptr)
|
||||
declare i32 @ScreenToClient(ptr, ptr)
|
||||
declare i32 @GetCursorPos(ptr)
|
||||
declare i32 @ClipCursor(ptr)
|
||||
declare ptr @SetCursor(ptr)
|
||||
declare ptr @LoadCursorA(ptr, ptr)
|
||||
declare ptr @GetForegroundWindow()
|
||||
declare i32 @IsWindow(ptr)
|
||||
declare ptr @SetCapture(ptr)
|
||||
declare i32 @ReleaseCapture()
|
||||
declare i32 @MapVirtualKeyA(i32, i32)
|
||||
declare i16 @GetKeyState(i32)
|
||||
declare i32 @RegisterRawInputDevices(ptr, i32, i32)
|
||||
declare i32 @GetRawInputData(ptr, i32, ptr, ptr, i32)
|
||||
declare i32 @SetProcessDpiAwarenessContext(ptr)
|
||||
declare i32 @StretchDIBits(ptr, i32, i32, i32, i32, i32, i32, i32, i32, ptr, ptr, i32, i32)
|
||||
declare void @Sleep(i32)
|
||||
declare i32 @XInputGetState(i32, ptr)
|
||||
declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)
|
||||
|
||||
@.w_class = private unnamed_addr constant [12 x i8] c"LudicWindow\00"
|
||||
|
||||
; shared with win32_gl.ll, which declares them external
|
||||
@W_hwnd = global ptr null
|
||||
@W_hdc = global ptr null
|
||||
@W_fbw = global i32 320
|
||||
@W_fbh = global i32 240
|
||||
@W_scale = global i32 3
|
||||
|
||||
@W_fb = internal global ptr null
|
||||
@W_key = internal global i32 0
|
||||
@W_running = internal global i32 1
|
||||
@W_held = internal global [8 x i32] zeroinitializer
|
||||
@W_mx = internal global i32 0
|
||||
@W_my = internal global i32 0
|
||||
@W_mbtn = internal global i32 0
|
||||
@W_wheel = internal global i32 0
|
||||
; raw mouse motion since the last win_mouse, for cursor mode 2
|
||||
@W_rawdx = internal global i32 0
|
||||
@W_rawdy = internal global i32 0
|
||||
; 0 normal, 1 hidden, 2 locked (relative), 3 confined; see win_cursor_maintain
|
||||
@W_cursor_mode = internal global i32 0
|
||||
@W_cursor_hidden = internal global i32 0
|
||||
@W_clipped = internal global i32 0
|
||||
|
||||
; ---- the window procedure ---------------------------------------------------
|
||||
; Only what is SENT to a window arrives here (posted input is read in win_poll).
|
||||
define internal i64 @ludic_wndproc(ptr %hwnd, i32 %msg, i64 %wp, i64 %lp) {
|
||||
entry:
|
||||
switch i32 %msg, label %def [
|
||||
i32 16, label %close ; WM_CLOSE: end the run; the game decides what quitting does
|
||||
i32 20, label %erase ; WM_ERASEBKGND: the frame covers it, and erasing flickers
|
||||
i32 8, label %blur ; WM_KILLFOCUS
|
||||
i32 32, label %setcur ; WM_SETCURSOR
|
||||
]
|
||||
close:
|
||||
store i32 0, ptr @W_running
|
||||
ret i64 0
|
||||
erase:
|
||||
ret i64 1
|
||||
blur:
|
||||
; a key held when focus went away never sends its key-up to this window: drop them all,
|
||||
; or the hiker walks on by himself after an Alt-Tab
|
||||
call void @llvm.memset.p0.i64(ptr @W_held, i8 0, i64 32, i1 false)
|
||||
store i32 0, ptr @W_mbtn
|
||||
br label %def
|
||||
setcur:
|
||||
; a hidden cursor is hidden by answering WM_SETCURSOR with no cursor over the client
|
||||
; area, which needs no ShowCursor counter to keep balanced
|
||||
%hid = load i32, ptr @W_cursor_hidden
|
||||
%ishid = icmp ne i32 %hid, 0
|
||||
%hit = and i64 %lp, 65535
|
||||
%client = icmp eq i64 %hit, 1 ; HTCLIENT
|
||||
%both = and i1 %ishid, %client
|
||||
br i1 %both, label %nocur, label %def
|
||||
nocur:
|
||||
%c = call ptr @SetCursor(ptr null)
|
||||
ret i64 1
|
||||
def:
|
||||
%r = call i64 @DefWindowProcA(ptr %hwnd, i32 %msg, i64 %wp, i64 %lp)
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
define void @win_open(i32 %w, i32 %h, i32 %scale, ptr %title) {
|
||||
entry:
|
||||
%wc = alloca [80 x i8], align 8
|
||||
%rc = alloca [16 x i8], align 4
|
||||
%rid = alloca [16 x i8], align 8
|
||||
store i32 %w, ptr @W_fbw
|
||||
store i32 %h, ptr @W_fbh
|
||||
store i32 %scale, ptr @W_scale
|
||||
%have = load ptr, ptr @W_hwnd
|
||||
%again = icmp ne ptr %have, null
|
||||
br i1 %again, label %out, label %make
|
||||
make:
|
||||
; DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = -4
|
||||
%dpi = call i32 @SetProcessDpiAwarenessContext(ptr inttoptr (i64 -4 to ptr))
|
||||
%inst = call ptr @GetModuleHandleA(ptr null)
|
||||
; WNDCLASSEXA: cbSize 0, style 4, lpfnWndProc 8, hInstance 24, hCursor 40, lpszClassName 64
|
||||
call void @llvm.memset.p0.i64(ptr %wc, i8 0, i64 80, i1 false)
|
||||
store i32 80, ptr %wc
|
||||
%wst = getelementptr i8, ptr %wc, i64 4
|
||||
store i32 35, ptr %wst ; CS_OWNDC | CS_HREDRAW | CS_VREDRAW
|
||||
%wwp = getelementptr i8, ptr %wc, i64 8
|
||||
store ptr @ludic_wndproc, ptr %wwp
|
||||
%whi = getelementptr i8, ptr %wc, i64 24
|
||||
store ptr %inst, ptr %whi
|
||||
%arrow = call ptr @LoadCursorA(ptr null, ptr inttoptr (i64 32512 to ptr)) ; IDC_ARROW
|
||||
%whc = getelementptr i8, ptr %wc, i64 40
|
||||
store ptr %arrow, ptr %whc
|
||||
%wcn = getelementptr i8, ptr %wc, i64 64
|
||||
store ptr @.w_class, ptr %wcn
|
||||
%atom = call i16 @RegisterClassExA(ptr %wc)
|
||||
; the client area is w*scale x h*scale pixels; the frame goes round it
|
||||
%pw = mul i32 %w, %scale
|
||||
%ph = mul i32 %h, %scale
|
||||
call void @llvm.memset.p0.i64(ptr %rc, i8 0, i64 16, i1 false)
|
||||
%rcr = getelementptr i8, ptr %rc, i64 8
|
||||
store i32 %pw, ptr %rcr
|
||||
%rcb = getelementptr i8, ptr %rc, i64 12
|
||||
store i32 %ph, ptr %rcb
|
||||
%adj = call i32 @AdjustWindowRectEx(ptr %rc, i32 13565952, i32 0, i32 0) ; WS_OVERLAPPEDWINDOW
|
||||
%rl = load i32, ptr %rc
|
||||
%rtp = getelementptr i8, ptr %rc, i64 4
|
||||
%rt = load i32, ptr %rtp
|
||||
%rr = load i32, ptr %rcr
|
||||
%rb = load i32, ptr %rcb
|
||||
%ww = sub i32 %rr, %rl
|
||||
%wh = sub i32 %rb, %rt
|
||||
; centred on the primary display
|
||||
%sw = call i32 @GetSystemMetrics(i32 0)
|
||||
%sh = call i32 @GetSystemMetrics(i32 1)
|
||||
%dx = sub i32 %sw, %ww
|
||||
%x0 = sdiv i32 %dx, 2
|
||||
%xneg = icmp slt i32 %x0, 0
|
||||
%x = select i1 %xneg, i32 0, i32 %x0
|
||||
%dy = sub i32 %sh, %wh
|
||||
%y0 = sdiv i32 %dy, 2
|
||||
%yneg = icmp slt i32 %y0, 0
|
||||
%y = select i1 %yneg, i32 0, i32 %y0
|
||||
; WS_OVERLAPPEDWINDOW | WS_VISIBLE
|
||||
%hwnd = call ptr @CreateWindowExA(i32 0, ptr @.w_class, ptr %title, i32 282001408, i32 %x, i32 %y, i32 %ww, i32 %wh, ptr null, ptr null, ptr %inst, ptr null)
|
||||
%nowin = icmp eq ptr %hwnd, null
|
||||
br i1 %nowin, label %out, label %show
|
||||
show:
|
||||
store ptr %hwnd, ptr @W_hwnd
|
||||
%hdc = call ptr @GetDC(ptr %hwnd)
|
||||
store ptr %hdc, ptr @W_hdc
|
||||
%s1 = call i32 @ShowWindow(ptr %hwnd, i32 5) ; SW_SHOW
|
||||
%s2 = call i32 @SetForegroundWindow(ptr %hwnd)
|
||||
; RAWINPUTDEVICE { usUsagePage 1, usUsage 2 (mouse), dwFlags 0, hwndTarget }: the raw
|
||||
; motion cursor mode 2 turns into mouse_dx / mouse_dy
|
||||
call void @llvm.memset.p0.i64(ptr %rid, i8 0, i64 16, i1 false)
|
||||
store i16 1, ptr %rid
|
||||
%ru = getelementptr i8, ptr %rid, i64 2
|
||||
store i16 2, ptr %ru
|
||||
%rh = getelementptr i8, ptr %rid, i64 8
|
||||
store ptr %hwnd, ptr %rh
|
||||
%reg = call i32 @RegisterRawInputDevices(ptr %rid, i32 1, i32 16)
|
||||
store i32 1, ptr @W_running
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
; set (%on != 0) or clear a key's bit in the 256-bit held set
|
||||
define void @win_held_bit(i32 %k, i32 %on) {
|
||||
entry:
|
||||
%lo = icmp slt i32 %k, 0
|
||||
%hi = icmp sgt i32 %k, 255
|
||||
%oob = or i1 %lo, %hi
|
||||
br i1 %oob, label %ret, label %go
|
||||
go:
|
||||
%w = ashr i32 %k, 5
|
||||
%b = and i32 %k, 31
|
||||
%m = shl i32 1, %b
|
||||
%p = getelementptr [8 x i32], ptr @W_held, i32 0, i32 %w
|
||||
%cur = load i32, ptr %p
|
||||
%onb = icmp ne i32 %on, 0
|
||||
br i1 %onb, label %set, label %clr
|
||||
set:
|
||||
%sv = or i32 %cur, %m
|
||||
store i32 %sv, ptr %p
|
||||
br label %ret
|
||||
clr:
|
||||
%nm = xor i32 %m, -1
|
||||
%cv = and i32 %cur, %nm
|
||||
store i32 %cv, ptr %p
|
||||
br label %ret
|
||||
ret:
|
||||
ret void
|
||||
}
|
||||
|
||||
; the unshifted character a virtual key types, 0 for none (F-keys, Home, ...)
|
||||
define internal i32 @w_vk_char(i32 %vk) {
|
||||
entry:
|
||||
%c = call i32 @MapVirtualKeyA(i32 %vk, i32 2) ; MAPVK_VK_TO_CHAR; the top bit marks a dead key
|
||||
%c7 = and i32 %c, 32767
|
||||
ret i32 %c7
|
||||
}
|
||||
|
||||
; the held-set code of a virtual key (cocoa.ll's ev_keyval)
|
||||
define internal i32 @w_keyval(i64 %vk64) {
|
||||
entry:
|
||||
%vk = trunc i64 %vk64 to i32
|
||||
switch i32 %vk, label %chars [
|
||||
i32 38, label %up
|
||||
i32 40, label %down
|
||||
i32 37, label %left
|
||||
i32 39, label %right
|
||||
i32 32, label %space
|
||||
i32 13, label %enter
|
||||
i32 27, label %esc
|
||||
i32 16, label %shift
|
||||
i32 17, label %ctrl
|
||||
i32 18, label %alt
|
||||
i32 8, label %bksp
|
||||
i32 9, label %tab
|
||||
]
|
||||
up: ret i32 128
|
||||
down: ret i32 129
|
||||
left: ret i32 130
|
||||
right: ret i32 131
|
||||
space: ret i32 32
|
||||
enter: ret i32 10
|
||||
esc: ret i32 27
|
||||
shift: ret i32 16
|
||||
ctrl: ret i32 17
|
||||
alt: ret i32 18
|
||||
bksp: ret i32 8
|
||||
tab: ret i32 9
|
||||
chars:
|
||||
%c = call i32 @w_vk_char(i32 %vk)
|
||||
; the held set is keyed by the key, not the case: fold A-Z (Shift is its own code)
|
||||
%isA = icmp sge i32 %c, 65
|
||||
%isZ = icmp sle i32 %c, 90
|
||||
%upper = and i1 %isA, %isZ
|
||||
%lower = add i32 %c, 32
|
||||
%f = select i1 %upper, i32 %lower, i32 %c
|
||||
ret i32 %f
|
||||
}
|
||||
|
||||
; the frame key of a virtual key (cocoa.ll's win_poll): arrows as wasd, a letter in the
|
||||
; case Shift gives it, and 0 for a key that types nothing
|
||||
define internal i32 @w_framekey(i64 %vk64) {
|
||||
entry:
|
||||
%vk = trunc i64 %vk64 to i32
|
||||
switch i32 %vk, label %chars [
|
||||
i32 38, label %up
|
||||
i32 40, label %down
|
||||
i32 37, label %left
|
||||
i32 39, label %right
|
||||
i32 32, label %space
|
||||
i32 13, label %enter
|
||||
i32 27, label %esc
|
||||
i32 16, label %none
|
||||
i32 17, label %none
|
||||
i32 18, label %none
|
||||
]
|
||||
up: ret i32 119
|
||||
down: ret i32 115
|
||||
left: ret i32 97
|
||||
right: ret i32 100
|
||||
space: ret i32 32
|
||||
enter: ret i32 10
|
||||
esc: ret i32 27
|
||||
none: ret i32 0
|
||||
chars:
|
||||
%c = call i32 @w_vk_char(i32 %vk)
|
||||
%isA = icmp sge i32 %c, 65
|
||||
%isZ = icmp sle i32 %c, 90
|
||||
%upper = and i1 %isA, %isZ
|
||||
%ks = call i16 @GetKeyState(i32 16)
|
||||
%shifted = icmp slt i16 %ks, 0
|
||||
%keepup = and i1 %upper, %shifted
|
||||
%fold = xor i1 %keepup, true
|
||||
%dofold = and i1 %upper, %fold
|
||||
%lower = add i32 %c, 32
|
||||
%f = select i1 %dofold, i32 %lower, i32 %c
|
||||
ret i32 %f
|
||||
}
|
||||
|
||||
; Drain the message queue: keys, buttons, the wheel and raw motion are read here,
|
||||
; everything else is dispatched to the window procedure. Returns the frame key.
|
||||
define i32 @win_poll() {
|
||||
entry:
|
||||
%msg = alloca [48 x i8], align 8 ; MSG: message 8, wParam 16, lParam 24
|
||||
%rbuf = alloca [48 x i8], align 8 ; RAWINPUT (mouse): header 24, RAWMOUSE 24
|
||||
%rsz = alloca i32, align 4
|
||||
store i32 0, ptr @W_key
|
||||
%hwnd = load ptr, ptr @W_hwnd
|
||||
%nohwnd = icmp eq ptr %hwnd, null
|
||||
br i1 %nohwnd, label %done, label %pump
|
||||
pump:
|
||||
%got = call i32 @PeekMessageA(ptr %msg, ptr null, i32 0, i32 0, i32 1) ; PM_REMOVE
|
||||
%any = icmp ne i32 %got, 0
|
||||
br i1 %any, label %handle, label %finish
|
||||
handle:
|
||||
%mp = getelementptr i8, ptr %msg, i64 8
|
||||
%m = load i32, ptr %mp
|
||||
%wpp = getelementptr i8, ptr %msg, i64 16
|
||||
%wp = load i64, ptr %wpp
|
||||
%lpp = getelementptr i8, ptr %msg, i64 24
|
||||
%lp = load i64, ptr %lpp
|
||||
switch i32 %m, label %dispatch [
|
||||
i32 256, label %kdown ; WM_KEYDOWN
|
||||
i32 260, label %kdown ; WM_SYSKEYDOWN
|
||||
i32 257, label %kup ; WM_KEYUP
|
||||
i32 261, label %kup ; WM_SYSKEYUP
|
||||
i32 513, label %ldown ; WM_LBUTTONDOWN
|
||||
i32 514, label %lup ; WM_LBUTTONUP
|
||||
i32 516, label %rdown ; WM_RBUTTONDOWN
|
||||
i32 517, label %rup ; WM_RBUTTONUP
|
||||
i32 522, label %wheel ; WM_MOUSEWHEEL
|
||||
i32 255, label %raw ; WM_INPUT
|
||||
]
|
||||
kdown:
|
||||
%hv = call i32 @w_keyval(i64 %wp)
|
||||
call void @win_held_bit(i32 %hv, i32 1)
|
||||
%isf4 = icmp eq i64 %wp, 115 ; VK_F4
|
||||
%issys = icmp eq i32 %m, 260
|
||||
%altf4 = and i1 %isf4, %issys
|
||||
br i1 %altf4, label %quit, label %fkey
|
||||
quit:
|
||||
store i32 0, ptr @W_running
|
||||
br label %pump
|
||||
fkey:
|
||||
%fk = call i32 @w_framekey(i64 %wp)
|
||||
%hasfk = icmp ne i32 %fk, 0
|
||||
br i1 %hasfk, label %setfk, label %pump
|
||||
setfk:
|
||||
store i32 %fk, ptr @W_key
|
||||
br label %pump
|
||||
kup:
|
||||
%uv = call i32 @w_keyval(i64 %wp)
|
||||
call void @win_held_bit(i32 %uv, i32 0)
|
||||
br label %pump
|
||||
ldown:
|
||||
%lb = load i32, ptr @W_mbtn
|
||||
%lb2 = or i32 %lb, 1
|
||||
store i32 %lb2, ptr @W_mbtn
|
||||
%cap1 = call ptr @SetCapture(ptr %hwnd) ; so the release is seen outside the window too
|
||||
br label %dispatch
|
||||
lup:
|
||||
%lc = load i32, ptr @W_mbtn
|
||||
%lc2 = and i32 %lc, -2
|
||||
store i32 %lc2, ptr @W_mbtn
|
||||
br label %release
|
||||
rdown:
|
||||
%rbn = load i32, ptr @W_mbtn
|
||||
%rbn2 = or i32 %rbn, 2
|
||||
store i32 %rbn2, ptr @W_mbtn
|
||||
%cap2 = call ptr @SetCapture(ptr %hwnd)
|
||||
br label %dispatch
|
||||
rup:
|
||||
%rcn = load i32, ptr @W_mbtn
|
||||
%rcn2 = and i32 %rcn, -3
|
||||
store i32 %rcn2, ptr @W_mbtn
|
||||
br label %release
|
||||
release:
|
||||
%still = load i32, ptr @W_mbtn
|
||||
%nobtn = icmp eq i32 %still, 0
|
||||
br i1 %nobtn, label %uncap, label %dispatch
|
||||
uncap:
|
||||
%rel = call i32 @ReleaseCapture()
|
||||
br label %dispatch
|
||||
wheel:
|
||||
; the high word of wParam is the signed delta, 120 to a notch, positive away from the user
|
||||
%hiw = lshr i64 %wp, 16
|
||||
%d16 = trunc i64 %hiw to i16
|
||||
%d32 = sext i16 %d16 to i32
|
||||
%notches = sdiv i32 %d32, 120
|
||||
%wv = load i32, ptr @W_wheel
|
||||
%wv2 = add i32 %wv, %notches
|
||||
store i32 %wv2, ptr @W_wheel
|
||||
br label %pump
|
||||
raw:
|
||||
%hraw = inttoptr i64 %lp to ptr
|
||||
store i32 48, ptr %rsz
|
||||
%n = call i32 @GetRawInputData(ptr %hraw, i32 268435459, ptr %rbuf, ptr %rsz, i32 24) ; RID_INPUT
|
||||
%okn = icmp sgt i32 %n, 43
|
||||
br i1 %okn, label %rawtype, label %dispatch
|
||||
rawtype:
|
||||
%rtype = load i32, ptr %rbuf
|
||||
%ismouse = icmp eq i32 %rtype, 0 ; RIM_TYPEMOUSE
|
||||
%flp = getelementptr i8, ptr %rbuf, i64 24
|
||||
%fl = load i16, ptr %flp
|
||||
%abs = and i16 %fl, 1 ; MOUSE_MOVE_ABSOLUTE (a tablet, a remote desktop)
|
||||
%isrel = icmp eq i16 %abs, 0
|
||||
%use = and i1 %ismouse, %isrel
|
||||
br i1 %use, label %rawadd, label %dispatch
|
||||
rawadd:
|
||||
%rxp = getelementptr i8, ptr %rbuf, i64 36
|
||||
%rx = load i32, ptr %rxp
|
||||
%ryp = getelementptr i8, ptr %rbuf, i64 40
|
||||
%ry = load i32, ptr %ryp
|
||||
%ax = load i32, ptr @W_rawdx
|
||||
%ax2 = add i32 %ax, %rx
|
||||
store i32 %ax2, ptr @W_rawdx
|
||||
%ay = load i32, ptr @W_rawdy
|
||||
%ay2 = add i32 %ay, %ry
|
||||
store i32 %ay2, ptr @W_rawdy
|
||||
br label %dispatch
|
||||
dispatch:
|
||||
%dm = call i64 @DispatchMessageA(ptr %msg)
|
||||
br label %pump
|
||||
finish:
|
||||
call void @win_cursor_maintain()
|
||||
%alive = call i32 @IsWindow(ptr %hwnd)
|
||||
%dead = icmp eq i32 %alive, 0
|
||||
br i1 %dead, label %closed, label %done
|
||||
closed:
|
||||
store i32 0, ptr @W_running
|
||||
br label %done
|
||||
done:
|
||||
%k = load i32, ptr @W_key
|
||||
ret i32 %k
|
||||
}
|
||||
|
||||
; A software framebuffer: w*h words of 0x00RRGGBB, row 0 at the top - which is
|
||||
; exactly a top-down 32-bit DIB, so StretchDIBits takes it as it is.
|
||||
define void @win_present(ptr %fb, i32 %w, i32 %h) {
|
||||
entry:
|
||||
%bmi = alloca [44 x i8], align 4
|
||||
store ptr %fb, ptr @W_fb
|
||||
%hdc = load ptr, ptr @W_hdc
|
||||
%nodc = icmp eq ptr %hdc, null
|
||||
br i1 %nodc, label %out, label %draw
|
||||
draw:
|
||||
; BITMAPINFOHEADER: biSize 40, biWidth, biHeight negative (top-down), 1 plane, 32 bpp, BI_RGB
|
||||
call void @llvm.memset.p0.i64(ptr %bmi, i8 0, i64 44, i1 false)
|
||||
store i32 40, ptr %bmi
|
||||
%bw = getelementptr i8, ptr %bmi, i64 4
|
||||
store i32 %w, ptr %bw
|
||||
%nh = sub i32 0, %h
|
||||
%bh = getelementptr i8, ptr %bmi, i64 8
|
||||
store i32 %nh, ptr %bh
|
||||
%bp = getelementptr i8, ptr %bmi, i64 12
|
||||
store i16 1, ptr %bp
|
||||
%bb = getelementptr i8, ptr %bmi, i64 14
|
||||
store i16 32, ptr %bb
|
||||
%sc = load i32, ptr @W_scale
|
||||
%dw = mul i32 %w, %sc
|
||||
%dh = mul i32 %h, %sc
|
||||
%r = call i32 @StretchDIBits(ptr %hdc, i32 0, i32 0, i32 %dw, i32 %dh, i32 0, i32 0, i32 %w, i32 %h, ptr %fb, ptr %bmi, i32 0, i32 13369376) ; DIB_RGB_COLORS, SRCCOPY
|
||||
call void @Sleep(i32 16) ; ~60 fps, as cocoa.ll's usleep
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @win_running() {
|
||||
entry:
|
||||
%r = load i32, ptr @W_running
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
define void @win_close() {
|
||||
entry:
|
||||
store i32 0, ptr @W_cursor_mode
|
||||
call void @win_cursor_maintain()
|
||||
store i32 0, ptr @W_running
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @win_held(ptr %out) {
|
||||
entry:
|
||||
br label %loop
|
||||
loop:
|
||||
%i = phi i32 [ 0, %entry ], [ %ni, %body ]
|
||||
%done = icmp sge i32 %i, 8
|
||||
br i1 %done, label %ret, label %body
|
||||
body:
|
||||
%sp = getelementptr [8 x i32], ptr @W_held, i32 0, i32 %i
|
||||
%v = load i32, ptr %sp
|
||||
%dp = getelementptr i32, ptr %out, i32 %i
|
||||
store i32 %v, ptr %dp
|
||||
%ni = add i32 %i, 1
|
||||
br label %loop
|
||||
ret:
|
||||
ret void
|
||||
}
|
||||
|
||||
; [x, y, buttons, wheel, raw dx, raw dy]; the wheel and the raw motion are per call
|
||||
define void @win_mouse(ptr %out) {
|
||||
entry:
|
||||
%pt = alloca [8 x i8], align 4
|
||||
%mode = load i32, ptr @W_cursor_mode
|
||||
%isrel = icmp eq i32 %mode, 2
|
||||
%ddx = load i32, ptr @W_rawdx
|
||||
%ddy = load i32, ptr @W_rawdy
|
||||
store i32 0, ptr @W_rawdx
|
||||
store i32 0, ptr @W_rawdy
|
||||
%fbw = load i32, ptr @W_fbw
|
||||
%fbh = load i32, ptr @W_fbh
|
||||
%fbwm = sub i32 %fbw, 1
|
||||
%fbhm = sub i32 %fbh, 1
|
||||
br i1 %isrel, label %rel, label %abs
|
||||
rel:
|
||||
; locked: the OS cursor is held still, so the position is a virtual one moved by the
|
||||
; raw motion and clamped to the framebuffer; the motion itself is reported unclamped
|
||||
%omx = load i32, ptr @W_mx
|
||||
%omy = load i32, ptr @W_my
|
||||
%nmx = add i32 %omx, %ddx
|
||||
%nmy = add i32 %omy, %ddy
|
||||
%p4r = getelementptr i32, ptr %out, i32 4
|
||||
store i32 %ddx, ptr %p4r
|
||||
%p5r = getelementptr i32, ptr %out, i32 5
|
||||
store i32 %ddy, ptr %p5r
|
||||
br label %clamp
|
||||
abs:
|
||||
%p4a = getelementptr i32, ptr %out, i32 4
|
||||
store i32 0, ptr %p4a
|
||||
%p5a = getelementptr i32, ptr %out, i32 5
|
||||
store i32 0, ptr %p5a
|
||||
%hwnd = load ptr, ptr @W_hwnd
|
||||
%nowin = icmp eq ptr %hwnd, null
|
||||
br i1 %nowin, label %emit, label %qpos
|
||||
qpos:
|
||||
%g = call i32 @GetCursorPos(ptr %pt)
|
||||
%s = call i32 @ScreenToClient(ptr %hwnd, ptr %pt)
|
||||
%cx = load i32, ptr %pt
|
||||
%cyp = getelementptr i8, ptr %pt, i64 4
|
||||
%cy = load i32, ptr %cyp
|
||||
%sc = load i32, ptr @W_scale
|
||||
%sc0 = icmp slt i32 %sc, 1
|
||||
%scv = select i1 %sc0, i32 1, i32 %sc
|
||||
%ax = sdiv i32 %cx, %scv
|
||||
%ay = sdiv i32 %cy, %scv
|
||||
br label %clamp
|
||||
clamp:
|
||||
%ux = phi i32 [ %nmx, %rel ], [ %ax, %qpos ]
|
||||
%uy = phi i32 [ %nmy, %rel ], [ %ay, %qpos ]
|
||||
%xlo = icmp slt i32 %ux, 0
|
||||
%x1 = select i1 %xlo, i32 0, i32 %ux
|
||||
%xhi = icmp sgt i32 %x1, %fbwm
|
||||
%x2 = select i1 %xhi, i32 %fbwm, i32 %x1
|
||||
%ylo = icmp slt i32 %uy, 0
|
||||
%y1 = select i1 %ylo, i32 0, i32 %uy
|
||||
%yhi = icmp sgt i32 %y1, %fbhm
|
||||
%y2 = select i1 %yhi, i32 %fbhm, i32 %y1
|
||||
store i32 %x2, ptr @W_mx
|
||||
store i32 %y2, ptr @W_my
|
||||
br label %emit
|
||||
emit:
|
||||
%mx = load i32, ptr @W_mx
|
||||
store i32 %mx, ptr %out
|
||||
%my = load i32, ptr @W_my
|
||||
%p1 = getelementptr i32, ptr %out, i32 1
|
||||
store i32 %my, ptr %p1
|
||||
%mb = load i32, ptr @W_mbtn
|
||||
%p2 = getelementptr i32, ptr %out, i32 2
|
||||
store i32 %mb, ptr %p2
|
||||
%wh = load i32, ptr @W_wheel
|
||||
%p3 = getelementptr i32, ptr %out, i32 3
|
||||
store i32 %wh, ptr %p3
|
||||
store i32 0, ptr @W_wheel
|
||||
ret void
|
||||
}
|
||||
|
||||
; ---- the cursor ----------------------------------------------------------------
|
||||
define internal void @w_cursor_hide(i32 %want) {
|
||||
entry:
|
||||
%cur = load i32, ptr @W_cursor_hidden
|
||||
%same = icmp eq i32 %cur, %want
|
||||
br i1 %same, label %out, label %change
|
||||
change:
|
||||
store i32 %want, ptr @W_cursor_hidden
|
||||
%hide = icmp ne i32 %want, 0
|
||||
br i1 %hide, label %none, label %arrow
|
||||
none:
|
||||
%c0 = call ptr @SetCursor(ptr null)
|
||||
br label %out
|
||||
arrow:
|
||||
%a = call ptr @LoadCursorA(ptr null, ptr inttoptr (i64 32512 to ptr))
|
||||
%c1 = call ptr @SetCursor(ptr %a)
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Re-derive the cursor from the mode and whether this window is in front, every frame:
|
||||
; hidden for modes 1-3, held to the window's centre for 2, to its client area for 3,
|
||||
; and all of it let go the moment another window comes forward. ClipCursor is global,
|
||||
; so it is only released when this window was the one that set it.
|
||||
define void @win_cursor_maintain() {
|
||||
entry:
|
||||
%rc = alloca [16 x i8], align 4
|
||||
%hwnd = load ptr, ptr @W_hwnd
|
||||
%nowin = icmp eq ptr %hwnd, null
|
||||
br i1 %nowin, label %release, label %askfg
|
||||
askfg:
|
||||
%fg = call ptr @GetForegroundWindow()
|
||||
%front = icmp eq ptr %fg, %hwnd
|
||||
br i1 %front, label %keyed, label %release
|
||||
release:
|
||||
call void @w_cursor_hide(i32 0)
|
||||
%was = load i32, ptr @W_clipped
|
||||
%clipped = icmp ne i32 %was, 0
|
||||
br i1 %clipped, label %unclip, label %out
|
||||
unclip:
|
||||
%u = call i32 @ClipCursor(ptr null)
|
||||
store i32 0, ptr @W_clipped
|
||||
br label %out
|
||||
keyed:
|
||||
%mode = load i32, ptr @W_cursor_mode
|
||||
%any = icmp ne i32 %mode, 0
|
||||
%anyi = zext i1 %any to i32
|
||||
call void @w_cursor_hide(i32 %anyi)
|
||||
%is2 = icmp eq i32 %mode, 2
|
||||
%is3 = icmp eq i32 %mode, 3
|
||||
%holds = or i1 %is2, %is3
|
||||
br i1 %holds, label %rect, label %free
|
||||
free:
|
||||
%fwas = load i32, ptr @W_clipped
|
||||
%fclipped = icmp ne i32 %fwas, 0
|
||||
br i1 %fclipped, label %unclip, label %out
|
||||
rect:
|
||||
%gc = call i32 @GetClientRect(ptr %hwnd, ptr %rc)
|
||||
%tl = call i32 @ClientToScreen(ptr %hwnd, ptr %rc)
|
||||
%brp = getelementptr i8, ptr %rc, i64 8
|
||||
%br = call i32 @ClientToScreen(ptr %hwnd, ptr %brp)
|
||||
br i1 %is2, label %centre, label %clip
|
||||
centre:
|
||||
%l = load i32, ptr %rc
|
||||
%tp = getelementptr i8, ptr %rc, i64 4
|
||||
%t = load i32, ptr %tp
|
||||
%r = load i32, ptr %brp
|
||||
%bp = getelementptr i8, ptr %rc, i64 12
|
||||
%b = load i32, ptr %bp
|
||||
%lr = add i32 %l, %r
|
||||
%cx = sdiv i32 %lr, 2
|
||||
%tb = add i32 %t, %b
|
||||
%cy = sdiv i32 %tb, 2
|
||||
%cx1 = add i32 %cx, 1
|
||||
%cy1 = add i32 %cy, 1
|
||||
store i32 %cx, ptr %rc
|
||||
store i32 %cy, ptr %tp
|
||||
store i32 %cx1, ptr %brp
|
||||
store i32 %cy1, ptr %bp
|
||||
br label %clip
|
||||
clip:
|
||||
%cc = call i32 @ClipCursor(ptr %rc)
|
||||
store i32 1, ptr @W_clipped
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @win_cursor_mode(i32 %mode) {
|
||||
entry:
|
||||
store i32 %mode, ptr @W_cursor_mode
|
||||
call void @win_cursor_maintain()
|
||||
ret void
|
||||
}
|
||||
|
||||
; ---- gamepads, through XInput --------------------------------------------------
|
||||
; A stick value past its deadzone, rescaled so the edge of the deadzone is 0.0 and
|
||||
; full deflection is 1.0, as Q16.16 (GameController does the same before macOS sees it).
|
||||
define internal i32 @w_axis(i16 %v, i32 %dz) {
|
||||
entry:
|
||||
%s = sext i16 %v to i32
|
||||
%neg = icmp slt i32 %s, 0
|
||||
%ms = sub i32 0, %s
|
||||
%a = select i1 %neg, i32 %ms, i32 %s
|
||||
%inside = icmp sle i32 %a, %dz
|
||||
br i1 %inside, label %zero, label %scale
|
||||
zero:
|
||||
ret i32 0
|
||||
scale:
|
||||
%past = sub i32 %a, %dz
|
||||
%range = sub i32 32767, %dz
|
||||
%p64 = sext i32 %past to i64
|
||||
%m = mul i64 %p64, 65536
|
||||
%r64 = sext i32 %range to i64
|
||||
%q = sdiv i64 %m, %r64
|
||||
%q32 = trunc i64 %q to i32
|
||||
%big = icmp sgt i32 %q32, 65536
|
||||
%cl = select i1 %big, i32 65536, i32 %q32
|
||||
%mneg = sub i32 0, %cl
|
||||
%res = select i1 %neg, i32 %mneg, i32 %cl
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; bit %from of %bits, moved to bit %to
|
||||
define internal i32 @w_bit(i32 %bits, i32 %from, i32 %to) {
|
||||
entry:
|
||||
%s = lshr i32 %bits, %from
|
||||
%b = and i32 %s, 1
|
||||
%o = shl i32 %b, %to
|
||||
ret i32 %o
|
||||
}
|
||||
|
||||
; [connected, mask, lx, ly, rx, ry] for pads 0-3. XINPUT_STATE: dwPacketNumber 0, then
|
||||
; XINPUT_GAMEPAD at 4: wButtons 4, bLeftTrigger 6, bRightTrigger 7, sThumbLX 8, LY 10, RX 12, RY 14.
|
||||
define void @win_pad(ptr %out) {
|
||||
entry:
|
||||
%st = alloca [16 x i8], align 4
|
||||
call void @llvm.memset.p0.i64(ptr %out, i8 0, i64 96, i1 false)
|
||||
br label %loop
|
||||
loop:
|
||||
%p = phi i32 [ 0, %entry ], [ %pn, %next ]
|
||||
%more = icmp slt i32 %p, 4
|
||||
br i1 %more, label %ask, label %done
|
||||
ask:
|
||||
call void @llvm.memset.p0.i64(ptr %st, i8 0, i64 16, i1 false)
|
||||
%r = call i32 @XInputGetState(i32 %p, ptr %st)
|
||||
%conn = icmp eq i32 %r, 0 ; ERROR_SUCCESS
|
||||
br i1 %conn, label %pack, label %next
|
||||
pack:
|
||||
%base = mul i32 %p, 6
|
||||
%o0 = getelementptr i32, ptr %out, i32 %base
|
||||
store i32 1, ptr %o0
|
||||
%btp = getelementptr i8, ptr %st, i64 4
|
||||
%bt16 = load i16, ptr %btp
|
||||
%bt = zext i16 %bt16 to i32
|
||||
; XInput bits -> SDL order: A B X Y Back . Start LStick RStick LShoulder RShoulder Up Down Left Right
|
||||
%mA = call i32 @w_bit(i32 %bt, i32 12, i32 0)
|
||||
%mB = call i32 @w_bit(i32 %bt, i32 13, i32 1)
|
||||
%mX = call i32 @w_bit(i32 %bt, i32 14, i32 2)
|
||||
%mY = call i32 @w_bit(i32 %bt, i32 15, i32 3)
|
||||
%mBk = call i32 @w_bit(i32 %bt, i32 5, i32 4)
|
||||
%mSt = call i32 @w_bit(i32 %bt, i32 4, i32 6)
|
||||
%mLs = call i32 @w_bit(i32 %bt, i32 6, i32 7)
|
||||
%mRs = call i32 @w_bit(i32 %bt, i32 7, i32 8)
|
||||
%mLb = call i32 @w_bit(i32 %bt, i32 8, i32 9)
|
||||
%mRb = call i32 @w_bit(i32 %bt, i32 9, i32 10)
|
||||
%mU = call i32 @w_bit(i32 %bt, i32 0, i32 11)
|
||||
%mD = call i32 @w_bit(i32 %bt, i32 1, i32 12)
|
||||
%mL = call i32 @w_bit(i32 %bt, i32 2, i32 13)
|
||||
%mR = call i32 @w_bit(i32 %bt, i32 3, i32 14)
|
||||
; the triggers are analogue; past XINPUT_GAMEPAD_TRIGGER_THRESHOLD (30) they are pressed
|
||||
%ltp = getelementptr i8, ptr %st, i64 6
|
||||
%lt8 = load i8, ptr %ltp
|
||||
%lt = zext i8 %lt8 to i32
|
||||
%ltd = icmp sgt i32 %lt, 30
|
||||
%ltb = zext i1 %ltd to i32
|
||||
%mLt = shl i32 %ltb, 15
|
||||
%rtp = getelementptr i8, ptr %st, i64 7
|
||||
%rt8 = load i8, ptr %rtp
|
||||
%rt = zext i8 %rt8 to i32
|
||||
%rtd = icmp sgt i32 %rt, 30
|
||||
%rtb = zext i1 %rtd to i32
|
||||
%mRt = shl i32 %rtb, 16
|
||||
%k1 = or i32 %mA, %mB
|
||||
%k2 = or i32 %k1, %mX
|
||||
%k3 = or i32 %k2, %mY
|
||||
%k4 = or i32 %k3, %mBk
|
||||
%k5 = or i32 %k4, %mSt
|
||||
%k6 = or i32 %k5, %mLs
|
||||
%k7 = or i32 %k6, %mRs
|
||||
%k8 = or i32 %k7, %mLb
|
||||
%k9 = or i32 %k8, %mRb
|
||||
%k10 = or i32 %k9, %mU
|
||||
%k11 = or i32 %k10, %mD
|
||||
%k12 = or i32 %k11, %mL
|
||||
%k13 = or i32 %k12, %mR
|
||||
%k14 = or i32 %k13, %mLt
|
||||
%mask = or i32 %k14, %mRt
|
||||
%i1 = add i32 %base, 1
|
||||
%o1 = getelementptr i32, ptr %out, i32 %i1
|
||||
store i32 %mask, ptr %o1
|
||||
; XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849, RIGHT 8689; XInput's Y is up, Ludic's is down
|
||||
%lxp = getelementptr i8, ptr %st, i64 8
|
||||
%lxv = load i16, ptr %lxp
|
||||
%lx = call i32 @w_axis(i16 %lxv, i32 7849)
|
||||
%i2 = add i32 %base, 2
|
||||
%o2 = getelementptr i32, ptr %out, i32 %i2
|
||||
store i32 %lx, ptr %o2
|
||||
%lyp = getelementptr i8, ptr %st, i64 10
|
||||
%lyv = load i16, ptr %lyp
|
||||
%lyu = call i32 @w_axis(i16 %lyv, i32 7849)
|
||||
%ly = sub i32 0, %lyu
|
||||
%i3 = add i32 %base, 3
|
||||
%o3 = getelementptr i32, ptr %out, i32 %i3
|
||||
store i32 %ly, ptr %o3
|
||||
%rxp = getelementptr i8, ptr %st, i64 12
|
||||
%rxv = load i16, ptr %rxp
|
||||
%rx = call i32 @w_axis(i16 %rxv, i32 8689)
|
||||
%i4 = add i32 %base, 4
|
||||
%o4 = getelementptr i32, ptr %out, i32 %i4
|
||||
store i32 %rx, ptr %o4
|
||||
%ryp = getelementptr i8, ptr %st, i64 14
|
||||
%ryv = load i16, ptr %ryp
|
||||
%ryu = call i32 @w_axis(i16 %ryv, i32 8689)
|
||||
%ry = sub i32 0, %ryu
|
||||
%i5 = add i32 %base, 5
|
||||
%o5 = getelementptr i32, ptr %out, i32 %i5
|
||||
store i32 %ry, ptr %o5
|
||||
br label %next
|
||||
next:
|
||||
%pn = add i32 %p, 1
|
||||
br label %loop
|
||||
done:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Touch: a Windows PC reports its touchpad as a mouse, so there are no points.
|
||||
define void @win_touch(ptr %out) {
|
||||
entry:
|
||||
call void @llvm.memset.p0.i64(ptr %out, i8 0, i64 96, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
; ---- the splash and the icon ---------------------------------------------------
|
||||
; Not yet: both need an image decoder (WIC), and on Windows the icon a player sees on
|
||||
; the taskbar and in Explorer is the one linked into the .exe, which `ludic bundle`
|
||||
; will do. Until then these keep the contract - safe to call, change nothing.
|
||||
define void @splash_show(ptr %bytes, i32 %len, i32 %bg) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @splash_hide() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
define void @app_set_icon(ptr %bytes, i32 %len) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
253
runtime/native/win32_gl.ll
Normal file
253
runtime/native/win32_gl.ll
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
; ============================================================================
|
||||
; win32_gl.ll — OpenGL on the Windows window (cocoa.ll's win_gl_* half).
|
||||
;
|
||||
; Linked into a windowed Windows program that uses Gl.*, beside win32.ll (the
|
||||
; window) and gl_win.ll (which makes a 4.1 core context on a DC and fills the
|
||||
; entry-point table). A headless build links gl_win_nowin.ll in its place.
|
||||
;
|
||||
; win_gl_attach() -> ok the context on the window's DC (0 = no window yet)
|
||||
; win_gl_resize(w, h) client area of w x h pixels, centred
|
||||
; win_gl_swap() SwapBuffers, paced by the swap interval
|
||||
; win_gl_scale() -> 1 the process is DPI aware: one pixel is one pixel
|
||||
; win_gl_drawable(out) the client area in pixels
|
||||
; win_toggle_fullscreen() borderless, over the monitor the window is on
|
||||
; ============================================================================
|
||||
|
||||
@W_hwnd = external global ptr
|
||||
@W_hdc = external global ptr
|
||||
@W_fbw = external global i32
|
||||
@W_fbh = external global i32
|
||||
@W_scale = external global i32
|
||||
|
||||
declare ptr @lgl_wgl_core(ptr, i32)
|
||||
declare ptr @wglGetProcAddress(ptr)
|
||||
declare i32 @SwapBuffers(ptr)
|
||||
declare i32 @GetClientRect(ptr, ptr)
|
||||
declare i32 @AdjustWindowRectEx(ptr, i32, i32, i32)
|
||||
declare i32 @SetWindowPos(ptr, ptr, i32, i32, i32, i32, i32)
|
||||
declare i32 @GetSystemMetrics(i32)
|
||||
declare i64 @GetWindowLongPtrA(ptr, i32)
|
||||
declare i64 @SetWindowLongPtrA(ptr, i32, i64)
|
||||
declare i32 @GetWindowRect(ptr, ptr)
|
||||
declare ptr @MonitorFromWindow(ptr, i32)
|
||||
declare i32 @GetMonitorInfoA(ptr, ptr)
|
||||
declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)
|
||||
|
||||
@.wgl_swapint = private unnamed_addr constant [19 x i8] c"wglSwapIntervalEXT\00"
|
||||
|
||||
@W_glctx = internal global ptr null
|
||||
@W_fs = internal global i32 0
|
||||
@W_fs_style = internal global i64 0
|
||||
@W_fs_rect = internal global [4 x i32] zeroinitializer
|
||||
|
||||
define i32 @win_gl_attach() {
|
||||
entry:
|
||||
%have = load ptr, ptr @W_glctx
|
||||
%again = icmp ne ptr %have, null
|
||||
br i1 %again, label %ok, label %make
|
||||
make:
|
||||
%hdc = load ptr, ptr @W_hdc
|
||||
%nodc = icmp eq ptr %hdc, null
|
||||
br i1 %nodc, label %fail, label %ctx
|
||||
ctx:
|
||||
; 24-bit colour with 8 of alpha, 24 depth, 8 stencil, double-buffered: cocoa.ll's format
|
||||
%c = call ptr @lgl_wgl_core(ptr %hdc, i32 8)
|
||||
%noc = icmp eq ptr %c, null
|
||||
br i1 %noc, label %fail, label %keep
|
||||
keep:
|
||||
store ptr %c, ptr @W_glctx
|
||||
call void @win_gl_swap_interval(i32 1)
|
||||
br label %ok
|
||||
ok:
|
||||
ret i32 1
|
||||
fail:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define void @win_gl_resize(i32 %w, i32 %h) {
|
||||
entry:
|
||||
%rc = alloca [16 x i8], align 4
|
||||
%hwnd = load ptr, ptr @W_hwnd
|
||||
%nowin = icmp eq ptr %hwnd, null
|
||||
br i1 %nowin, label %out, label %go
|
||||
go:
|
||||
store i32 %w, ptr @W_fbw
|
||||
store i32 %h, ptr @W_fbh
|
||||
store i32 1, ptr @W_scale
|
||||
%fs = load i32, ptr @W_fs
|
||||
%isfs = icmp ne i32 %fs, 0
|
||||
br i1 %isfs, label %out, label %size
|
||||
size:
|
||||
call void @llvm.memset.p0.i64(ptr %rc, i8 0, i64 16, i1 false)
|
||||
%rcr = getelementptr i8, ptr %rc, i64 8
|
||||
store i32 %w, ptr %rcr
|
||||
%rcb = getelementptr i8, ptr %rc, i64 12
|
||||
store i32 %h, ptr %rcb
|
||||
%style64 = call i64 @GetWindowLongPtrA(ptr %hwnd, i32 -16) ; GWL_STYLE
|
||||
%style = trunc i64 %style64 to i32
|
||||
%adj = call i32 @AdjustWindowRectEx(ptr %rc, i32 %style, i32 0, i32 0)
|
||||
%l = load i32, ptr %rc
|
||||
%tp = getelementptr i8, ptr %rc, i64 4
|
||||
%t = load i32, ptr %tp
|
||||
%r = load i32, ptr %rcr
|
||||
%b = load i32, ptr %rcb
|
||||
%ww = sub i32 %r, %l
|
||||
%wh = sub i32 %b, %t
|
||||
%sw = call i32 @GetSystemMetrics(i32 0)
|
||||
%sh = call i32 @GetSystemMetrics(i32 1)
|
||||
%dx = sub i32 %sw, %ww
|
||||
%x0 = sdiv i32 %dx, 2
|
||||
%xneg = icmp slt i32 %x0, 0
|
||||
%x = select i1 %xneg, i32 0, i32 %x0
|
||||
%dy = sub i32 %sh, %wh
|
||||
%y0 = sdiv i32 %dy, 2
|
||||
%yneg = icmp slt i32 %y0, 0
|
||||
%y = select i1 %yneg, i32 0, i32 %y0
|
||||
%sp = call i32 @SetWindowPos(ptr %hwnd, ptr null, i32 %x, i32 %y, i32 %ww, i32 %wh, i32 20) ; SWP_NOZORDER | SWP_NOACTIVATE
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @win_gl_swap() {
|
||||
entry:
|
||||
%c = load ptr, ptr @W_glctx
|
||||
%noc = icmp eq ptr %c, null
|
||||
br i1 %noc, label %out, label %go
|
||||
go:
|
||||
%hdc = load ptr, ptr @W_hdc
|
||||
%r = call i32 @SwapBuffers(ptr %hdc)
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @win_gl_scale() {
|
||||
entry:
|
||||
ret i32 1
|
||||
}
|
||||
|
||||
; 1 = vsync (set at attach), 0 = free-running; wglSwapIntervalEXT is a driver extension,
|
||||
; reachable only through the current context
|
||||
define void @win_gl_swap_interval(i32 %n) {
|
||||
entry:
|
||||
%c = load ptr, ptr @W_glctx
|
||||
%noc = icmp eq ptr %c, null
|
||||
br i1 %noc, label %out, label %find
|
||||
find:
|
||||
%fp = call ptr @wglGetProcAddress(ptr @.wgl_swapint)
|
||||
%fpi = ptrtoint ptr %fp to i64
|
||||
%fpa = add i64 %fpi, 1
|
||||
%bad = icmp ult i64 %fpa, 5
|
||||
br i1 %bad, label %out, label %call
|
||||
call:
|
||||
%r = call i32 %fp(i32 %n)
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @win_gl_drawable(ptr %out) {
|
||||
entry:
|
||||
%rc = alloca [16 x i8], align 4
|
||||
%hwnd = load ptr, ptr @W_hwnd
|
||||
%nowin = icmp eq ptr %hwnd, null
|
||||
br i1 %nowin, label %none, label %go
|
||||
go:
|
||||
%g = call i32 @GetClientRect(ptr %hwnd, ptr %rc)
|
||||
%rp = getelementptr i8, ptr %rc, i64 8
|
||||
%w = load i32, ptr %rp
|
||||
%bp = getelementptr i8, ptr %rc, i64 12
|
||||
%h = load i32, ptr %bp
|
||||
store i32 %w, ptr %out
|
||||
%o1 = getelementptr i32, ptr %out, i32 1
|
||||
store i32 %h, ptr %o1
|
||||
; a minimised window has no client area; keep the last real size for the mouse mapping
|
||||
%zw = icmp sle i32 %w, 0
|
||||
%zh = icmp sle i32 %h, 0
|
||||
%gone = or i1 %zw, %zh
|
||||
br i1 %gone, label %done, label %track
|
||||
track:
|
||||
store i32 %w, ptr @W_fbw
|
||||
store i32 %h, ptr @W_fbh
|
||||
br label %done
|
||||
done:
|
||||
ret void
|
||||
none:
|
||||
store i32 0, ptr %out
|
||||
%o1n = getelementptr i32, ptr %out, i32 1
|
||||
store i32 0, ptr %o1n
|
||||
ret void
|
||||
}
|
||||
|
||||
; WGL needs no notice that its window changed size
|
||||
define void @win_gl_update() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; The Retina switch: on Windows the process is DPI aware and always draws one pixel per
|
||||
; screen pixel, which is what "on" means on macOS; there is no lower-resolution surface
|
||||
; for "off" to fall back to, so it changes nothing.
|
||||
define void @win_gl_retina(i32 %on) {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Borderless full screen over the window's monitor, and back to the frame and the
|
||||
; rectangle it had. (Exclusive full screen would change the display mode under a
|
||||
; player's other windows; nothing in the game needs it.)
|
||||
define void @win_toggle_fullscreen() {
|
||||
entry:
|
||||
%mi = alloca [40 x i8], align 4
|
||||
%hwnd = load ptr, ptr @W_hwnd
|
||||
%nowin = icmp eq ptr %hwnd, null
|
||||
br i1 %nowin, label %out, label %which
|
||||
which:
|
||||
%fs = load i32, ptr @W_fs
|
||||
%isfs = icmp ne i32 %fs, 0
|
||||
br i1 %isfs, label %leave, label %enter
|
||||
enter:
|
||||
%style = call i64 @GetWindowLongPtrA(ptr %hwnd, i32 -16)
|
||||
store i64 %style, ptr @W_fs_style
|
||||
%gr = call i32 @GetWindowRect(ptr %hwnd, ptr @W_fs_rect)
|
||||
%mon = call ptr @MonitorFromWindow(ptr %hwnd, i32 2) ; MONITOR_DEFAULTTONEAREST
|
||||
call void @llvm.memset.p0.i64(ptr %mi, i8 0, i64 40, i1 false)
|
||||
store i32 40, ptr %mi
|
||||
%gm = call i32 @GetMonitorInfoA(ptr %mon, ptr %mi)
|
||||
; MONITORINFO.rcMonitor at 4
|
||||
%mlp = getelementptr i8, ptr %mi, i64 4
|
||||
%ml = load i32, ptr %mlp
|
||||
%mtp = getelementptr i8, ptr %mi, i64 8
|
||||
%mt = load i32, ptr %mtp
|
||||
%mrp = getelementptr i8, ptr %mi, i64 12
|
||||
%mr = load i32, ptr %mrp
|
||||
%mbp = getelementptr i8, ptr %mi, i64 16
|
||||
%mb = load i32, ptr %mbp
|
||||
; drop WS_OVERLAPPEDWINDOW (0x00CF0000), add WS_POPUP (0x80000000)
|
||||
%bare = and i64 %style, -13565953
|
||||
%popup = or i64 %bare, 2147483648
|
||||
%sl = call i64 @SetWindowLongPtrA(ptr %hwnd, i32 -16, i64 %popup)
|
||||
%fw = sub i32 %mr, %ml
|
||||
%fh = sub i32 %mb, %mt
|
||||
%sp = call i32 @SetWindowPos(ptr %hwnd, ptr null, i32 %ml, i32 %mt, i32 %fw, i32 %fh, i32 544) ; SWP_FRAMECHANGED | SWP_NOOWNERZORDER
|
||||
store i32 1, ptr @W_fs
|
||||
br label %out
|
||||
leave:
|
||||
%saved = load i64, ptr @W_fs_style
|
||||
%sl2 = call i64 @SetWindowLongPtrA(ptr %hwnd, i32 -16, i64 %saved)
|
||||
%l = load i32, ptr @W_fs_rect
|
||||
%tp = getelementptr i32, ptr @W_fs_rect, i32 1
|
||||
%t = load i32, ptr %tp
|
||||
%rp = getelementptr i32, ptr @W_fs_rect, i32 2
|
||||
%r = load i32, ptr %rp
|
||||
%bp = getelementptr i32, ptr @W_fs_rect, i32 3
|
||||
%b = load i32, ptr %bp
|
||||
%ww = sub i32 %r, %l
|
||||
%wh = sub i32 %b, %t
|
||||
%sp2 = call i32 @SetWindowPos(ptr %hwnd, ptr null, i32 %l, i32 %t, i32 %ww, i32 %wh, i32 548) ; ... | SWP_NOZORDER
|
||||
store i32 0, ptr @W_fs
|
||||
br label %out
|
||||
out:
|
||||
ret void
|
||||
}
|
||||
|
|
@ -11314,40 +11314,47 @@ declare void @hs_free(i32)
|
|||
@.str11126 = private unnamed_addr constant [108 x i8] c"usage: ludicc <file.ludic> [-o out] [--windowed|--headless] [--target triple] [--emit-llvm] [--save-temps]\0A\00"
|
||||
@.str11127 = private unnamed_addr constant [8 x i8] c"windows\00"
|
||||
@.str11128 = private unnamed_addr constant [27 x i8] c"ludicc: cannot open input\0A\00"
|
||||
@.str11129 = private unnamed_addr constant [81 x i8] c"ludicc: a windowed build is not available on Windows yet; build with --headless\0A\00"
|
||||
@.str11130 = private unnamed_addr constant [48 x i8] c"ludicc: Http.* is not available on Windows yet\0A\00"
|
||||
@.str11131 = private unnamed_addr constant [5 x i8] c"TEMP\00"
|
||||
@.str11132 = private unnamed_addr constant [2 x i8] c".\00"
|
||||
@.str11133 = private unnamed_addr constant [12 x i8] c"/ludic-run-\00"
|
||||
@.str11134 = private unnamed_addr constant [16 x i8] c"/tmp/ludic-run-\00"
|
||||
@.str11129 = private unnamed_addr constant [48 x i8] c"ludicc: Http.* is not available on Windows yet\0A\00"
|
||||
@.str11130 = private unnamed_addr constant [5 x i8] c"TEMP\00"
|
||||
@.str11131 = private unnamed_addr constant [2 x i8] c".\00"
|
||||
@.str11132 = private unnamed_addr constant [12 x i8] c"/ludic-run-\00"
|
||||
@.str11133 = private unnamed_addr constant [16 x i8] c"/tmp/ludic-run-\00"
|
||||
@.str11134 = private unnamed_addr constant [5 x i8] c".exe\00"
|
||||
@.str11135 = private unnamed_addr constant [5 x i8] c".exe\00"
|
||||
@.str11136 = private unnamed_addr constant [5 x i8] c".exe\00"
|
||||
@.str11137 = private unnamed_addr constant [4 x i8] c".ll\00"
|
||||
@.str11138 = private unnamed_addr constant [25 x i8] c"ludicc: cannot write IR\0A\00"
|
||||
@.str11139 = private unnamed_addr constant [27 x i8] c" -O2 -Wno-override-module \00"
|
||||
@.str11140 = private unnamed_addr constant [24 x i8] c"runtime/native/cocoa.ll\00"
|
||||
@.str11141 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11142 = private unnamed_addr constant [79 x i8] c" -framework Cocoa -Wl,-needed_framework,GameController -Wl,-rpath,@loader_path\00"
|
||||
@.str11143 = private unnamed_addr constant [24 x i8] c"runtime/native/audio.ll\00"
|
||||
@.str11144 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11145 = private unnamed_addr constant [36 x i8] c" -Wl,-needed_framework,AVFoundation\00"
|
||||
@.str11146 = private unnamed_addr constant [23 x i8] c"runtime/native/http.ll\00"
|
||||
@.str11147 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11148 = private unnamed_addr constant [34 x i8] c" -Wl,-needed_framework,Foundation\00"
|
||||
@.str11149 = private unnamed_addr constant [25 x i8] c"runtime/native/gl_win.ll\00"
|
||||
@.str11150 = private unnamed_addr constant [32 x i8] c"runtime/native/gl_thunks_win.ll\00"
|
||||
@.str11136 = private unnamed_addr constant [4 x i8] c".ll\00"
|
||||
@.str11137 = private unnamed_addr constant [25 x i8] c"ludicc: cannot write IR\0A\00"
|
||||
@.str11138 = private unnamed_addr constant [27 x i8] c" -O2 -Wno-override-module \00"
|
||||
@.str11139 = private unnamed_addr constant [24 x i8] c"runtime/native/win32.ll\00"
|
||||
@.str11140 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11141 = private unnamed_addr constant [27 x i8] c" -luser32 -lgdi32 -lxinput\00"
|
||||
@.str11142 = private unnamed_addr constant [28 x i8] c"runtime/native/audio_win.ll\00"
|
||||
@.str11143 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11144 = private unnamed_addr constant [24 x i8] c"runtime/native/cocoa.ll\00"
|
||||
@.str11145 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11146 = private unnamed_addr constant [79 x i8] c" -framework Cocoa -Wl,-needed_framework,GameController -Wl,-rpath,@loader_path\00"
|
||||
@.str11147 = private unnamed_addr constant [24 x i8] c"runtime/native/audio.ll\00"
|
||||
@.str11148 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11149 = private unnamed_addr constant [36 x i8] c" -Wl,-needed_framework,AVFoundation\00"
|
||||
@.str11150 = private unnamed_addr constant [23 x i8] c"runtime/native/http.ll\00"
|
||||
@.str11151 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11152 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11153 = private unnamed_addr constant [29 x i8] c" -luser32 -lgdi32 -lopengl32\00"
|
||||
@.str11154 = private unnamed_addr constant [21 x i8] c"runtime/native/gl.ll\00"
|
||||
@.str11155 = private unnamed_addr constant [28 x i8] c"runtime/native/gl_thunks.ll\00"
|
||||
@.str11156 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11152 = private unnamed_addr constant [34 x i8] c" -Wl,-needed_framework,Foundation\00"
|
||||
@.str11153 = private unnamed_addr constant [25 x i8] c"runtime/native/gl_win.ll\00"
|
||||
@.str11154 = private unnamed_addr constant [32 x i8] c"runtime/native/gl_thunks_win.ll\00"
|
||||
@.str11155 = private unnamed_addr constant [31 x i8] c"runtime/native/gl_win_nowin.ll\00"
|
||||
@.str11156 = private unnamed_addr constant [27 x i8] c"runtime/native/win32_gl.ll\00"
|
||||
@.str11157 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11158 = private unnamed_addr constant [19 x i8] c" -framework OpenGL\00"
|
||||
@.str11159 = private unnamed_addr constant [5 x i8] c" -o \00"
|
||||
@.str11160 = private unnamed_addr constant [21 x i8] c"ludicc: link failed\0A\00"
|
||||
@.str11161 = private unnamed_addr constant [2 x i8] c"\22\00"
|
||||
@.str11162 = private unnamed_addr constant [2 x i8] c"\22\00"
|
||||
@.str11158 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11159 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11160 = private unnamed_addr constant [29 x i8] c" -luser32 -lgdi32 -lopengl32\00"
|
||||
@.str11161 = private unnamed_addr constant [21 x i8] c"runtime/native/gl.ll\00"
|
||||
@.str11162 = private unnamed_addr constant [28 x i8] c"runtime/native/gl_thunks.ll\00"
|
||||
@.str11163 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11164 = private unnamed_addr constant [2 x i8] c" \00"
|
||||
@.str11165 = private unnamed_addr constant [19 x i8] c" -framework OpenGL\00"
|
||||
@.str11166 = private unnamed_addr constant [5 x i8] c" -o \00"
|
||||
@.str11167 = private unnamed_addr constant [21 x i8] c"ludicc: link failed\0A\00"
|
||||
@.str11168 = private unnamed_addr constant [2 x i8] c"\22\00"
|
||||
@.str11169 = private unnamed_addr constant [2 x i8] c"\22\00"
|
||||
define i32 @lp_str_eq(ptr %a, ptr %b) {
|
||||
entry:
|
||||
br label %loop
|
||||
|
|
@ -12152,56 +12159,56 @@ sod:
|
|||
store i32 %fcnt, ptr %d2
|
||||
ret ptr %h
|
||||
}
|
||||
@.str11163 = private unnamed_addr constant [4 x i8] c"png\00"
|
||||
@.str11164 = private unnamed_addr constant [10 x i8] c"image/png\00"
|
||||
@.str11165 = private unnamed_addr constant [4 x i8] c"jpg\00"
|
||||
@.str11166 = private unnamed_addr constant [11 x i8] c"image/jpeg\00"
|
||||
@.str11167 = private unnamed_addr constant [5 x i8] c"jpeg\00"
|
||||
@.str11168 = private unnamed_addr constant [11 x i8] c"image/jpeg\00"
|
||||
@.str11169 = private unnamed_addr constant [4 x i8] c"gif\00"
|
||||
@.str11170 = private unnamed_addr constant [10 x i8] c"image/gif\00"
|
||||
@.str11171 = private unnamed_addr constant [4 x i8] c"bmp\00"
|
||||
@.str11172 = private unnamed_addr constant [10 x i8] c"image/bmp\00"
|
||||
@.str11173 = private unnamed_addr constant [5 x i8] c"webp\00"
|
||||
@.str11174 = private unnamed_addr constant [11 x i8] c"image/webp\00"
|
||||
@.str11175 = private unnamed_addr constant [4 x i8] c"svg\00"
|
||||
@.str11176 = private unnamed_addr constant [14 x i8] c"image/svg+xml\00"
|
||||
@.str11177 = private unnamed_addr constant [4 x i8] c"txt\00"
|
||||
@.str11178 = private unnamed_addr constant [11 x i8] c"text/plain\00"
|
||||
@.str11179 = private unnamed_addr constant [3 x i8] c"md\00"
|
||||
@.str11180 = private unnamed_addr constant [14 x i8] c"text/markdown\00"
|
||||
@.str11181 = private unnamed_addr constant [4 x i8] c"csv\00"
|
||||
@.str11182 = private unnamed_addr constant [9 x i8] c"text/csv\00"
|
||||
@.str11183 = private unnamed_addr constant [5 x i8] c"html\00"
|
||||
@.str11184 = private unnamed_addr constant [10 x i8] c"text/html\00"
|
||||
@.str11185 = private unnamed_addr constant [4 x i8] c"htm\00"
|
||||
@.str11186 = private unnamed_addr constant [10 x i8] c"text/html\00"
|
||||
@.str11187 = private unnamed_addr constant [4 x i8] c"css\00"
|
||||
@.str11188 = private unnamed_addr constant [9 x i8] c"text/css\00"
|
||||
@.str11189 = private unnamed_addr constant [3 x i8] c"js\00"
|
||||
@.str11190 = private unnamed_addr constant [16 x i8] c"text/javascript\00"
|
||||
@.str11191 = private unnamed_addr constant [5 x i8] c"json\00"
|
||||
@.str11192 = private unnamed_addr constant [17 x i8] c"application/json\00"
|
||||
@.str11193 = private unnamed_addr constant [4 x i8] c"xml\00"
|
||||
@.str11194 = private unnamed_addr constant [16 x i8] c"application/xml\00"
|
||||
@.str11195 = private unnamed_addr constant [4 x i8] c"zip\00"
|
||||
@.str11196 = private unnamed_addr constant [16 x i8] c"application/zip\00"
|
||||
@.str11197 = private unnamed_addr constant [4 x i8] c"pdf\00"
|
||||
@.str11198 = private unnamed_addr constant [16 x i8] c"application/pdf\00"
|
||||
@.str11199 = private unnamed_addr constant [4 x i8] c"wav\00"
|
||||
@.str11200 = private unnamed_addr constant [10 x i8] c"audio/wav\00"
|
||||
@.str11201 = private unnamed_addr constant [4 x i8] c"ogg\00"
|
||||
@.str11202 = private unnamed_addr constant [10 x i8] c"audio/ogg\00"
|
||||
@.str11203 = private unnamed_addr constant [4 x i8] c"mp3\00"
|
||||
@.str11204 = private unnamed_addr constant [11 x i8] c"audio/mpeg\00"
|
||||
@.str11205 = private unnamed_addr constant [4 x i8] c"ttf\00"
|
||||
@.str11206 = private unnamed_addr constant [9 x i8] c"font/ttf\00"
|
||||
@.str11207 = private unnamed_addr constant [4 x i8] c"otf\00"
|
||||
@.str11208 = private unnamed_addr constant [9 x i8] c"font/otf\00"
|
||||
@.str11209 = private unnamed_addr constant [6 x i8] c"ludic\00"
|
||||
@.str11210 = private unnamed_addr constant [13 x i8] c"text/x-ludic\00"
|
||||
@.str11211 = private unnamed_addr constant [25 x i8] c"application/octet-stream\00"
|
||||
@mime_tbl = private unnamed_addr constant [24 x { ptr, ptr }] [{ ptr, ptr } { ptr @.str11163, ptr @.str11164 }, { ptr, ptr } { ptr @.str11165, ptr @.str11166 }, { ptr, ptr } { ptr @.str11167, ptr @.str11168 }, { ptr, ptr } { ptr @.str11169, ptr @.str11170 }, { ptr, ptr } { ptr @.str11171, ptr @.str11172 }, { ptr, ptr } { ptr @.str11173, ptr @.str11174 }, { ptr, ptr } { ptr @.str11175, ptr @.str11176 }, { ptr, ptr } { ptr @.str11177, ptr @.str11178 }, { ptr, ptr } { ptr @.str11179, ptr @.str11180 }, { ptr, ptr } { ptr @.str11181, ptr @.str11182 }, { ptr, ptr } { ptr @.str11183, ptr @.str11184 }, { ptr, ptr } { ptr @.str11185, ptr @.str11186 }, { ptr, ptr } { ptr @.str11187, ptr @.str11188 }, { ptr, ptr } { ptr @.str11189, ptr @.str11190 }, { ptr, ptr } { ptr @.str11191, ptr @.str11192 }, { ptr, ptr } { ptr @.str11193, ptr @.str11194 }, { ptr, ptr } { ptr @.str11195, ptr @.str11196 }, { ptr, ptr } { ptr @.str11197, ptr @.str11198 }, { ptr, ptr } { ptr @.str11199, ptr @.str11200 }, { ptr, ptr } { ptr @.str11201, ptr @.str11202 }, { ptr, ptr } { ptr @.str11203, ptr @.str11204 }, { ptr, ptr } { ptr @.str11205, ptr @.str11206 }, { ptr, ptr } { ptr @.str11207, ptr @.str11208 }, { ptr, ptr } { ptr @.str11209, ptr @.str11210 }]
|
||||
@.str11170 = private unnamed_addr constant [4 x i8] c"png\00"
|
||||
@.str11171 = private unnamed_addr constant [10 x i8] c"image/png\00"
|
||||
@.str11172 = private unnamed_addr constant [4 x i8] c"jpg\00"
|
||||
@.str11173 = private unnamed_addr constant [11 x i8] c"image/jpeg\00"
|
||||
@.str11174 = private unnamed_addr constant [5 x i8] c"jpeg\00"
|
||||
@.str11175 = private unnamed_addr constant [11 x i8] c"image/jpeg\00"
|
||||
@.str11176 = private unnamed_addr constant [4 x i8] c"gif\00"
|
||||
@.str11177 = private unnamed_addr constant [10 x i8] c"image/gif\00"
|
||||
@.str11178 = private unnamed_addr constant [4 x i8] c"bmp\00"
|
||||
@.str11179 = private unnamed_addr constant [10 x i8] c"image/bmp\00"
|
||||
@.str11180 = private unnamed_addr constant [5 x i8] c"webp\00"
|
||||
@.str11181 = private unnamed_addr constant [11 x i8] c"image/webp\00"
|
||||
@.str11182 = private unnamed_addr constant [4 x i8] c"svg\00"
|
||||
@.str11183 = private unnamed_addr constant [14 x i8] c"image/svg+xml\00"
|
||||
@.str11184 = private unnamed_addr constant [4 x i8] c"txt\00"
|
||||
@.str11185 = private unnamed_addr constant [11 x i8] c"text/plain\00"
|
||||
@.str11186 = private unnamed_addr constant [3 x i8] c"md\00"
|
||||
@.str11187 = private unnamed_addr constant [14 x i8] c"text/markdown\00"
|
||||
@.str11188 = private unnamed_addr constant [4 x i8] c"csv\00"
|
||||
@.str11189 = private unnamed_addr constant [9 x i8] c"text/csv\00"
|
||||
@.str11190 = private unnamed_addr constant [5 x i8] c"html\00"
|
||||
@.str11191 = private unnamed_addr constant [10 x i8] c"text/html\00"
|
||||
@.str11192 = private unnamed_addr constant [4 x i8] c"htm\00"
|
||||
@.str11193 = private unnamed_addr constant [10 x i8] c"text/html\00"
|
||||
@.str11194 = private unnamed_addr constant [4 x i8] c"css\00"
|
||||
@.str11195 = private unnamed_addr constant [9 x i8] c"text/css\00"
|
||||
@.str11196 = private unnamed_addr constant [3 x i8] c"js\00"
|
||||
@.str11197 = private unnamed_addr constant [16 x i8] c"text/javascript\00"
|
||||
@.str11198 = private unnamed_addr constant [5 x i8] c"json\00"
|
||||
@.str11199 = private unnamed_addr constant [17 x i8] c"application/json\00"
|
||||
@.str11200 = private unnamed_addr constant [4 x i8] c"xml\00"
|
||||
@.str11201 = private unnamed_addr constant [16 x i8] c"application/xml\00"
|
||||
@.str11202 = private unnamed_addr constant [4 x i8] c"zip\00"
|
||||
@.str11203 = private unnamed_addr constant [16 x i8] c"application/zip\00"
|
||||
@.str11204 = private unnamed_addr constant [4 x i8] c"pdf\00"
|
||||
@.str11205 = private unnamed_addr constant [16 x i8] c"application/pdf\00"
|
||||
@.str11206 = private unnamed_addr constant [4 x i8] c"wav\00"
|
||||
@.str11207 = private unnamed_addr constant [10 x i8] c"audio/wav\00"
|
||||
@.str11208 = private unnamed_addr constant [4 x i8] c"ogg\00"
|
||||
@.str11209 = private unnamed_addr constant [10 x i8] c"audio/ogg\00"
|
||||
@.str11210 = private unnamed_addr constant [4 x i8] c"mp3\00"
|
||||
@.str11211 = private unnamed_addr constant [11 x i8] c"audio/mpeg\00"
|
||||
@.str11212 = private unnamed_addr constant [4 x i8] c"ttf\00"
|
||||
@.str11213 = private unnamed_addr constant [9 x i8] c"font/ttf\00"
|
||||
@.str11214 = private unnamed_addr constant [4 x i8] c"otf\00"
|
||||
@.str11215 = private unnamed_addr constant [9 x i8] c"font/otf\00"
|
||||
@.str11216 = private unnamed_addr constant [6 x i8] c"ludic\00"
|
||||
@.str11217 = private unnamed_addr constant [13 x i8] c"text/x-ludic\00"
|
||||
@.str11218 = private unnamed_addr constant [25 x i8] c"application/octet-stream\00"
|
||||
@mime_tbl = private unnamed_addr constant [24 x { ptr, ptr }] [{ ptr, ptr } { ptr @.str11170, ptr @.str11171 }, { ptr, ptr } { ptr @.str11172, ptr @.str11173 }, { ptr, ptr } { ptr @.str11174, ptr @.str11175 }, { ptr, ptr } { ptr @.str11176, ptr @.str11177 }, { ptr, ptr } { ptr @.str11178, ptr @.str11179 }, { ptr, ptr } { ptr @.str11180, ptr @.str11181 }, { ptr, ptr } { ptr @.str11182, ptr @.str11183 }, { ptr, ptr } { ptr @.str11184, ptr @.str11185 }, { ptr, ptr } { ptr @.str11186, ptr @.str11187 }, { ptr, ptr } { ptr @.str11188, ptr @.str11189 }, { ptr, ptr } { ptr @.str11190, ptr @.str11191 }, { ptr, ptr } { ptr @.str11192, ptr @.str11193 }, { ptr, ptr } { ptr @.str11194, ptr @.str11195 }, { ptr, ptr } { ptr @.str11196, ptr @.str11197 }, { ptr, ptr } { ptr @.str11198, ptr @.str11199 }, { ptr, ptr } { ptr @.str11200, ptr @.str11201 }, { ptr, ptr } { ptr @.str11202, ptr @.str11203 }, { ptr, ptr } { ptr @.str11204, ptr @.str11205 }, { ptr, ptr } { ptr @.str11206, ptr @.str11207 }, { ptr, ptr } { ptr @.str11208, ptr @.str11209 }, { ptr, ptr } { ptr @.str11210, ptr @.str11211 }, { ptr, ptr } { ptr @.str11212, ptr @.str11213 }, { ptr, ptr } { ptr @.str11214, ptr @.str11215 }, { ptr, ptr } { ptr @.str11216, ptr @.str11217 }]
|
||||
define ptr @lp_mime_of(ptr %path) {
|
||||
entry:
|
||||
%ext = call ptr @lp_path_ext(ptr %path)
|
||||
|
|
@ -12229,7 +12236,7 @@ nx:
|
|||
store i32 %i1, ptr %ip
|
||||
br label %lp
|
||||
def:
|
||||
%d = call ptr @lp_fs_strdup(ptr @.str11211)
|
||||
%d = call ptr @lp_fs_strdup(ptr @.str11218)
|
||||
ret ptr %d
|
||||
}
|
||||
define ptr @lp_mime_lc(ptr %s) {
|
||||
|
|
@ -110113,23 +110120,27 @@ entry:
|
|||
%t125 = alloca i32
|
||||
%t135 = alloca i32
|
||||
%t144 = alloca i32
|
||||
%t167 = alloca i32
|
||||
%t196 = alloca i32
|
||||
%t197 = alloca i32
|
||||
%t216 = alloca ptr
|
||||
%t226 = alloca ptr
|
||||
%t233 = alloca ptr
|
||||
%t235 = alloca ptr
|
||||
%t240 = alloca ptr
|
||||
%t245 = alloca ptr
|
||||
%t255 = alloca ptr
|
||||
%t265 = alloca ptr
|
||||
%t277 = alloca ptr
|
||||
%t280 = alloca ptr
|
||||
%t291 = alloca ptr
|
||||
%t294 = alloca ptr
|
||||
%t309 = alloca i32
|
||||
%t330 = alloca i32
|
||||
%t161 = alloca i32
|
||||
%t170 = alloca i32
|
||||
%t199 = alloca i32
|
||||
%t200 = alloca i32
|
||||
%t219 = alloca ptr
|
||||
%t229 = alloca ptr
|
||||
%t236 = alloca ptr
|
||||
%t238 = alloca ptr
|
||||
%t243 = alloca ptr
|
||||
%t250 = alloca ptr
|
||||
%t260 = alloca ptr
|
||||
%t269 = alloca ptr
|
||||
%t279 = alloca ptr
|
||||
%t289 = alloca ptr
|
||||
%t301 = alloca ptr
|
||||
%t304 = alloca ptr
|
||||
%t307 = alloca ptr
|
||||
%t325 = alloca ptr
|
||||
%t328 = alloca ptr
|
||||
%t343 = alloca i32
|
||||
%t364 = alloca i32
|
||||
store i32 %argc, ptr @L_argc
|
||||
store ptr %argv, ptr @L_argv
|
||||
store i32 0, ptr %retval
|
||||
|
|
@ -110464,284 +110475,335 @@ then70:
|
|||
%t160 = call i32 @fn_ir_flush(ptr null)
|
||||
br label %ret
|
||||
ifend72:
|
||||
%t161 = load i32, ptr @g_g_target_win
|
||||
%t162 = icmp ne i32 %t161, 0
|
||||
br i1 %t162, label %then73, label %ifend75
|
||||
then73:
|
||||
%t163 = load i32, ptr @g_g_windowed
|
||||
%t164 = icmp ne i32 %t163, 0
|
||||
br i1 %t164, label %then76, label %ifend78
|
||||
then76:
|
||||
call void @fn_die(ptr @.str11129)
|
||||
br label %ifend78
|
||||
ifend78:
|
||||
%t162 = load i32, ptr @g_g_target_win
|
||||
%t163 = icmp ne i32 %t162, 0
|
||||
%t164 = zext i1 %t163 to i32
|
||||
store i32 %t164, ptr %t161
|
||||
br i1 %t163, label %sc73, label %scend74
|
||||
sc73:
|
||||
%t165 = load i32, ptr @g_g_uses_http
|
||||
%t166 = icmp ne i32 %t165, 0
|
||||
br i1 %t166, label %then79, label %ifend81
|
||||
then79:
|
||||
call void @fn_die(ptr @.str11130)
|
||||
br label %ifend81
|
||||
ifend81:
|
||||
br label %ifend75
|
||||
ifend75:
|
||||
%t168 = load i32, ptr %t6
|
||||
%t167 = zext i1 %t166 to i32
|
||||
store i32 %t167, ptr %t161
|
||||
br label %scend74
|
||||
scend74:
|
||||
%t168 = load i32, ptr %t161
|
||||
%t169 = icmp ne i32 %t168, 0
|
||||
%t170 = zext i1 %t169 to i32
|
||||
store i32 %t170, ptr %t167
|
||||
br i1 %t169, label %sc82, label %scend83
|
||||
sc82:
|
||||
%t171 = load ptr, ptr %t1
|
||||
%t172 = icmp eq ptr %t171, null
|
||||
br i1 %t169, label %then75, label %ifend77
|
||||
then75:
|
||||
call void @fn_die(ptr @.str11129)
|
||||
br label %ifend77
|
||||
ifend77:
|
||||
%t171 = load i32, ptr %t6
|
||||
%t172 = icmp ne i32 %t171, 0
|
||||
%t173 = zext i1 %t172 to i32
|
||||
%t174 = icmp ne i32 %t173, 0
|
||||
%t175 = zext i1 %t174 to i32
|
||||
store i32 %t175, ptr %t167
|
||||
br label %scend83
|
||||
scend83:
|
||||
%t176 = load i32, ptr %t167
|
||||
store i32 %t173, ptr %t170
|
||||
br i1 %t172, label %sc78, label %scend79
|
||||
sc78:
|
||||
%t174 = load ptr, ptr %t1
|
||||
%t175 = icmp eq ptr %t174, null
|
||||
%t176 = zext i1 %t175 to i32
|
||||
%t177 = icmp ne i32 %t176, 0
|
||||
br i1 %t177, label %then84, label %ifend86
|
||||
then84:
|
||||
%t178 = call i32 @fn_host_is_windows()
|
||||
%t179 = icmp ne i32 %t178, 0
|
||||
br i1 %t179, label %then87, label %else88
|
||||
then87:
|
||||
%t180 = call ptr @fn_getenv_or(ptr @.str11131, ptr @.str11132)
|
||||
%t181 = call ptr @fn_fwd_slashes(ptr %t180)
|
||||
%t182 = call ptr @lp_str_concat(ptr %t181, ptr @.str11133)
|
||||
%t183 = load ptr, ptr %t0
|
||||
%t184 = call ptr @fn_base_name(ptr %t183)
|
||||
%t185 = call ptr @fn_strip_ludic(ptr %t184)
|
||||
%t186 = call ptr @lp_str_concat(ptr %t182, ptr %t185)
|
||||
store ptr %t186, ptr %t1
|
||||
br label %ifend89
|
||||
else88:
|
||||
%t187 = load ptr, ptr %t0
|
||||
%t188 = call ptr @fn_base_name(ptr %t187)
|
||||
%t189 = call ptr @fn_strip_ludic(ptr %t188)
|
||||
%t190 = call ptr @lp_str_concat(ptr @.str11134, ptr %t189)
|
||||
store ptr %t190, ptr %t1
|
||||
br label %ifend89
|
||||
ifend89:
|
||||
br label %ifend86
|
||||
ifend86:
|
||||
%t191 = load i32, ptr @g_g_target_win
|
||||
%t192 = icmp ne i32 %t191, 0
|
||||
br i1 %t192, label %then90, label %ifend92
|
||||
then90:
|
||||
%t193 = load ptr, ptr %t1
|
||||
%t194 = call i64 @strlen(ptr %t193)
|
||||
%t195 = trunc i64 %t194 to i32
|
||||
store i32 %t195, ptr %t196
|
||||
store i32 0, ptr %t197
|
||||
%t198 = load i32, ptr %t196
|
||||
%t199 = icmp sge i32 %t198, 4
|
||||
%t200 = zext i1 %t199 to i32
|
||||
%t201 = icmp ne i32 %t200, 0
|
||||
br i1 %t201, label %then93, label %ifend95
|
||||
then93:
|
||||
%t202 = load ptr, ptr %t1
|
||||
%t203 = load i32, ptr %t196
|
||||
%t204 = sub i32 %t203, 4
|
||||
%t205 = load i32, ptr %t196
|
||||
%t206 = call ptr @lp_str_slice(ptr %t202, i32 %t204, i32 %t205)
|
||||
%t207 = call i32 @lp_str_eq(ptr %t206, ptr @.str11135)
|
||||
store i32 %t207, ptr %t197
|
||||
br label %ifend95
|
||||
ifend95:
|
||||
%t208 = load i32, ptr %t197
|
||||
%t209 = icmp eq i32 %t208, 0
|
||||
%t210 = zext i1 %t209 to i32
|
||||
%t211 = icmp ne i32 %t210, 0
|
||||
br i1 %t211, label %then96, label %ifend98
|
||||
then96:
|
||||
%t212 = load ptr, ptr %t1
|
||||
%t213 = call ptr @lp_str_concat(ptr %t212, ptr @.str11136)
|
||||
store ptr %t213, ptr %t1
|
||||
br label %ifend98
|
||||
ifend98:
|
||||
br label %ifend92
|
||||
ifend92:
|
||||
%t214 = load ptr, ptr %t1
|
||||
%t215 = call ptr @fn_dir_of(ptr %t214)
|
||||
store ptr %t215, ptr %t216
|
||||
%t217 = load ptr, ptr %t216
|
||||
%t218 = call i64 @strlen(ptr %t217)
|
||||
%t219 = trunc i64 %t218 to i32
|
||||
%t220 = icmp sgt i32 %t219, 0
|
||||
%t221 = zext i1 %t220 to i32
|
||||
%t222 = icmp ne i32 %t221, 0
|
||||
br i1 %t222, label %then99, label %ifend101
|
||||
then99:
|
||||
%t223 = load ptr, ptr %t216
|
||||
call void @fn_make_dir(ptr %t223)
|
||||
br label %ifend101
|
||||
ifend101:
|
||||
%t224 = load ptr, ptr %t1
|
||||
%t225 = call ptr @lp_str_concat(ptr %t224, ptr @.str11137)
|
||||
store ptr %t225, ptr %t226
|
||||
%t227 = load ptr, ptr %t226
|
||||
%t228 = call i32 @fn_ir_flush(ptr %t227)
|
||||
%t229 = icmp eq i32 %t228, 0
|
||||
%t230 = zext i1 %t229 to i32
|
||||
%t231 = icmp ne i32 %t230, 0
|
||||
br i1 %t231, label %then102, label %ifend104
|
||||
then102:
|
||||
call void @fn_die(ptr @.str11138)
|
||||
br label %ifend104
|
||||
ifend104:
|
||||
%t232 = call ptr @fn_find_cc()
|
||||
store ptr %t232, ptr %t233
|
||||
%t234 = call ptr @fn_ludic_home()
|
||||
store ptr %t234, ptr %t235
|
||||
%t236 = load ptr, ptr %t233
|
||||
%t237 = call ptr @lp_str_concat(ptr %t236, ptr @.str11139)
|
||||
%t238 = load ptr, ptr %t226
|
||||
%t239 = call ptr @lp_str_concat(ptr %t237, ptr %t238)
|
||||
store ptr %t239, ptr %t240
|
||||
%t241 = load i32, ptr @g_g_windowed
|
||||
%t242 = icmp ne i32 %t241, 0
|
||||
br i1 %t242, label %then105, label %ifend107
|
||||
then105:
|
||||
%t243 = load ptr, ptr %t235
|
||||
%t244 = call ptr @fn_join_path(ptr %t243, ptr @.str11140)
|
||||
store ptr %t244, ptr %t245
|
||||
%t246 = load ptr, ptr %t240
|
||||
%t247 = call ptr @lp_str_concat(ptr %t246, ptr @.str11141)
|
||||
%t248 = load ptr, ptr %t245
|
||||
%t249 = call ptr @lp_str_concat(ptr %t247, ptr %t248)
|
||||
%t250 = call ptr @lp_str_concat(ptr %t249, ptr @.str11142)
|
||||
store ptr %t250, ptr %t240
|
||||
%t251 = load i32, ptr @g_g_uses_audio
|
||||
%t252 = icmp ne i32 %t251, 0
|
||||
br i1 %t252, label %then108, label %ifend110
|
||||
then108:
|
||||
%t253 = load ptr, ptr %t235
|
||||
%t254 = call ptr @fn_join_path(ptr %t253, ptr @.str11143)
|
||||
store ptr %t254, ptr %t255
|
||||
%t256 = load ptr, ptr %t240
|
||||
%t257 = call ptr @lp_str_concat(ptr %t256, ptr @.str11144)
|
||||
%t258 = load ptr, ptr %t255
|
||||
%t259 = call ptr @lp_str_concat(ptr %t257, ptr %t258)
|
||||
%t260 = call ptr @lp_str_concat(ptr %t259, ptr @.str11145)
|
||||
store ptr %t260, ptr %t240
|
||||
br label %ifend110
|
||||
ifend110:
|
||||
br label %ifend107
|
||||
ifend107:
|
||||
%t261 = load i32, ptr @g_g_uses_http
|
||||
%t262 = icmp ne i32 %t261, 0
|
||||
br i1 %t262, label %then111, label %ifend113
|
||||
then111:
|
||||
%t263 = load ptr, ptr %t235
|
||||
%t264 = call ptr @fn_join_path(ptr %t263, ptr @.str11146)
|
||||
store ptr %t264, ptr %t265
|
||||
%t266 = load ptr, ptr %t240
|
||||
%t267 = call ptr @lp_str_concat(ptr %t266, ptr @.str11147)
|
||||
%t268 = load ptr, ptr %t265
|
||||
%t269 = call ptr @lp_str_concat(ptr %t267, ptr %t268)
|
||||
%t270 = call ptr @lp_str_concat(ptr %t269, ptr @.str11148)
|
||||
store ptr %t270, ptr %t240
|
||||
br label %ifend113
|
||||
ifend113:
|
||||
%t271 = load i32, ptr @g_g_uses_gl
|
||||
%t272 = icmp ne i32 %t271, 0
|
||||
br i1 %t272, label %then114, label %ifend116
|
||||
then114:
|
||||
%t273 = load i32, ptr @g_g_target_win
|
||||
%t274 = icmp ne i32 %t273, 0
|
||||
br i1 %t274, label %then117, label %else118
|
||||
then117:
|
||||
%t275 = load ptr, ptr %t235
|
||||
%t276 = call ptr @fn_join_path(ptr %t275, ptr @.str11149)
|
||||
store ptr %t276, ptr %t277
|
||||
%t278 = load ptr, ptr %t235
|
||||
%t279 = call ptr @fn_join_path(ptr %t278, ptr @.str11150)
|
||||
store ptr %t279, ptr %t280
|
||||
%t281 = load ptr, ptr %t240
|
||||
%t282 = call ptr @lp_str_concat(ptr %t281, ptr @.str11151)
|
||||
%t283 = load ptr, ptr %t277
|
||||
%t284 = call ptr @lp_str_concat(ptr %t282, ptr %t283)
|
||||
%t285 = call ptr @lp_str_concat(ptr %t284, ptr @.str11152)
|
||||
%t286 = load ptr, ptr %t280
|
||||
%t287 = call ptr @lp_str_concat(ptr %t285, ptr %t286)
|
||||
%t288 = call ptr @lp_str_concat(ptr %t287, ptr @.str11153)
|
||||
store ptr %t288, ptr %t240
|
||||
br label %ifend119
|
||||
else118:
|
||||
%t289 = load ptr, ptr %t235
|
||||
%t290 = call ptr @fn_join_path(ptr %t289, ptr @.str11154)
|
||||
store ptr %t290, ptr %t291
|
||||
%t292 = load ptr, ptr %t235
|
||||
%t293 = call ptr @fn_join_path(ptr %t292, ptr @.str11155)
|
||||
store ptr %t293, ptr %t294
|
||||
%t295 = load ptr, ptr %t240
|
||||
%t296 = call ptr @lp_str_concat(ptr %t295, ptr @.str11156)
|
||||
%t297 = load ptr, ptr %t291
|
||||
%t298 = call ptr @lp_str_concat(ptr %t296, ptr %t297)
|
||||
%t299 = call ptr @lp_str_concat(ptr %t298, ptr @.str11157)
|
||||
%t300 = load ptr, ptr %t294
|
||||
%t301 = call ptr @lp_str_concat(ptr %t299, ptr %t300)
|
||||
%t302 = call ptr @lp_str_concat(ptr %t301, ptr @.str11158)
|
||||
store ptr %t302, ptr %t240
|
||||
br label %ifend119
|
||||
ifend119:
|
||||
br label %ifend116
|
||||
ifend116:
|
||||
%t303 = load ptr, ptr %t240
|
||||
%t304 = call ptr @lp_str_concat(ptr %t303, ptr @.str11159)
|
||||
%t305 = load ptr, ptr %t1
|
||||
%t306 = call ptr @lp_str_concat(ptr %t304, ptr %t305)
|
||||
store ptr %t306, ptr %t240
|
||||
%t307 = load ptr, ptr %t240
|
||||
%t308 = call i32 @system(ptr %t307)
|
||||
store i32 %t308, ptr %t309
|
||||
%t310 = load i32, ptr %t5
|
||||
%t311 = icmp eq i32 %t310, 0
|
||||
%t312 = zext i1 %t311 to i32
|
||||
%t313 = icmp ne i32 %t312, 0
|
||||
br i1 %t313, label %then120, label %ifend122
|
||||
then120:
|
||||
%t314 = load ptr, ptr %t226
|
||||
call void @fn_remove_file(ptr %t314)
|
||||
br label %ifend122
|
||||
ifend122:
|
||||
%t315 = load i32, ptr %t309
|
||||
%t316 = icmp ne i32 %t315, 0
|
||||
%t317 = zext i1 %t316 to i32
|
||||
%t318 = icmp ne i32 %t317, 0
|
||||
br i1 %t318, label %then123, label %ifend125
|
||||
then123:
|
||||
call void @fn_die(ptr @.str11160)
|
||||
br label %ifend125
|
||||
ifend125:
|
||||
%t319 = load i32, ptr %t6
|
||||
%t320 = icmp ne i32 %t319, 0
|
||||
br i1 %t320, label %then126, label %ifend128
|
||||
then126:
|
||||
%t321 = call i32 @fn_host_is_windows()
|
||||
%t322 = icmp ne i32 %t321, 0
|
||||
br i1 %t322, label %then129, label %ifend131
|
||||
then129:
|
||||
%t323 = load ptr, ptr %t1
|
||||
%t324 = call ptr @fn_win_path(ptr %t323)
|
||||
%t325 = call ptr @lp_str_concat(ptr @.str11161, ptr %t324)
|
||||
%t326 = call ptr @lp_str_concat(ptr %t325, ptr @.str11162)
|
||||
%t327 = call i32 @system(ptr %t326)
|
||||
call void @exit(i32 %t327)
|
||||
%t178 = zext i1 %t177 to i32
|
||||
store i32 %t178, ptr %t170
|
||||
br label %scend79
|
||||
scend79:
|
||||
%t179 = load i32, ptr %t170
|
||||
%t180 = icmp ne i32 %t179, 0
|
||||
br i1 %t180, label %then80, label %ifend82
|
||||
then80:
|
||||
%t181 = call i32 @fn_host_is_windows()
|
||||
%t182 = icmp ne i32 %t181, 0
|
||||
br i1 %t182, label %then83, label %else84
|
||||
then83:
|
||||
%t183 = call ptr @fn_getenv_or(ptr @.str11130, ptr @.str11131)
|
||||
%t184 = call ptr @fn_fwd_slashes(ptr %t183)
|
||||
%t185 = call ptr @lp_str_concat(ptr %t184, ptr @.str11132)
|
||||
%t186 = load ptr, ptr %t0
|
||||
%t187 = call ptr @fn_base_name(ptr %t186)
|
||||
%t188 = call ptr @fn_strip_ludic(ptr %t187)
|
||||
%t189 = call ptr @lp_str_concat(ptr %t185, ptr %t188)
|
||||
store ptr %t189, ptr %t1
|
||||
br label %ifend85
|
||||
else84:
|
||||
%t190 = load ptr, ptr %t0
|
||||
%t191 = call ptr @fn_base_name(ptr %t190)
|
||||
%t192 = call ptr @fn_strip_ludic(ptr %t191)
|
||||
%t193 = call ptr @lp_str_concat(ptr @.str11133, ptr %t192)
|
||||
store ptr %t193, ptr %t1
|
||||
br label %ifend85
|
||||
ifend85:
|
||||
br label %ifend82
|
||||
ifend82:
|
||||
%t194 = load i32, ptr @g_g_target_win
|
||||
%t195 = icmp ne i32 %t194, 0
|
||||
br i1 %t195, label %then86, label %ifend88
|
||||
then86:
|
||||
%t196 = load ptr, ptr %t1
|
||||
%t197 = call i64 @strlen(ptr %t196)
|
||||
%t198 = trunc i64 %t197 to i32
|
||||
store i32 %t198, ptr %t199
|
||||
store i32 0, ptr %t200
|
||||
%t201 = load i32, ptr %t199
|
||||
%t202 = icmp sge i32 %t201, 4
|
||||
%t203 = zext i1 %t202 to i32
|
||||
%t204 = icmp ne i32 %t203, 0
|
||||
br i1 %t204, label %then89, label %ifend91
|
||||
then89:
|
||||
%t205 = load ptr, ptr %t1
|
||||
%t206 = load i32, ptr %t199
|
||||
%t207 = sub i32 %t206, 4
|
||||
%t208 = load i32, ptr %t199
|
||||
%t209 = call ptr @lp_str_slice(ptr %t205, i32 %t207, i32 %t208)
|
||||
%t210 = call i32 @lp_str_eq(ptr %t209, ptr @.str11134)
|
||||
store i32 %t210, ptr %t200
|
||||
br label %ifend91
|
||||
ifend91:
|
||||
%t211 = load i32, ptr %t200
|
||||
%t212 = icmp eq i32 %t211, 0
|
||||
%t213 = zext i1 %t212 to i32
|
||||
%t214 = icmp ne i32 %t213, 0
|
||||
br i1 %t214, label %then92, label %ifend94
|
||||
then92:
|
||||
%t215 = load ptr, ptr %t1
|
||||
%t216 = call ptr @lp_str_concat(ptr %t215, ptr @.str11135)
|
||||
store ptr %t216, ptr %t1
|
||||
br label %ifend94
|
||||
ifend94:
|
||||
br label %ifend88
|
||||
ifend88:
|
||||
%t217 = load ptr, ptr %t1
|
||||
%t218 = call ptr @fn_dir_of(ptr %t217)
|
||||
store ptr %t218, ptr %t219
|
||||
%t220 = load ptr, ptr %t219
|
||||
%t221 = call i64 @strlen(ptr %t220)
|
||||
%t222 = trunc i64 %t221 to i32
|
||||
%t223 = icmp sgt i32 %t222, 0
|
||||
%t224 = zext i1 %t223 to i32
|
||||
%t225 = icmp ne i32 %t224, 0
|
||||
br i1 %t225, label %then95, label %ifend97
|
||||
then95:
|
||||
%t226 = load ptr, ptr %t219
|
||||
call void @fn_make_dir(ptr %t226)
|
||||
br label %ifend97
|
||||
ifend97:
|
||||
%t227 = load ptr, ptr %t1
|
||||
%t228 = call ptr @lp_str_concat(ptr %t227, ptr @.str11136)
|
||||
store ptr %t228, ptr %t229
|
||||
%t230 = load ptr, ptr %t229
|
||||
%t231 = call i32 @fn_ir_flush(ptr %t230)
|
||||
%t232 = icmp eq i32 %t231, 0
|
||||
%t233 = zext i1 %t232 to i32
|
||||
%t234 = icmp ne i32 %t233, 0
|
||||
br i1 %t234, label %then98, label %ifend100
|
||||
then98:
|
||||
call void @fn_die(ptr @.str11137)
|
||||
br label %ifend100
|
||||
ifend100:
|
||||
%t235 = call ptr @fn_find_cc()
|
||||
store ptr %t235, ptr %t236
|
||||
%t237 = call ptr @fn_ludic_home()
|
||||
store ptr %t237, ptr %t238
|
||||
%t239 = load ptr, ptr %t236
|
||||
%t240 = call ptr @lp_str_concat(ptr %t239, ptr @.str11138)
|
||||
%t241 = load ptr, ptr %t229
|
||||
%t242 = call ptr @lp_str_concat(ptr %t240, ptr %t241)
|
||||
store ptr %t242, ptr %t243
|
||||
%t244 = load i32, ptr @g_g_target_win
|
||||
%t245 = icmp ne i32 %t244, 0
|
||||
br i1 %t245, label %then101, label %else102
|
||||
then101:
|
||||
%t246 = load i32, ptr @g_g_windowed
|
||||
%t247 = icmp ne i32 %t246, 0
|
||||
br i1 %t247, label %then104, label %ifend106
|
||||
then104:
|
||||
%t248 = load ptr, ptr %t238
|
||||
%t249 = call ptr @fn_join_path(ptr %t248, ptr @.str11139)
|
||||
store ptr %t249, ptr %t250
|
||||
%t251 = load ptr, ptr %t243
|
||||
%t252 = call ptr @lp_str_concat(ptr %t251, ptr @.str11140)
|
||||
%t253 = load ptr, ptr %t250
|
||||
%t254 = call ptr @lp_str_concat(ptr %t252, ptr %t253)
|
||||
%t255 = call ptr @lp_str_concat(ptr %t254, ptr @.str11141)
|
||||
store ptr %t255, ptr %t243
|
||||
%t256 = load i32, ptr @g_g_uses_audio
|
||||
%t257 = icmp ne i32 %t256, 0
|
||||
br i1 %t257, label %then107, label %ifend109
|
||||
then107:
|
||||
%t258 = load ptr, ptr %t238
|
||||
%t259 = call ptr @fn_join_path(ptr %t258, ptr @.str11142)
|
||||
store ptr %t259, ptr %t260
|
||||
%t261 = load ptr, ptr %t243
|
||||
%t262 = call ptr @lp_str_concat(ptr %t261, ptr @.str11143)
|
||||
%t263 = load ptr, ptr %t260
|
||||
%t264 = call ptr @lp_str_concat(ptr %t262, ptr %t263)
|
||||
store ptr %t264, ptr %t243
|
||||
br label %ifend109
|
||||
ifend109:
|
||||
br label %ifend106
|
||||
ifend106:
|
||||
br label %ifend103
|
||||
else102:
|
||||
%t265 = load i32, ptr @g_g_windowed
|
||||
%t266 = icmp ne i32 %t265, 0
|
||||
br i1 %t266, label %then110, label %ifend112
|
||||
then110:
|
||||
%t267 = load ptr, ptr %t238
|
||||
%t268 = call ptr @fn_join_path(ptr %t267, ptr @.str11144)
|
||||
store ptr %t268, ptr %t269
|
||||
%t270 = load ptr, ptr %t243
|
||||
%t271 = call ptr @lp_str_concat(ptr %t270, ptr @.str11145)
|
||||
%t272 = load ptr, ptr %t269
|
||||
%t273 = call ptr @lp_str_concat(ptr %t271, ptr %t272)
|
||||
%t274 = call ptr @lp_str_concat(ptr %t273, ptr @.str11146)
|
||||
store ptr %t274, ptr %t243
|
||||
%t275 = load i32, ptr @g_g_uses_audio
|
||||
%t276 = icmp ne i32 %t275, 0
|
||||
br i1 %t276, label %then113, label %ifend115
|
||||
then113:
|
||||
%t277 = load ptr, ptr %t238
|
||||
%t278 = call ptr @fn_join_path(ptr %t277, ptr @.str11147)
|
||||
store ptr %t278, ptr %t279
|
||||
%t280 = load ptr, ptr %t243
|
||||
%t281 = call ptr @lp_str_concat(ptr %t280, ptr @.str11148)
|
||||
%t282 = load ptr, ptr %t279
|
||||
%t283 = call ptr @lp_str_concat(ptr %t281, ptr %t282)
|
||||
%t284 = call ptr @lp_str_concat(ptr %t283, ptr @.str11149)
|
||||
store ptr %t284, ptr %t243
|
||||
br label %ifend115
|
||||
ifend115:
|
||||
br label %ifend112
|
||||
ifend112:
|
||||
br label %ifend103
|
||||
ifend103:
|
||||
%t285 = load i32, ptr @g_g_uses_http
|
||||
%t286 = icmp ne i32 %t285, 0
|
||||
br i1 %t286, label %then116, label %ifend118
|
||||
then116:
|
||||
%t287 = load ptr, ptr %t238
|
||||
%t288 = call ptr @fn_join_path(ptr %t287, ptr @.str11150)
|
||||
store ptr %t288, ptr %t289
|
||||
%t290 = load ptr, ptr %t243
|
||||
%t291 = call ptr @lp_str_concat(ptr %t290, ptr @.str11151)
|
||||
%t292 = load ptr, ptr %t289
|
||||
%t293 = call ptr @lp_str_concat(ptr %t291, ptr %t292)
|
||||
%t294 = call ptr @lp_str_concat(ptr %t293, ptr @.str11152)
|
||||
store ptr %t294, ptr %t243
|
||||
br label %ifend118
|
||||
ifend118:
|
||||
%t295 = load i32, ptr @g_g_uses_gl
|
||||
%t296 = icmp ne i32 %t295, 0
|
||||
br i1 %t296, label %then119, label %ifend121
|
||||
then119:
|
||||
%t297 = load i32, ptr @g_g_target_win
|
||||
%t298 = icmp ne i32 %t297, 0
|
||||
br i1 %t298, label %then122, label %else123
|
||||
then122:
|
||||
%t299 = load ptr, ptr %t238
|
||||
%t300 = call ptr @fn_join_path(ptr %t299, ptr @.str11153)
|
||||
store ptr %t300, ptr %t301
|
||||
%t302 = load ptr, ptr %t238
|
||||
%t303 = call ptr @fn_join_path(ptr %t302, ptr @.str11154)
|
||||
store ptr %t303, ptr %t304
|
||||
%t305 = load ptr, ptr %t238
|
||||
%t306 = call ptr @fn_join_path(ptr %t305, ptr @.str11155)
|
||||
store ptr %t306, ptr %t307
|
||||
%t308 = load i32, ptr @g_g_windowed
|
||||
%t309 = icmp ne i32 %t308, 0
|
||||
br i1 %t309, label %then125, label %ifend127
|
||||
then125:
|
||||
%t310 = load ptr, ptr %t238
|
||||
%t311 = call ptr @fn_join_path(ptr %t310, ptr @.str11156)
|
||||
store ptr %t311, ptr %t307
|
||||
br label %ifend127
|
||||
ifend127:
|
||||
%t312 = load ptr, ptr %t243
|
||||
%t313 = call ptr @lp_str_concat(ptr %t312, ptr @.str11157)
|
||||
%t314 = load ptr, ptr %t301
|
||||
%t315 = call ptr @lp_str_concat(ptr %t313, ptr %t314)
|
||||
%t316 = call ptr @lp_str_concat(ptr %t315, ptr @.str11158)
|
||||
%t317 = load ptr, ptr %t304
|
||||
%t318 = call ptr @lp_str_concat(ptr %t316, ptr %t317)
|
||||
%t319 = call ptr @lp_str_concat(ptr %t318, ptr @.str11159)
|
||||
%t320 = load ptr, ptr %t307
|
||||
%t321 = call ptr @lp_str_concat(ptr %t319, ptr %t320)
|
||||
%t322 = call ptr @lp_str_concat(ptr %t321, ptr @.str11160)
|
||||
store ptr %t322, ptr %t243
|
||||
br label %ifend124
|
||||
else123:
|
||||
%t323 = load ptr, ptr %t238
|
||||
%t324 = call ptr @fn_join_path(ptr %t323, ptr @.str11161)
|
||||
store ptr %t324, ptr %t325
|
||||
%t326 = load ptr, ptr %t238
|
||||
%t327 = call ptr @fn_join_path(ptr %t326, ptr @.str11162)
|
||||
store ptr %t327, ptr %t328
|
||||
%t329 = load ptr, ptr %t243
|
||||
%t330 = call ptr @lp_str_concat(ptr %t329, ptr @.str11163)
|
||||
%t331 = load ptr, ptr %t325
|
||||
%t332 = call ptr @lp_str_concat(ptr %t330, ptr %t331)
|
||||
%t333 = call ptr @lp_str_concat(ptr %t332, ptr @.str11164)
|
||||
%t334 = load ptr, ptr %t328
|
||||
%t335 = call ptr @lp_str_concat(ptr %t333, ptr %t334)
|
||||
%t336 = call ptr @lp_str_concat(ptr %t335, ptr @.str11165)
|
||||
store ptr %t336, ptr %t243
|
||||
br label %ifend124
|
||||
ifend124:
|
||||
br label %ifend121
|
||||
ifend121:
|
||||
%t337 = load ptr, ptr %t243
|
||||
%t338 = call ptr @lp_str_concat(ptr %t337, ptr @.str11166)
|
||||
%t339 = load ptr, ptr %t1
|
||||
%t340 = call ptr @lp_str_concat(ptr %t338, ptr %t339)
|
||||
store ptr %t340, ptr %t243
|
||||
%t341 = load ptr, ptr %t243
|
||||
%t342 = call i32 @system(ptr %t341)
|
||||
store i32 %t342, ptr %t343
|
||||
%t344 = load i32, ptr %t5
|
||||
%t345 = icmp eq i32 %t344, 0
|
||||
%t346 = zext i1 %t345 to i32
|
||||
%t347 = icmp ne i32 %t346, 0
|
||||
br i1 %t347, label %then128, label %ifend130
|
||||
then128:
|
||||
%t348 = load ptr, ptr %t229
|
||||
call void @fn_remove_file(ptr %t348)
|
||||
br label %ifend130
|
||||
ifend130:
|
||||
%t349 = load i32, ptr %t343
|
||||
%t350 = icmp ne i32 %t349, 0
|
||||
%t351 = zext i1 %t350 to i32
|
||||
%t352 = icmp ne i32 %t351, 0
|
||||
br i1 %t352, label %then131, label %ifend133
|
||||
then131:
|
||||
call void @fn_die(ptr @.str11167)
|
||||
br label %ifend133
|
||||
ifend133:
|
||||
%t353 = load i32, ptr %t6
|
||||
%t354 = icmp ne i32 %t353, 0
|
||||
br i1 %t354, label %then134, label %ifend136
|
||||
then134:
|
||||
%t355 = call i32 @fn_host_is_windows()
|
||||
%t356 = icmp ne i32 %t355, 0
|
||||
br i1 %t356, label %then137, label %ifend139
|
||||
then137:
|
||||
%t357 = load ptr, ptr %t1
|
||||
%t358 = call ptr @fn_win_path(ptr %t357)
|
||||
%t359 = call ptr @lp_str_concat(ptr @.str11168, ptr %t358)
|
||||
%t360 = call ptr @lp_str_concat(ptr %t359, ptr @.str11169)
|
||||
%t361 = call i32 @system(ptr %t360)
|
||||
call void @exit(i32 %t361)
|
||||
unreachable
|
||||
ifend131:
|
||||
%t328 = load ptr, ptr %t1
|
||||
%t329 = call i32 @system(ptr %t328)
|
||||
store i32 %t329, ptr %t330
|
||||
%t331 = load i32, ptr %t330
|
||||
%t332 = lshr i32 %t331, 8
|
||||
%t333 = and i32 %t332, 255
|
||||
call void @exit(i32 %t333)
|
||||
ifend139:
|
||||
%t362 = load ptr, ptr %t1
|
||||
%t363 = call i32 @system(ptr %t362)
|
||||
store i32 %t363, ptr %t364
|
||||
%t365 = load i32, ptr %t364
|
||||
%t366 = lshr i32 %t365, 8
|
||||
%t367 = and i32 %t366, 255
|
||||
call void @exit(i32 %t367)
|
||||
unreachable
|
||||
ifend128:
|
||||
ifend136:
|
||||
br label %ret
|
||||
ret:
|
||||
%t334 = load i32, ptr %retval
|
||||
ret i32 %t334
|
||||
%t368 = load i32, ptr %retval
|
||||
ret i32 %t368
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,13 +199,9 @@ entry {
|
|||
if emit_ir { ir_flush(out); return }
|
||||
if not has_target { ir_flush(null); return }
|
||||
|
||||
# The Windows runtime is the libc surface so far: a window, audio, HTTP and GL
|
||||
# are macOS platform layers with no Windows counterpart yet, and linking one
|
||||
# would fail on a hundred Objective-C symbols rather than say so.
|
||||
if g_target_win {
|
||||
if g_windowed { die("ludicc: a windowed build is not available on Windows yet; build with --headless\n") }
|
||||
if g_uses_http { die("ludicc: Http.* is not available on Windows yet\n") }
|
||||
}
|
||||
# Http.* is still a macOS platform layer (NSURLConnection) with no Windows
|
||||
# counterpart; linking it would fail on Objective-C symbols rather than say so.
|
||||
if g_target_win and g_uses_http { die("ludicc: Http.* is not available on Windows yet\n") }
|
||||
|
||||
# a run with no explicit -o lands in a temp file
|
||||
if run and (out == null) {
|
||||
|
|
@ -236,7 +232,19 @@ entry {
|
|||
# substitutes the host's and warns about it on every single build. There is
|
||||
# nothing to act on — the host default is exactly what we want — so it is off.
|
||||
var cmd = `{cc} -O2 -Wno-override-module {ll}`
|
||||
if g_windowed {
|
||||
if g_target_win {
|
||||
# The Windows window: win32.ll (user32, gdi32 for the software present, xinput
|
||||
# for pads), and audio_win.ll when the program uses Audio.*, as on macOS.
|
||||
if g_windowed {
|
||||
let win32 = join_path(home, "runtime/native/win32.ll")
|
||||
cmd = `{cmd} {win32} -luser32 -lgdi32 -lxinput`
|
||||
if g_uses_audio {
|
||||
let audiow = join_path(home, "runtime/native/audio_win.ll")
|
||||
cmd = `{cmd} {audiow}`
|
||||
}
|
||||
}
|
||||
}
|
||||
else { if g_windowed {
|
||||
let cocoa = join_path(home, "runtime/native/cocoa.ll")
|
||||
# GameController holds no symbol cocoa.ll references directly (its classes are
|
||||
# reached by name through objc_getClass), so a plain -framework link gets
|
||||
|
|
@ -250,7 +258,7 @@ entry {
|
|||
let audio = join_path(home, "runtime/native/audio.ll")
|
||||
cmd = `{cmd} {audio} -Wl,-needed_framework,AVFoundation`
|
||||
}
|
||||
}
|
||||
} }
|
||||
# Http.* (#6) links the native transport and Foundation (NSURLConnection etc.,
|
||||
# reached by name). Works headless too, so it is outside the windowed block —
|
||||
# macOS-only for now, which is where the toolchain runs.
|
||||
|
|
@ -261,12 +269,15 @@ entry {
|
|||
# Gl.* links the OpenGL backend: gl.ll (offscreen contexts, float helpers), the
|
||||
# generated per-entry-point ABI thunks, and OpenGL.framework. Windowed or not.
|
||||
# On Windows the same pair is gl_win.ll (a WGL context) and gl_thunks_win.ll (the
|
||||
# thunks through a table wglGetProcAddress fills), against opengl32/gdi32/user32.
|
||||
# thunks through a table wglGetProcAddress fills), against opengl32/gdi32/user32,
|
||||
# with the window half from win32_gl.ll - or, headless, gl_win_nowin.ll's stubs.
|
||||
if g_uses_gl {
|
||||
if g_target_win {
|
||||
let glw = join_path(home, "runtime/native/gl_win.ll")
|
||||
let gltw = join_path(home, "runtime/native/gl_thunks_win.ll")
|
||||
cmd = `{cmd} {glw} {gltw} -luser32 -lgdi32 -lopengl32`
|
||||
var glhalf = join_path(home, "runtime/native/gl_win_nowin.ll")
|
||||
if g_windowed { glhalf = join_path(home, "runtime/native/win32_gl.ll") }
|
||||
cmd = `{cmd} {glw} {gltw} {glhalf} -luser32 -lgdi32 -lopengl32`
|
||||
} else {
|
||||
let gl = join_path(home, "runtime/native/gl.ll")
|
||||
let glt = join_path(home, "runtime/native/gl_thunks.ll")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue