From 3300fb39574d1feaa55218bcc9916c4f717000a0 Mon Sep 17 00:00:00 2001 From: Orkuncakilkaya Date: Sun, 13 Sep 2026 02:42:48 +0300 Subject: [PATCH] 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 --- changes/windows-target.md | 9 +- runtime/native/audio_win.ll | 438 ++++++++++++++++++++++++++++++++++-- selfhost/ludicc.seed.ll | 424 +++++++++++++++++----------------- selfhost/main.ludic | 6 +- 4 files changed, 646 insertions(+), 231 deletions(-) diff --git a/changes/windows-target.md b/changes/windows-target.md index d3036f98..dfbec5da 100644 --- a/changes/windows-target.md +++ b/changes/windows-target.md @@ -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 diff --git a/runtime/native/audio_win.ll b/runtime/native/audio_win.ll index 00af0fab..5b21ee51 100644 --- a/runtime/native/audio_win.ll +++ b/runtime/native/audio_win.ll @@ -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 } diff --git a/selfhost/ludicc.seed.ll b/selfhost/ludicc.seed.ll index 8c3dbba4..1fb3e40a 100644 --- a/selfhost/ludicc.seed.ll +++ b/selfhost/ludicc.seed.ll @@ -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 } diff --git a/selfhost/main.ludic b/selfhost/main.ludic index 31dfa2af..a19166f1 100644 --- a/selfhost/main.ludic +++ b/selfhost/main.ludic @@ -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` } } }