arena (25.3b): LOCAL sites allocate from the frame's scratch; dispatch is not an allocation; @frame by property
Behind ludicc --arena (or 'arena on' in the program's package.ludic): the escape analysis runs and a LOCAL site's allocation raises @lp_want for that one call, so it comes from the frame's arena. Two halves in one mmap reservation (R3D_ARENA_MB each, 256 by default), bump-allocated with a 16-byte size header, flipped at each frame mark: a frame's scratch is good through the next frame, then its half is started again (R3D_ARENA_CHECK=1 fills it with 0xDD first). The heap takes over when no frame is running, off the main thread, or past the half's end; lp_free ignores an arena block and lp_realloc copies one out. R3D_ARENA=0 turns it off at run time; the census reports each half's high-water mark. A program that builds text, a list and a record per frame: 29998 heap blocks made and 18002 freed without it, 8 and 8 with it and 544 bytes of scratch a frame, the same output. A dispatch's 'new' fills the queue's kept record (E_NEW.b), so 25.2 no longer counts it and 25.3 treats its fields as kept. '@frame' is keyed by property and field: a 'run' field is a root only in a property that marks it, and 'tick' stays a System's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
8dfcccad41
commit
bef0d6fbca
11 changed files with 80823 additions and 78428 deletions
|
|
@ -2,6 +2,19 @@
|
|||
# template (docs/plan 25); the tables sized by the program are emit_fence.ludic's.
|
||||
function emit_fence_globals() -> void {
|
||||
emith("@lp_site = global i32 0\n")
|
||||
emith("@lp_want = global i8 0\n")
|
||||
emith("@lp_ar_on = global i8 0\n")
|
||||
emith("@lp_ar_tried = global i8 0\n")
|
||||
emith("@lp_ar_lo = global i64 0\n")
|
||||
emith("@lp_ar_hi = global i64 0\n")
|
||||
emith("@lp_ar_cur = global i64 0\n")
|
||||
emith("@lp_ar_end = global i64 0\n")
|
||||
emith("@lp_ar_which = global i64 0\n")
|
||||
emith("@lp_ar_half = global i64 0\n")
|
||||
emith("@lp_ar_main = global ptr null\n")
|
||||
emith("@lp_ar_hw0 = global i64 0\n")
|
||||
emith("@lp_ar_hw1 = global i64 0\n")
|
||||
emith("@lp_ar_check = global i8 0\n")
|
||||
emith("@lp_fdecl = global i32 0\n")
|
||||
emith("@lp_dlive = global i64 0\n")
|
||||
emith("@lp_mdlive = global i64 0\n")
|
||||
|
|
@ -47,6 +60,7 @@ function emit_fence_globals() -> void {
|
|||
emith("declare i64 @_Unwind_GetIP(ptr)\n")
|
||||
emith("declare i32 @dladdr(ptr, ptr)\n")
|
||||
emith("declare ptr @dlsym(ptr, ptr)\n")
|
||||
emith("declare ptr @pthread_self()\n")
|
||||
emith("@.lpf_env = private unnamed_addr constant [16 x i8] c\"R3D_ALLOC_FENCE\\00\"\n")
|
||||
emith("@.lpf_warm = private unnamed_addr constant [15 x i8] c\"R3D_ALLOC_WARM\\00\"\n")
|
||||
emith("@.lpf_play = private unnamed_addr constant [15 x i8] c\"R3D_ALLOC_PLAY\\00\"\n")
|
||||
|
|
@ -60,6 +74,10 @@ function emit_fence_globals() -> void {
|
|||
emith("@.lpf_row = private unnamed_addr constant [26 x i8] c\" %+lld B %s %s:%d %s\\0A\\00\"\n")
|
||||
emith("@.lpf_more = private unnamed_addr constant [21 x i8] c\" ... and %lld more\\0A\\00\"\n")
|
||||
emith("@.lpf_full = private unnamed_addr constant [99 x i8] c\"alloc-fence: the table is full (%lld blocks) - raise R3D_ALLOC_TABLE; from here it judges nothing\\0A\\00\"\n")
|
||||
emith("@.lpf_arena = private unnamed_addr constant [10 x i8] c\"R3D_ARENA\\00\"\n")
|
||||
emith("@.lpf_arenamb = private unnamed_addr constant [13 x i8] c\"R3D_ARENA_MB\\00\"\n")
|
||||
emith("@.lpf_archeck = private unnamed_addr constant [16 x i8] c\"R3D_ARENA_CHECK\\00\"\n")
|
||||
emith("@.lpf_car = private unnamed_addr constant [61 x i8] c\"arena %lld %lld (each frame arena's high-water mark, bytes)\\0A\\00\"\n")
|
||||
emith("@.lpf_failing = private unnamed_addr constant [53 x i8] c\"alloc-fence: failing the run (R3D_ALLOC_FENCE=fail)\\0A\\00\"\n")
|
||||
emith("@.lpf_census = private unnamed_addr constant [17 x i8] c\"R3D_ALLOC_CENSUS\\00\"\n")
|
||||
emith("@.lpf_warmmax = private unnamed_addr constant [19 x i8] c\"R3D_ALLOC_WARM_MAX\\00\"\n")
|
||||
|
|
@ -80,7 +98,10 @@ function emit_fence_globals() -> void {
|
|||
emith("@.lpf_lp = private unnamed_addr constant [4 x i8] c\"lp_\\00\"\n")
|
||||
}
|
||||
function emit_fence_entry() -> void {
|
||||
emith("define ptr @lp_malloc(i64 %n) {\n")
|
||||
emith("; the four entry points. Off: one load of the fence and the scratch request, one branch, then libc.\n")
|
||||
emith("; @lp_want is raised by the emitter around an allocation of a LOCAL site (25.3): it goes to the\n")
|
||||
emith("; frame's scratch arena, and lp_free hands an arena block back to nobody\n")
|
||||
emith("define internal ptr @lp_heap(i64 %n) {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %t = load i8, ptr @lp_ft\n")
|
||||
emith(" %on = icmp ne i8 %t, 0\n")
|
||||
|
|
@ -93,47 +114,254 @@ function emit_fence_entry() -> void {
|
|||
emith(" call void @lp_fadd(ptr %q, i64 %n)\n")
|
||||
emith(" ret ptr %q\n")
|
||||
emith("}\n")
|
||||
emith("define ptr @lp_malloc(i64 %n) {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %t = load i8, ptr @lp_ft\n")
|
||||
emith(" %w = load i8, ptr @lp_want\n")
|
||||
emith(" %o = or i8 %t, %w\n")
|
||||
emith(" %on = icmp ne i8 %o, 0\n")
|
||||
emith(" br i1 %on, label %slow, label %fast\n")
|
||||
emith("fast:\n")
|
||||
emith(" %p = tail call ptr @malloc(i64 %n)\n")
|
||||
emith(" ret ptr %p\n")
|
||||
emith("slow:\n")
|
||||
emith(" %wq = icmp ne i8 %w, 0\n")
|
||||
emith(" br i1 %wq, label %scratch, label %heap\n")
|
||||
emith("scratch:\n")
|
||||
emith(" store i8 0, ptr @lp_want\n")
|
||||
emith(" %s = call ptr @lp_scratch(i64 %n)\n")
|
||||
emith(" ret ptr %s\n")
|
||||
emith("heap:\n")
|
||||
emith(" %q = call ptr @malloc(i64 %n)\n")
|
||||
emith(" call void @lp_fadd(ptr %q, i64 %n)\n")
|
||||
emith(" ret ptr %q\n")
|
||||
emith("}\n")
|
||||
emith("define ptr @lp_calloc(i64 %n, i64 %s) {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %t = load i8, ptr @lp_ft\n")
|
||||
emith(" %on = icmp ne i8 %t, 0\n")
|
||||
emith(" %w = load i8, ptr @lp_want\n")
|
||||
emith(" %o = or i8 %t, %w\n")
|
||||
emith(" %on = icmp ne i8 %o, 0\n")
|
||||
emith(" br i1 %on, label %slow, label %fast\n")
|
||||
emith("fast:\n")
|
||||
emith(" %p = tail call ptr @calloc(i64 %n, i64 %s)\n")
|
||||
emith(" ret ptr %p\n")
|
||||
emith("slow:\n")
|
||||
emith(" %q = call ptr @calloc(i64 %n, i64 %s)\n")
|
||||
emith(" %b = mul i64 %n, %s\n")
|
||||
emith(" %wq = icmp ne i8 %w, 0\n")
|
||||
emith(" br i1 %wq, label %scratch, label %heap\n")
|
||||
emith("scratch:\n")
|
||||
emith(" store i8 0, ptr @lp_want\n")
|
||||
emith(" %z = call ptr @lp_scratch(i64 %b)\n")
|
||||
emith(" call ptr @memset(ptr %z, i32 0, i64 %b)\n")
|
||||
emith(" ret ptr %z\n")
|
||||
emith("heap:\n")
|
||||
emith(" %q = call ptr @calloc(i64 %n, i64 %s)\n")
|
||||
emith(" call void @lp_fadd(ptr %q, i64 %b)\n")
|
||||
emith(" ret ptr %q\n")
|
||||
emith("}\n")
|
||||
emith("define ptr @lp_realloc(ptr %o, i64 %n) {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %t = load i8, ptr @lp_ft\n")
|
||||
emith(" %on = icmp ne i8 %t, 0\n")
|
||||
emith(" %w = load i8, ptr @lp_want\n")
|
||||
emith(" %a = load i8, ptr @lp_ar_on\n")
|
||||
emith(" %o1 = or i8 %t, %w\n")
|
||||
emith(" %o2 = or i8 %o1, %a\n")
|
||||
emith(" %on = icmp ne i8 %o2, 0\n")
|
||||
emith(" br i1 %on, label %slow, label %fast\n")
|
||||
emith("fast:\n")
|
||||
emith(" %p = tail call ptr @realloc(ptr %o, i64 %n)\n")
|
||||
emith(" ret ptr %p\n")
|
||||
emith("slow:\n")
|
||||
emith(" call void @lp_fdel(ptr %o)\n")
|
||||
emith(" %q = call ptr @realloc(ptr %o, i64 %n)\n")
|
||||
emith(" call void @lp_fadd(ptr %q, i64 %n)\n")
|
||||
emith(" %in = call i1 @lp_in_arena(ptr %o)\n")
|
||||
emith(" %wq = icmp ne i8 %w, 0\n")
|
||||
emith(" %move = or i1 %in, %wq\n")
|
||||
emith(" br i1 %move, label %scratch, label %heap\n")
|
||||
emith("scratch:\n")
|
||||
emith(" store i8 0, ptr @lp_want\n")
|
||||
emith(" %q = call ptr @lp_scratch(i64 %n)\n")
|
||||
emith(" %none = icmp eq ptr %o, null\n")
|
||||
emith(" br i1 %none, label %done, label %copy\n")
|
||||
emith("copy:\n")
|
||||
emith(" br i1 %in, label %oldar, label %oldheap\n")
|
||||
emith("oldar:\n")
|
||||
emith(" %hp = getelementptr i8, ptr %o, i64 -16\n")
|
||||
emith(" %osz = load i64, ptr %hp\n")
|
||||
emith(" br label %cp\n")
|
||||
emith("oldheap:\n")
|
||||
emith(" %has = icmp ne ptr @malloc_size, null\n")
|
||||
emith(" br i1 %has, label %msz, label %cp\n")
|
||||
emith("msz:\n")
|
||||
emith(" %hsz = call i64 @malloc_size(ptr %o)\n")
|
||||
emith(" br label %cp\n")
|
||||
emith("cp:\n")
|
||||
emith(" %old = phi i64 [ %osz, %oldar ], [ 0, %oldheap ], [ %hsz, %msz ]\n")
|
||||
emith(" %less = icmp ult i64 %old, %n\n")
|
||||
emith(" %c = select i1 %less, i64 %old, i64 %n\n")
|
||||
emith(" call ptr @memcpy(ptr %q, ptr %o, i64 %c)\n")
|
||||
emith(" br i1 %in, label %done, label %givebk\n")
|
||||
emith("givebk:\n")
|
||||
emith(" call void @lp_free(ptr %o)\n")
|
||||
emith(" br label %done\n")
|
||||
emith("done:\n")
|
||||
emith(" ret ptr %q\n")
|
||||
emith("heap:\n")
|
||||
emith(" %tq = icmp ne i8 %t, 0\n")
|
||||
emith(" br i1 %tq, label %tracked, label %plain\n")
|
||||
emith("plain:\n")
|
||||
emith(" %r = tail call ptr @realloc(ptr %o, i64 %n)\n")
|
||||
emith(" ret ptr %r\n")
|
||||
emith("tracked:\n")
|
||||
emith(" call void @lp_fdel(ptr %o)\n")
|
||||
emith(" %r2 = call ptr @realloc(ptr %o, i64 %n)\n")
|
||||
emith(" call void @lp_fadd(ptr %r2, i64 %n)\n")
|
||||
emith(" ret ptr %r2\n")
|
||||
emith("}\n")
|
||||
emith("define void @lp_free(ptr %o) {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %t = load i8, ptr @lp_ft\n")
|
||||
emith(" %on = icmp ne i8 %t, 0\n")
|
||||
emith(" %a = load i8, ptr @lp_ar_on\n")
|
||||
emith(" %o1 = or i8 %t, %a\n")
|
||||
emith(" %on = icmp ne i8 %o1, 0\n")
|
||||
emith(" br i1 %on, label %slow, label %fast\n")
|
||||
emith("fast:\n")
|
||||
emith(" tail call void @free(ptr %o)\n")
|
||||
emith(" ret void\n")
|
||||
emith("slow:\n")
|
||||
emith(" %in = call i1 @lp_in_arena(ptr %o)\n")
|
||||
emith(" br i1 %in, label %keep, label %give\n")
|
||||
emith("keep:\n")
|
||||
emith(" ret void\n")
|
||||
emith("give:\n")
|
||||
emith(" %tq = icmp ne i8 %t, 0\n")
|
||||
emith(" br i1 %tq, label %tracked, label %plain\n")
|
||||
emith("plain:\n")
|
||||
emith(" tail call void @free(ptr %o)\n")
|
||||
emith(" ret void\n")
|
||||
emith("tracked:\n")
|
||||
emith(" call void @lp_fdel(ptr %o)\n")
|
||||
emith(" call void @free(ptr %o)\n")
|
||||
emith(" ret void\n")
|
||||
emith("}\n")
|
||||
emith("define internal i1 @lp_in_arena(ptr %o) {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %x = ptrtoint ptr %o to i64\n")
|
||||
emith(" %lo = load i64, ptr @lp_ar_lo\n")
|
||||
emith(" %hi = load i64, ptr @lp_ar_hi\n")
|
||||
emith(" %a = icmp uge i64 %x, %lo\n")
|
||||
emith(" %b = icmp ult i64 %x, %hi\n")
|
||||
emith(" %in = and i1 %a, %b\n")
|
||||
emith(" ret i1 %in\n")
|
||||
emith("}\n")
|
||||
emith("; a block from the frame's arena: a 16-byte header (its size) and 16-aligned; the heap when no\n")
|
||||
emith("; frame is running, off the main thread, or past the arena's end\n")
|
||||
emith("define internal ptr @lp_scratch(i64 %n) {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %on = load i8, ptr @lp_ar_on\n")
|
||||
emith(" %onq = icmp ne i8 %on, 0\n")
|
||||
emith(" br i1 %onq, label %thread, label %heap\n")
|
||||
emith("thread:\n")
|
||||
emith(" %me = call ptr @pthread_self()\n")
|
||||
emith(" %main = load ptr, ptr @lp_ar_main\n")
|
||||
emith(" %mainq = icmp eq ptr %me, %main\n")
|
||||
emith(" br i1 %mainq, label %bump, label %heap\n")
|
||||
emith("bump:\n")
|
||||
emith(" %cur = load i64, ptr @lp_ar_cur\n")
|
||||
emith(" %n16 = add i64 %n, 31\n")
|
||||
emith(" %need = and i64 %n16, -16\n")
|
||||
emith(" %np = add i64 %cur, %need\n")
|
||||
emith(" %end = load i64, ptr @lp_ar_end\n")
|
||||
emith(" %fits = icmp ule i64 %np, %end\n")
|
||||
emith(" br i1 %fits, label %take, label %heap\n")
|
||||
emith("take:\n")
|
||||
emith(" store i64 %np, ptr @lp_ar_cur\n")
|
||||
emith(" %hp = inttoptr i64 %cur to ptr\n")
|
||||
emith(" store i64 %n, ptr %hp\n")
|
||||
emith(" %bp = getelementptr i8, ptr %hp, i64 16\n")
|
||||
emith(" ret ptr %bp\n")
|
||||
emith("heap:\n")
|
||||
emith(" %h = call ptr @lp_heap(i64 %n)\n")
|
||||
emith(" ret ptr %h\n")
|
||||
emith("}\n")
|
||||
emith("; the frame's mark for the arenas: the first reserves them (two halves, R3D_ARENA_MB each, 256 by\n")
|
||||
emith("; default; R3D_ARENA=0 keeps everything on the heap), then each flips to the other half - which\n")
|
||||
emith("; held the frame before last - and starts it again (R3D_ARENA_CHECK=1 fills it with 0xDD first)\n")
|
||||
emith("define internal void @lp_ar_frame() {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %def = load i8, ptr @lp_ardef\n")
|
||||
emith(" %defq = icmp ne i8 %def, 0\n")
|
||||
emith(" br i1 %defq, label %chk, label %out\n")
|
||||
emith("chk:\n")
|
||||
emith(" %on = load i8, ptr @lp_ar_on\n")
|
||||
emith(" %onq = icmp ne i8 %on, 0\n")
|
||||
emith(" br i1 %onq, label %flip, label %maybe\n")
|
||||
emith("maybe:\n")
|
||||
emith(" %tried = load i8, ptr @lp_ar_tried\n")
|
||||
emith(" %tq = icmp ne i8 %tried, 0\n")
|
||||
emith(" br i1 %tq, label %out, label %reserve\n")
|
||||
emith("reserve:\n")
|
||||
emith(" store i8 1, ptr @lp_ar_tried\n")
|
||||
emith(" %want = call i64 @lp_fenv(ptr @.lpf_arena, i64 1)\n")
|
||||
emith(" %wz = icmp eq i64 %want, 0\n")
|
||||
emith(" br i1 %wz, label %out, label %size\n")
|
||||
emith("size:\n")
|
||||
emith(" %mb = call i64 @lp_fenv(ptr @.lpf_arenamb, i64 256)\n")
|
||||
emith(" %half = shl i64 %mb, 20\n")
|
||||
emith(" store i64 %half, ptr @lp_ar_half\n")
|
||||
emith(" %both = shl i64 %half, 1\n")
|
||||
emith(" %m = call ptr @mmap(ptr null, i64 %both, i32 3, i32 4098, i32 -1, i64 0)\n")
|
||||
emith(" %mi = ptrtoint ptr %m to i64\n")
|
||||
emith(" %bad = icmp eq i64 %mi, -1\n")
|
||||
emith(" br i1 %bad, label %out, label %armed\n")
|
||||
emith("armed:\n")
|
||||
emith(" store i64 %mi, ptr @lp_ar_lo\n")
|
||||
emith(" %hi = add i64 %mi, %both\n")
|
||||
emith(" store i64 %hi, ptr @lp_ar_hi\n")
|
||||
emith(" store i64 %mi, ptr @lp_ar_cur\n")
|
||||
emith(" %e0 = add i64 %mi, %half\n")
|
||||
emith(" store i64 %e0, ptr @lp_ar_end\n")
|
||||
emith(" store i64 0, ptr @lp_ar_which\n")
|
||||
emith(" %me = call ptr @pthread_self()\n")
|
||||
emith(" store ptr %me, ptr @lp_ar_main\n")
|
||||
emith(" %ck = call i64 @lp_fenv(ptr @.lpf_archeck, i64 0)\n")
|
||||
emith(" %ck8 = trunc i64 %ck to i8\n")
|
||||
emith(" store i8 %ck8, ptr @lp_ar_check\n")
|
||||
emith(" store i8 1, ptr @lp_ar_on\n")
|
||||
emith(" br label %out\n")
|
||||
emith("flip:\n")
|
||||
emith(" %w = load i64, ptr @lp_ar_which\n")
|
||||
emith(" %lo = load i64, ptr @lp_ar_lo\n")
|
||||
emith(" %hf = load i64, ptr @lp_ar_half\n")
|
||||
emith(" %off = mul i64 %w, %hf\n")
|
||||
emith(" %start = add i64 %lo, %off\n")
|
||||
emith(" %cur = load i64, ptr @lp_ar_cur\n")
|
||||
emith(" %used = sub i64 %cur, %start\n")
|
||||
emith(" %w0 = icmp eq i64 %w, 0\n")
|
||||
emith(" %hwq = select i1 %w0, ptr @lp_ar_hw0, ptr @lp_ar_hw1\n")
|
||||
emith(" %hwv = load i64, ptr %hwq\n")
|
||||
emith(" %more = icmp ugt i64 %used, %hwv\n")
|
||||
emith(" %hwn = select i1 %more, i64 %used, i64 %hwv\n")
|
||||
emith(" store i64 %hwn, ptr %hwq\n")
|
||||
emith(" %nw = xor i64 %w, 1\n")
|
||||
emith(" store i64 %nw, ptr @lp_ar_which\n")
|
||||
emith(" %noff = mul i64 %nw, %hf\n")
|
||||
emith(" %nstart = add i64 %lo, %noff\n")
|
||||
emith(" store i64 %nstart, ptr @lp_ar_cur\n")
|
||||
emith(" %nend = add i64 %nstart, %hf\n")
|
||||
emith(" store i64 %nend, ptr @lp_ar_end\n")
|
||||
emith(" %cq = load i8, ptr @lp_ar_check\n")
|
||||
emith(" %cqq = icmp ne i8 %cq, 0\n")
|
||||
emith(" br i1 %cqq, label %poison, label %out\n")
|
||||
emith("poison:\n")
|
||||
emith(" %n0 = icmp eq i64 %nw, 0\n")
|
||||
emith(" %nhq = select i1 %n0, ptr @lp_ar_hw0, ptr @lp_ar_hw1\n")
|
||||
emith(" %nhv = load i64, ptr %nhq\n")
|
||||
emith(" %np = inttoptr i64 %nstart to ptr\n")
|
||||
emith(" call ptr @memset(ptr %np, i32 221, i64 %nhv)\n")
|
||||
emith(" br label %out\n")
|
||||
emith("out:\n")
|
||||
emith(" ret void\n")
|
||||
emith("}\n")
|
||||
}
|
||||
function emit_fence_table() -> void {
|
||||
emith("define internal void @lp_flock() {\n")
|
||||
|
|
@ -836,6 +1064,9 @@ function emit_fence_report() -> void {
|
|||
emith(" %ddc = sub i64 %dnow, %dset\n")
|
||||
emith(" %ddc1 = select i1 %jq, i64 %ddc, i64 0\n")
|
||||
emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_cdecl, i64 %ddc1)\n")
|
||||
emith(" %ah0 = load i64, ptr @lp_ar_hw0\n")
|
||||
emith(" %ah1 = load i64, ptr @lp_ar_hw1\n")
|
||||
emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_car, i64 %ah0, i64 %ah1)\n")
|
||||
emith(" %jd1 = select i1 %jq, i64 %jd, i64 0\n")
|
||||
emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_cjolt, i64 %jd1, i64 %jpk)\n")
|
||||
emith(" %vd1 = select i1 %jq, i64 %vd, i64 0\n")
|
||||
|
|
@ -930,6 +1161,7 @@ function emit_fence_frame() -> void {
|
|||
emith("; R3D_ALLOC_WARM_MAX frames after tracking (re)started, whichever is first\n")
|
||||
emith("define void @lp_mem_frame() {\n")
|
||||
emith("entry:\n")
|
||||
emith(" call void @lp_ar_frame()\n")
|
||||
emith(" call void @lp_finit()\n")
|
||||
emith(" %f = load i64, ptr @lp_frame\n")
|
||||
emith(" %f1 = add i64 %f, 1\n")
|
||||
|
|
@ -1039,6 +1271,7 @@ function emit_fence_frame() -> void {
|
|||
}
|
||||
function emit_fence_win() -> void {
|
||||
emith("@lp_site = global i32 0\n")
|
||||
emith("@lp_want = global i8 0\n")
|
||||
emith("@lp_fdecl = global i32 0\n")
|
||||
emith("define ptr @lp_malloc(i64 %n) {\n")
|
||||
emith("entry:\n")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue