feat(windows): sound, through XAudio2

audio_win.ll implements audio.ll's snd_* contract over XAudio2 from IR: a
source voice per clip, restart on play, LoopCount for loops, SetVolume,
SetFrequencyRatio and a balance pan through SetOutputMatrix, with the COM
slots taken from the SDK's xaudio2.h. Clips are RIFF WAVE read through
lp_pak_open (weakly referenced), so a packed sound loads directly. ludicc links
it with xaudio2 and ole32, and silences xinput.lib's importeddllmain warning.

Verified: ludic-dev test 135/135, selfhost-test 32/32; on the PC a harness
loads, plays, pans, loops and stops clips, and Maroon Lake windowed reports
"sound: 31 of 31 clips loaded".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-13 02:42:48 +03:00
parent 00d25dcc3e
commit 3300fb3957
4 changed files with 646 additions and 231 deletions

View file

@ -22,9 +22,12 @@ type: feat
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.
- **Sound** — `audio_win.ll` is `audio.ll`'s contract over XAudio2: one source voice per
clip, loops, volume, rate and a balance pan through the output matrix, RIFF WAVE in PCM or
float. It reads a clip through the asset pack, so a bundled game's first `Audio.load`
succeeds - AVAudioPlayer takes a filesystem path, which is why macOS cannot.
- **Not yet** — 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

View file

@ -1,36 +1,444 @@
; ============================================================================
; audio_win.ll — the Windows sound backend (audio.ll's snd_* contract).
; audio_win.ll — the Windows audio backend, written in LLVM IR.
;
; 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.
; audio.ll's contract over XAudio2 (xaudio2_9.dll, on every Windows 10 and 11).
; ludicc links it into a windowed Windows build that uses Audio.*, with xaudio2
; and ole32. A sound is loaded once into a player and the opaque player pointer
; goes back to audio.ludic, which keeps the handle table.
;
; snd_load(path) -> player snd_play(p, loops, rate, vol)
; snd_stop(p) snd_playing(p) -> bool
; snd_set_volume(p, vol) snd_set_rate(p, rate) snd_set_pan(p, pan)
; loops: 0 = once, -1 = forever, n = n more times. rate / vol / pan are 16.16 fixed.
;
; A player is one XAudio2 source voice holding one clip, which is what an
; AVAudioPlayer is: firing it again restarts it rather than layering a copy.
;
; Only RIFF WAVE is read - PCM or IEEE float, any rate and channel count - because
; that is what a Ludic game ships (AVAudioPlayer also reads MP3 and AAC; a game that
; wants those on Windows wants a decoder here first).
;
; The clip's bytes come through @lp_pak_open when the program has it, so a sound
; inside a shipped game's pack loads like every other asset. On macOS
; AVAudioPlayer takes a filesystem path and the pack is invisible to it, which is
; the reason Maroon Lake's sound_load() copies clips out of the pack; here the
; first Audio.load already succeeds. lp_pak_open is referenced weakly: a program
; that never opens a file has no pack runtime, and then the file is opened directly.
;
; COM, spoken from IR: every object's first word is its vtable, and a method is a
; load from a fixed slot. The slots are xaudio2.h's declaration order:
; IXAudio2 5 CreateSourceVoice 7 CreateMasteringVoice
; IXAudio2Voice 0 GetVoiceDetails 12 SetVolume 16 SetOutputMatrix 18 DestroyVoice
; IXAudio2SourceVoice (after the 19 above) 19 Start 20 Stop 21 SubmitSourceBuffer
; 22 FlushSourceBuffers 25 GetState 26 SetFrequencyRatio
; IXAudio2Voice does not derive from IUnknown, so its slot 0 is GetVoiceDetails.
; ============================================================================
define ptr @snd_load(ptr %path) {
declare i32 @CoInitializeEx(ptr, i32)
declare i32 @XAudio2Create(ptr, i32, i32)
declare extern_weak ptr @lp_pak_open(ptr, ptr)
declare ptr @_fsopen(ptr, ptr, i32)
declare i32 @_fseeki64(ptr, i64, i32)
declare i64 @_ftelli64(ptr)
declare i64 @fread(ptr, i64, i64, ptr)
declare i32 @fclose(ptr)
declare ptr @malloc(i64)
declare void @free(ptr)
declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
@.a_rb = private unnamed_addr constant [3 x i8] c"rb\00"
@A_xa = internal global ptr null ; IXAudio2
@A_master = internal global ptr null ; IXAudio2MasteringVoice
@A_mch = internal global i32 2 ; the mastering voice's channel count
@A_tried = internal global i32 0 ; the engine is attempted once, not per clip
; the method in slot %slot of a COM object's vtable
define internal ptr @a_fn(ptr %obj, i64 %slot) {
entry:
ret ptr null
%vt = load ptr, ptr %obj
%p = getelementptr ptr, ptr %vt, i64 %slot
%f = load ptr, ptr %p
ret ptr %f
}
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) {
; 1 when the engine and its mastering voice exist. A machine with no audio device
; fails here once and every later call is silent, as a headless build is.
define internal i32 @a_engine() {
entry:
%xap = alloca ptr, align 8
%mvp = alloca ptr, align 8
%det = alloca [16 x i8], align 4
%have = load ptr, ptr @A_xa
%up = icmp ne ptr %have, null
br i1 %up, label %yes, label %first
first:
%tried = load i32, ptr @A_tried
%again = icmp ne i32 %tried, 0
br i1 %again, label %no, label %make
make:
store i32 1, ptr @A_tried
; COINIT_MULTITHREADED; S_FALSE (already initialised) and RPC_E_CHANGED_MODE are both fine
%ci = call i32 @CoInitializeEx(ptr null, i32 0)
store ptr null, ptr %xap
%hr = call i32 @XAudio2Create(ptr %xap, i32 0, i32 0) ; XAUDIO2_USE_DEFAULT_PROCESSOR
%bad = icmp slt i32 %hr, 0
br i1 %bad, label %no, label %master
master:
%xa = load ptr, ptr %xap
store ptr %xa, ptr @A_xa
store ptr null, ptr %mvp
%cmv = call ptr @a_fn(ptr %xa, i64 7)
; default channels and rate, no flags, the default device, no effects, AudioCategory_GameEffects (6)
%hr2 = call i32 %cmv(ptr %xa, ptr %mvp, i32 0, i32 0, i32 0, ptr null, ptr null, i32 6)
%bad2 = icmp slt i32 %hr2, 0
br i1 %bad2, label %nomaster, label %details
nomaster:
store ptr null, ptr @A_xa
br label %no
details:
%mv = load ptr, ptr %mvp
store ptr %mv, ptr @A_master
call void @llvm.memset.p0.i64(ptr %det, i8 0, i64 16, i1 false)
%gvd = call ptr @a_fn(ptr %mv, i64 0)
call void %gvd(ptr %mv, ptr %det)
%chp = getelementptr i8, ptr %det, i64 8 ; XAUDIO2_VOICE_DETAILS.InputChannels
%ch = load i32, ptr %chp
store i32 %ch, ptr @A_mch
br label %yes
yes:
ret i32 1
no:
ret i32 0
}
; Player: voice 0, file bytes 8, sample data 16, data bytes 24, channels 28, started 32.
define ptr @snd_load(ptr %path) {
entry:
%wfx = alloca [20 x i8], align 4 ; WAVEFORMATEX, 18 bytes packed
%vpp = alloca ptr, align 8
%offp = alloca i32, align 4
%fmtok = alloca i32, align 4
%doffp = alloca i32, align 4
%dlenp = alloca i32, align 4
%nopath = icmp eq ptr %path, null
br i1 %nopath, label %fail, label %eng
eng:
%e = call i32 @a_engine()
%noeng = icmp eq i32 %e, 0
br i1 %noeng, label %fail, label %open
open:
%haspak = icmp ne ptr @lp_pak_open, null
br i1 %haspak, label %viapak, label %direct
viapak:
%fp = call ptr @lp_pak_open(ptr %path, ptr @.a_rb)
br label %opened
direct:
%fd = call ptr @_fsopen(ptr %path, ptr @.a_rb, i32 64) ; _SH_DENYNO
br label %opened
opened:
%f = phi ptr [ %fp, %viapak ], [ %fd, %direct ]
%nof = icmp eq ptr %f, null
br i1 %nof, label %fail, label %size
size:
%s1 = call i32 @_fseeki64(ptr %f, i64 0, i32 2)
%n64 = call i64 @_ftelli64(ptr %f)
%s2 = call i32 @_fseeki64(ptr %f, i64 0, i32 0)
%small = icmp slt i64 %n64, 44
%huge = icmp sgt i64 %n64, 2147483647
%nogo = or i1 %small, %huge
br i1 %nogo, label %closefail, label %read
closefail:
%c0 = call i32 @fclose(ptr %f)
br label %fail
read:
%buf = call ptr @malloc(i64 %n64)
%rd = call i64 @fread(ptr %buf, i64 1, i64 %n64, ptr %f)
%c1 = call i32 @fclose(ptr %f)
%n = trunc i64 %rd to i32
%riff = load i32, ptr %buf
%isriff = icmp eq i32 %riff, 1179011410 ; "RIFF"
%wavep = getelementptr i8, ptr %buf, i64 8
%wave = load i32, ptr %wavep
%iswave = icmp eq i32 %wave, 1163280727 ; "WAVE"
%okhdr = and i1 %isriff, %iswave
br i1 %okhdr, label %chunks, label %freefail
chunks:
store i32 12, ptr %offp
store i32 0, ptr %fmtok
store i32 -1, ptr %doffp
store i32 0, ptr %dlenp
br label %walk
walk:
%off = load i32, ptr %offp
%hdrend = add i32 %off, 8
%fits = icmp sle i32 %hdrend, %n
br i1 %fits, label %chunk, label %walked
chunk:
%idp = getelementptr i8, ptr %buf, i32 %off
%id = load i32, ptr %idp, align 1
%szo = add i32 %off, 4
%szp = getelementptr i8, ptr %buf, i32 %szo
%sz = load i32, ptr %szp, align 1
%isfmt = icmp eq i32 %id, 544501094 ; "fmt "
br i1 %isfmt, label %fmt, label %notfmt
fmt:
%fmtbig = icmp sge i32 %sz, 16
br i1 %fmtbig, label %fmtcopy, label %advance
fmtcopy:
%body = getelementptr i8, ptr %buf, i32 %hdrend
call void @llvm.memset.p0.i64(ptr %wfx, i8 0, i64 20, i1 false)
call void @llvm.memcpy.p0.p0.i64(ptr %wfx, ptr %body, i64 16, i1 false) ; cbSize stays 0
store i32 1, ptr %fmtok
br label %advance
notfmt:
%isdata = icmp eq i32 %id, 1635017060 ; "data"
br i1 %isdata, label %data, label %advance
data:
store i32 %hdrend, ptr %doffp
%left = sub i32 %n, %hdrend
%over = icmp sgt i32 %sz, %left
%dl = select i1 %over, i32 %left, i32 %sz
store i32 %dl, ptr %dlenp
br label %advance
advance:
; chunks are padded to an even length; a negative size would walk backwards, so stop
%neg = icmp slt i32 %sz, 0
br i1 %neg, label %walked, label %step
step:
%pad = and i32 %sz, 1
%adv = add i32 %sz, %pad
%next = add i32 %hdrend, %adv
store i32 %next, ptr %offp
br label %walk
walked:
%gotfmt = load i32, ptr %fmtok
%hasfmt = icmp ne i32 %gotfmt, 0
%doff = load i32, ptr %doffp
%hasdata = icmp sge i32 %doff, 0
%both = and i1 %hasfmt, %hasdata
br i1 %both, label %format, label %freefail
format:
; WAVE_FORMAT_PCM (1) or WAVE_FORMAT_IEEE_FLOAT (3)
%tag = load i16, ptr %wfx
%pcm = icmp eq i16 %tag, 1
%flt = icmp eq i16 %tag, 3
%known = or i1 %pcm, %flt
br i1 %known, label %voice, label %freefail
voice:
%xa = load ptr, ptr @A_xa
store ptr null, ptr %vpp
%csv = call ptr @a_fn(ptr %xa, i64 5)
; no flags, a pitch range up to 4x, no callback, the mastering voice, no effects
%hr = call i32 %csv(ptr %xa, ptr %vpp, ptr %wfx, i32 0, float 4.000000e+00, ptr null, ptr null, ptr null)
%badv = icmp slt i32 %hr, 0
br i1 %badv, label %freefail, label %keep
keep:
%v = load ptr, ptr %vpp
%p = call ptr @malloc(i64 40)
store ptr %v, ptr %p
%pbuf = getelementptr i8, ptr %p, i64 8
store ptr %buf, ptr %pbuf
%pdat = getelementptr i8, ptr %p, i64 16
%dptr = getelementptr i8, ptr %buf, i32 %doff
store ptr %dptr, ptr %pdat
%plen = getelementptr i8, ptr %p, i64 24
%dlen = load i32, ptr %dlenp
store i32 %dlen, ptr %plen
%pch = getelementptr i8, ptr %p, i64 28
%chp = getelementptr i8, ptr %wfx, i64 2
%ch16 = load i16, ptr %chp
%ch = zext i16 %ch16 to i32
store i32 %ch, ptr %pch
%pst = getelementptr i8, ptr %p, i64 32
store i32 0, ptr %pst
ret ptr %p
freefail:
call void @free(ptr %buf)
br label %fail
fail:
ret ptr null
}
; a 16.16 value as a float, clamped to [lo, hi]
define internal float @a_fx(i32 %v, float %lo, float %hi) {
entry:
%f = sitofp i32 %v to float
%s = fdiv float %f, 6.553600e+04
%under = fcmp olt float %s, %lo
%s1 = select i1 %under, float %lo, float %s
%over = fcmp ogt float %s1, %hi
%s2 = select i1 %over, float %hi, float %s1
ret float %s2
}
; stop the voice and drop what it had queued
define internal void @a_halt(ptr %p) {
entry:
%v = load ptr, ptr %p
%stop = call ptr @a_fn(ptr %v, i64 20)
%r1 = call i32 %stop(ptr %v, i32 0, i32 0)
%flush = call ptr @a_fn(ptr %v, i64 22)
%r2 = call i32 %flush(ptr %v)
%pst = getelementptr i8, ptr %p, i64 32
store i32 0, ptr %pst
ret void
}
; rewind to the start and play, with loops / rate / volume
define void @snd_play(ptr %p, i32 %loops, i32 %rate, i32 %vol) {
entry:
%xb = alloca [48 x i8], align 8
%nil = icmp eq ptr %p, null
br i1 %nil, label %out, label %go
go:
call void @a_halt(ptr %p)
%v = load ptr, ptr %p
; XAUDIO2_BUFFER: Flags 0, AudioBytes 4, pAudioData 8, PlayBegin 16, PlayLength 20,
; LoopBegin 24, LoopLength 28, LoopCount 32, pContext 40
call void @llvm.memset.p0.i64(ptr %xb, i8 0, i64 48, i1 false)
store i32 64, ptr %xb ; XAUDIO2_END_OF_STREAM
%plen = getelementptr i8, ptr %p, i64 24
%len = load i32, ptr %plen
%xlen = getelementptr i8, ptr %xb, i64 4
store i32 %len, ptr %xlen
%pdat = getelementptr i8, ptr %p, i64 16
%dat = load ptr, ptr %pdat
%xdat = getelementptr i8, ptr %xb, i64 8
store ptr %dat, ptr %xdat
; -1 forever (XAUDIO2_LOOP_INFINITE, 255); n more times, at most 254
%forever = icmp slt i32 %loops, 0
%many = icmp sgt i32 %loops, 254
%capped = select i1 %many, i32 254, i32 %loops
%count = select i1 %forever, i32 255, i32 %capped
%xlc = getelementptr i8, ptr %xb, i64 32
store i32 %count, ptr %xlc
%submit = call ptr @a_fn(ptr %v, i64 21)
%hr = call i32 %submit(ptr %v, ptr %xb, ptr null)
%bad = icmp slt i32 %hr, 0
br i1 %bad, label %out, label %levels
levels:
%fv = call float @a_fx(i32 %vol, float 0.000000e+00, float 4.000000e+00)
%setv = call ptr @a_fn(ptr %v, i64 12)
%r3 = call i32 %setv(ptr %v, float %fv, i32 0)
%fr = call float @a_fx(i32 %rate, float 0x3F847AE140000000, float 4.000000e+00)
%setr = call ptr @a_fn(ptr %v, i64 26)
%r4 = call i32 %setr(ptr %v, float %fr, i32 0)
%start = call ptr @a_fn(ptr %v, i64 19)
%r5 = call i32 %start(ptr %v, i32 0, i32 0)
%pst = getelementptr i8, ptr %p, i64 32
store i32 1, ptr %pst
br label %out
out:
ret void
}
define void @snd_stop(ptr %p) {
entry:
%nil = icmp eq ptr %p, null
br i1 %nil, label %out, label %go
go:
call void @a_halt(ptr %p)
br label %out
out:
ret void
}
; playing: started, and the clip is still queued (it leaves the queue when it ends)
define i32 @snd_playing(ptr %p) {
entry:
%state = alloca [24 x i8], align 8
%nil = icmp eq ptr %p, null
br i1 %nil, label %zero, label %started
started:
%pst = getelementptr i8, ptr %p, i64 32
%st = load i32, ptr %pst
%was = icmp ne i32 %st, 0
br i1 %was, label %ask, label %zero
ask:
%v = load ptr, ptr %p
call void @llvm.memset.p0.i64(ptr %state, i8 0, i64 24, i1 false)
%gs = call ptr @a_fn(ptr %v, i64 25)
call void %gs(ptr %v, ptr %state, i32 256) ; XAUDIO2_VOICE_NOSAMPLESPLAYED
%qp = getelementptr i8, ptr %state, i64 8 ; BuffersQueued
%q = load i32, ptr %qp
%busy = icmp ugt i32 %q, 0
%r = zext i1 %busy to i32
ret i32 %r
zero:
ret i32 0
}
define void @snd_set_volume(ptr %p, i32 %vol) {
entry:
%nil = icmp eq ptr %p, null
br i1 %nil, label %out, label %go
go:
%v = load ptr, ptr %p
%fv = call float @a_fx(i32 %vol, float 0.000000e+00, float 4.000000e+00)
%setv = call ptr @a_fn(ptr %v, i64 12)
%r = call i32 %setv(ptr %v, float %fv, i32 0)
br label %out
out:
ret void
}
define void @snd_set_rate(ptr %p, i32 %rate) {
entry:
%nil = icmp eq ptr %p, null
br i1 %nil, label %out, label %go
go:
%v = load ptr, ptr %p
%fr = call float @a_fx(i32 %rate, float 0x3F847AE140000000, float 4.000000e+00)
%setr = call ptr @a_fn(ptr %v, i64 26)
%r = call i32 %setr(ptr %v, float %fr, i32 0)
br label %out
out:
ret void
}
; Stereo position, -1.0 (hard left) .. 1.0 (hard right), as a balance: the centre
; leaves both sides at full level and a side pan turns the other side down. A mono
; clip feeds both front channels; a stereo clip keeps its left and right. Channels
; beyond the front pair (a 5.1 device) get nothing, which is where a stereo mix sits.
define void @snd_set_pan(ptr %p, i32 %pan) {
entry:
%mat = alloca [64 x float], align 4
%nil = icmp eq ptr %p, null
br i1 %nil, label %out, label %chk
chk:
%mch = load i32, ptr @A_mch
%stereo = icmp sge i32 %mch, 2
%big = icmp sgt i32 %mch, 8
%okm = xor i1 %big, true
%usem = and i1 %stereo, %okm
br i1 %usem, label %go, label %out
go:
%pch = getelementptr i8, ptr %p, i64 28
%ch = load i32, ptr %pch
%f = call float @a_fx(i32 %pan, float -1.000000e+00, float 1.000000e+00)
%rightward = fcmp ogt float %f, 0.000000e+00
%l0 = fsub float 1.000000e+00, %f
%left = select i1 %rightward, float %l0, float 1.000000e+00
%r0 = fadd float 1.000000e+00, %f
%right = select i1 %rightward, float 1.000000e+00, float %r0
%mono = icmp eq i32 %ch, 1
%two = icmp eq i32 %ch, 2
%known = or i1 %mono, %two
br i1 %known, label %fill, label %out
fill:
; the matrix is [destination][source], row-major
call void @llvm.memset.p0.i64(ptr %mat, i8 0, i64 256, i1 false)
store float %left, ptr %mat
%ri = select i1 %mono, i64 1, i64 3 ; mono: dst1,src0 = 1; stereo: dst1,src1 = 3
%rp = getelementptr float, ptr %mat, i64 %ri
store float %right, ptr %rp
%v = load ptr, ptr %p
%master = load ptr, ptr @A_master
%setm = call ptr @a_fn(ptr %v, i64 16)
%r = call i32 %setm(ptr %v, ptr %master, i32 %ch, i32 %mch, ptr %mat, i32 0)
br label %out
out:
ret void
}

View file

@ -11326,35 +11326,36 @@ declare void @hs_free(i32)
@.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"
@.str11141 = private unnamed_addr constant [55 x i8] c" -luser32 -lgdi32 -lxinput -Wl,/ignore:importeddllmain\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 [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"
@.str11144 = private unnamed_addr constant [19 x i8] c" -lxaudio2 -lole32\00"
@.str11145 = private unnamed_addr constant [24 x i8] c"runtime/native/cocoa.ll\00"
@.str11146 = private unnamed_addr constant [2 x i8] c" \00"
@.str11147 = private unnamed_addr constant [79 x i8] c" -framework Cocoa -Wl,-needed_framework,GameController -Wl,-rpath,@loader_path\00"
@.str11148 = private unnamed_addr constant [24 x i8] c"runtime/native/audio.ll\00"
@.str11149 = private unnamed_addr constant [2 x i8] c" \00"
@.str11150 = private unnamed_addr constant [36 x i8] c" -Wl,-needed_framework,AVFoundation\00"
@.str11151 = private unnamed_addr constant [23 x i8] c"runtime/native/http.ll\00"
@.str11152 = private unnamed_addr constant [2 x i8] c" \00"
@.str11153 = private unnamed_addr constant [34 x i8] c" -Wl,-needed_framework,Foundation\00"
@.str11154 = private unnamed_addr constant [25 x i8] c"runtime/native/gl_win.ll\00"
@.str11155 = private unnamed_addr constant [32 x i8] c"runtime/native/gl_thunks_win.ll\00"
@.str11156 = private unnamed_addr constant [31 x i8] c"runtime/native/gl_win_nowin.ll\00"
@.str11157 = private unnamed_addr constant [27 x i8] c"runtime/native/win32_gl.ll\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"
@.str11160 = private unnamed_addr constant [2 x i8] c" \00"
@.str11161 = private unnamed_addr constant [29 x i8] c" -luser32 -lgdi32 -lopengl32\00"
@.str11162 = private unnamed_addr constant [21 x i8] c"runtime/native/gl.ll\00"
@.str11163 = private unnamed_addr constant [28 x i8] c"runtime/native/gl_thunks.ll\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"
@.str11165 = private unnamed_addr constant [2 x i8] c" \00"
@.str11166 = private unnamed_addr constant [19 x i8] c" -framework OpenGL\00"
@.str11167 = private unnamed_addr constant [5 x i8] c" -o \00"
@.str11168 = private unnamed_addr constant [21 x i8] c"ludicc: link failed\0A\00"
@.str11169 = private unnamed_addr constant [2 x i8] c"\22\00"
@.str11170 = private unnamed_addr constant [2 x i8] c"\22\00"
define i32 @lp_str_eq(ptr %a, ptr %b) {
entry:
br label %loop
@ -12159,56 +12160,56 @@ sod:
store i32 %fcnt, ptr %d2
ret ptr %h
}
@.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 }]
@.str11171 = private unnamed_addr constant [4 x i8] c"png\00"
@.str11172 = private unnamed_addr constant [10 x i8] c"image/png\00"
@.str11173 = private unnamed_addr constant [4 x i8] c"jpg\00"
@.str11174 = private unnamed_addr constant [11 x i8] c"image/jpeg\00"
@.str11175 = private unnamed_addr constant [5 x i8] c"jpeg\00"
@.str11176 = private unnamed_addr constant [11 x i8] c"image/jpeg\00"
@.str11177 = private unnamed_addr constant [4 x i8] c"gif\00"
@.str11178 = private unnamed_addr constant [10 x i8] c"image/gif\00"
@.str11179 = private unnamed_addr constant [4 x i8] c"bmp\00"
@.str11180 = private unnamed_addr constant [10 x i8] c"image/bmp\00"
@.str11181 = private unnamed_addr constant [5 x i8] c"webp\00"
@.str11182 = private unnamed_addr constant [11 x i8] c"image/webp\00"
@.str11183 = private unnamed_addr constant [4 x i8] c"svg\00"
@.str11184 = private unnamed_addr constant [14 x i8] c"image/svg+xml\00"
@.str11185 = private unnamed_addr constant [4 x i8] c"txt\00"
@.str11186 = private unnamed_addr constant [11 x i8] c"text/plain\00"
@.str11187 = private unnamed_addr constant [3 x i8] c"md\00"
@.str11188 = private unnamed_addr constant [14 x i8] c"text/markdown\00"
@.str11189 = private unnamed_addr constant [4 x i8] c"csv\00"
@.str11190 = private unnamed_addr constant [9 x i8] c"text/csv\00"
@.str11191 = private unnamed_addr constant [5 x i8] c"html\00"
@.str11192 = private unnamed_addr constant [10 x i8] c"text/html\00"
@.str11193 = private unnamed_addr constant [4 x i8] c"htm\00"
@.str11194 = private unnamed_addr constant [10 x i8] c"text/html\00"
@.str11195 = private unnamed_addr constant [4 x i8] c"css\00"
@.str11196 = private unnamed_addr constant [9 x i8] c"text/css\00"
@.str11197 = private unnamed_addr constant [3 x i8] c"js\00"
@.str11198 = private unnamed_addr constant [16 x i8] c"text/javascript\00"
@.str11199 = private unnamed_addr constant [5 x i8] c"json\00"
@.str11200 = private unnamed_addr constant [17 x i8] c"application/json\00"
@.str11201 = private unnamed_addr constant [4 x i8] c"xml\00"
@.str11202 = private unnamed_addr constant [16 x i8] c"application/xml\00"
@.str11203 = private unnamed_addr constant [4 x i8] c"zip\00"
@.str11204 = private unnamed_addr constant [16 x i8] c"application/zip\00"
@.str11205 = private unnamed_addr constant [4 x i8] c"pdf\00"
@.str11206 = private unnamed_addr constant [16 x i8] c"application/pdf\00"
@.str11207 = private unnamed_addr constant [4 x i8] c"wav\00"
@.str11208 = private unnamed_addr constant [10 x i8] c"audio/wav\00"
@.str11209 = private unnamed_addr constant [4 x i8] c"ogg\00"
@.str11210 = private unnamed_addr constant [10 x i8] c"audio/ogg\00"
@.str11211 = private unnamed_addr constant [4 x i8] c"mp3\00"
@.str11212 = private unnamed_addr constant [11 x i8] c"audio/mpeg\00"
@.str11213 = private unnamed_addr constant [4 x i8] c"ttf\00"
@.str11214 = private unnamed_addr constant [9 x i8] c"font/ttf\00"
@.str11215 = private unnamed_addr constant [4 x i8] c"otf\00"
@.str11216 = private unnamed_addr constant [9 x i8] c"font/otf\00"
@.str11217 = private unnamed_addr constant [6 x i8] c"ludic\00"
@.str11218 = private unnamed_addr constant [13 x i8] c"text/x-ludic\00"
@.str11219 = 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 @.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 }, { ptr, ptr } { ptr @.str11211, ptr @.str11212 }, { ptr, ptr } { ptr @.str11213, ptr @.str11214 }, { ptr, ptr } { ptr @.str11215, ptr @.str11216 }, { ptr, ptr } { ptr @.str11217, ptr @.str11218 }]
define ptr @lp_mime_of(ptr %path) {
entry:
%ext = call ptr @lp_path_ext(ptr %path)
@ -12236,7 +12237,7 @@ nx:
store i32 %i1, ptr %ip
br label %lp
def:
%d = call ptr @lp_fs_strdup(ptr @.str11218)
%d = call ptr @lp_fs_strdup(ptr @.str11219)
ret ptr %d
}
define ptr @lp_mime_lc(ptr %s) {
@ -110131,16 +110132,16 @@ entry:
%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
%t270 = alloca ptr
%t280 = alloca ptr
%t290 = alloca ptr
%t302 = alloca ptr
%t305 = alloca ptr
%t308 = alloca ptr
%t326 = alloca ptr
%t329 = alloca ptr
%t344 = alloca i32
%t365 = alloca i32
store i32 %argc, ptr @L_argc
store ptr %argv, ptr @L_argv
store i32 0, ptr %retval
@ -110637,173 +110638,174 @@ then107:
%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
%t265 = call ptr @lp_str_concat(ptr %t264, ptr @.str11144)
store ptr %t265, 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
%t266 = load i32, ptr @g_g_windowed
%t267 = icmp ne i32 %t266, 0
br i1 %t267, 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
%t268 = load ptr, ptr %t238
%t269 = call ptr @fn_join_path(ptr %t268, ptr @.str11145)
store ptr %t269, ptr %t270
%t271 = load ptr, ptr %t243
%t272 = call ptr @lp_str_concat(ptr %t271, ptr @.str11146)
%t273 = load ptr, ptr %t270
%t274 = call ptr @lp_str_concat(ptr %t272, ptr %t273)
%t275 = call ptr @lp_str_concat(ptr %t274, ptr @.str11147)
store ptr %t275, ptr %t243
%t276 = load i32, ptr @g_g_uses_audio
%t277 = icmp ne i32 %t276, 0
br i1 %t277, 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
%t278 = load ptr, ptr %t238
%t279 = call ptr @fn_join_path(ptr %t278, ptr @.str11148)
store ptr %t279, ptr %t280
%t281 = load ptr, ptr %t243
%t282 = call ptr @lp_str_concat(ptr %t281, ptr @.str11149)
%t283 = load ptr, ptr %t280
%t284 = call ptr @lp_str_concat(ptr %t282, ptr %t283)
%t285 = call ptr @lp_str_concat(ptr %t284, ptr @.str11150)
store ptr %t285, 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
%t286 = load i32, ptr @g_g_uses_http
%t287 = icmp ne i32 %t286, 0
br i1 %t287, 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
%t288 = load ptr, ptr %t238
%t289 = call ptr @fn_join_path(ptr %t288, ptr @.str11151)
store ptr %t289, ptr %t290
%t291 = load ptr, ptr %t243
%t292 = call ptr @lp_str_concat(ptr %t291, ptr @.str11152)
%t293 = load ptr, ptr %t290
%t294 = call ptr @lp_str_concat(ptr %t292, ptr %t293)
%t295 = call ptr @lp_str_concat(ptr %t294, ptr @.str11153)
store ptr %t295, 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
%t296 = load i32, ptr @g_g_uses_gl
%t297 = icmp ne i32 %t296, 0
br i1 %t297, 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
%t298 = load i32, ptr @g_g_target_win
%t299 = icmp ne i32 %t298, 0
br i1 %t299, 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
%t300 = load ptr, ptr %t238
%t301 = call ptr @fn_join_path(ptr %t300, ptr @.str11154)
store ptr %t301, ptr %t302
%t303 = load ptr, ptr %t238
%t304 = call ptr @fn_join_path(ptr %t303, ptr @.str11155)
store ptr %t304, ptr %t305
%t306 = load ptr, ptr %t238
%t307 = call ptr @fn_join_path(ptr %t306, ptr @.str11156)
store ptr %t307, ptr %t308
%t309 = load i32, ptr @g_g_windowed
%t310 = icmp ne i32 %t309, 0
br i1 %t310, 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
%t311 = load ptr, ptr %t238
%t312 = call ptr @fn_join_path(ptr %t311, ptr @.str11157)
store ptr %t312, ptr %t308
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
%t313 = load ptr, ptr %t243
%t314 = call ptr @lp_str_concat(ptr %t313, ptr @.str11158)
%t315 = load ptr, ptr %t302
%t316 = call ptr @lp_str_concat(ptr %t314, ptr %t315)
%t317 = call ptr @lp_str_concat(ptr %t316, ptr @.str11159)
%t318 = load ptr, ptr %t305
%t319 = call ptr @lp_str_concat(ptr %t317, ptr %t318)
%t320 = call ptr @lp_str_concat(ptr %t319, ptr @.str11160)
%t321 = load ptr, ptr %t308
%t322 = call ptr @lp_str_concat(ptr %t320, ptr %t321)
%t323 = call ptr @lp_str_concat(ptr %t322, ptr @.str11161)
store ptr %t323, 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
%t324 = load ptr, ptr %t238
%t325 = call ptr @fn_join_path(ptr %t324, ptr @.str11162)
store ptr %t325, ptr %t326
%t327 = load ptr, ptr %t238
%t328 = call ptr @fn_join_path(ptr %t327, ptr @.str11163)
store ptr %t328, ptr %t329
%t330 = load ptr, ptr %t243
%t331 = call ptr @lp_str_concat(ptr %t330, ptr @.str11164)
%t332 = load ptr, ptr %t326
%t333 = call ptr @lp_str_concat(ptr %t331, ptr %t332)
%t334 = call ptr @lp_str_concat(ptr %t333, ptr @.str11165)
%t335 = load ptr, ptr %t329
%t336 = call ptr @lp_str_concat(ptr %t334, ptr %t335)
%t337 = call ptr @lp_str_concat(ptr %t336, ptr @.str11166)
store ptr %t337, 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
%t338 = load ptr, ptr %t243
%t339 = call ptr @lp_str_concat(ptr %t338, ptr @.str11167)
%t340 = load ptr, ptr %t1
%t341 = call ptr @lp_str_concat(ptr %t339, ptr %t340)
store ptr %t341, ptr %t243
%t342 = load ptr, ptr %t243
%t343 = call i32 @system(ptr %t342)
store i32 %t343, ptr %t344
%t345 = load i32, ptr %t5
%t346 = icmp eq i32 %t345, 0
%t347 = zext i1 %t346 to i32
%t348 = icmp ne i32 %t347, 0
br i1 %t348, label %then128, label %ifend130
then128:
%t348 = load ptr, ptr %t229
call void @fn_remove_file(ptr %t348)
%t349 = load ptr, ptr %t229
call void @fn_remove_file(ptr %t349)
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
%t350 = load i32, ptr %t344
%t351 = icmp ne i32 %t350, 0
%t352 = zext i1 %t351 to i32
%t353 = icmp ne i32 %t352, 0
br i1 %t353, label %then131, label %ifend133
then131:
call void @fn_die(ptr @.str11167)
call void @fn_die(ptr @.str11168)
br label %ifend133
ifend133:
%t353 = load i32, ptr %t6
%t354 = icmp ne i32 %t353, 0
br i1 %t354, label %then134, label %ifend136
%t354 = load i32, ptr %t6
%t355 = icmp ne i32 %t354, 0
br i1 %t355, 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
%t356 = call i32 @fn_host_is_windows()
%t357 = icmp ne i32 %t356, 0
br i1 %t357, 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)
%t358 = load ptr, ptr %t1
%t359 = call ptr @fn_win_path(ptr %t358)
%t360 = call ptr @lp_str_concat(ptr @.str11169, ptr %t359)
%t361 = call ptr @lp_str_concat(ptr %t360, ptr @.str11170)
%t362 = call i32 @system(ptr %t361)
call void @exit(i32 %t362)
unreachable
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)
%t363 = load ptr, ptr %t1
%t364 = call i32 @system(ptr %t363)
store i32 %t364, ptr %t365
%t366 = load i32, ptr %t365
%t367 = lshr i32 %t366, 8
%t368 = and i32 %t367, 255
call void @exit(i32 %t368)
unreachable
ifend136:
br label %ret
ret:
%t368 = load i32, ptr %retval
ret i32 %t368
%t369 = load i32, ptr %retval
ret i32 %t369
}

View file

@ -237,10 +237,12 @@ entry {
# 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`
# xinput.lib carries an import named DllMain, which lld skips with a warning on every
# link; it is the SDK's, not a mistake in the program, so it is silenced
cmd = `{cmd} {win32} -luser32 -lgdi32 -lxinput -Wl,/ignore:importeddllmain`
if g_uses_audio {
let audiow = join_path(home, "runtime/native/audio_win.ll")
cmd = `{cmd} {audiow}`
cmd = `{cmd} {audiow} -lxaudio2 -lole32`
}
}
}