# emit_fence_ir.ludic - the allocation fence's runtime (25.1), as IR. Generated from a # 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") emith("@lp_sdlive = global i64 0\n") emith("@lp_dwin = global i64 600\n") emith("@lp_drise = global i64 6\n") emith("@lp_dunb = global i64 0\n") emith("@lp_ft = global i8 0\n") emith("@lp_fm = global i8 0\n") emith("@lp_fj = global i8 0\n") emith("@lp_fl = global i32 0\n") emith("@lp_tab = global ptr null\n") emith("@lp_tabmask = global i64 0\n") emith("@lp_tabn = global i64 0\n") emith("@lp_tabmax = global i64 0\n") emith("@lp_live = global i64 0\n") emith("@lp_pre = global i64 0\n") emith("@lp_made = global i64 0\n") emith("@lp_freed = global i64 0\n") emith("@lp_over = global i64 0\n") emith("@lp_overrep = global i8 0\n") emith("@lp_frame = global i64 0\n") emith("@lp_flat = global i64 0\n") emith("@lp_playf = global i64 0\n") emith("@lp_warm_max = global i64 -1\n") emith("@lp_fauto = global i8 1\n") emith("@lp_autoplay = global i64 -1\n") emith("@lp_mlive = global i64 0\n") emith("@lp_mpre = global i64 0\n") emith("@lp_mmade = global i64 0\n") emith("@lp_mfreed = global i64 0\n") emith("@lp_slive = global i64 0\n") emith("@lp_spre = global i64 0\n") emith("@lp_touch = global [512 x i32] zeroinitializer\n") emith("@lp_ntouch = global i32 0\n") emith("@lp_fkept = global i64 0\n") emith("@lp_fbad = global i64 0\n") emith("@lp_fjudged = global i64 0\n") emith("@lp_scan_at = global i64 -2\n") emith("@lp_visit_set = global ptr null\n") emith("@lp_vmask = global i64 0\n") emith("@lp_wl = global ptr null\n") emith("@lp_wln = global i64 0\n") emith("@lp_wlcap = global i64 0\n") emith("@lp_scan_bytes = global i64 0\n") emith("@lp_capn = global i64 0\n") emith("@lp_zset = global i64 0\n") emith("@lp_jset = global i64 0\n") emith("@lp_vset = global i64 0\n") emith("@lp_census = global ptr null\n") emith("declare extern_weak i64 @malloc_size(ptr)\n") emith("declare i32 @dprintf(i32, ptr, ...)\n") emith("declare i32 @_Unwind_Backtrace(ptr, ptr)\n") 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") emith("@.lpf_tab = private unnamed_addr constant [16 x i8] c\"R3D_ALLOC_TABLE\\00\"\n") emith("@.lpf_dev = private unnamed_addr constant [8 x i8] c\"R3D_DEV\\00\"\n") emith("@.lpf_off = private unnamed_addr constant [4 x i8] c\"off\\00\"\n") emith("@.lpf_count = private unnamed_addr constant [6 x i8] c\"count\\00\"\n") emith("@.lpf_warn = private unnamed_addr constant [5 x i8] c\"warn\\00\"\n") emith("@.lpf_fail = private unnamed_addr constant [5 x i8] c\"fail\\00\"\n") emith("@.lpf_hdr = private unnamed_addr constant [62 x i8] c\"alloc-fence: frame %lld kept %+lld B (%lld made, %lld freed)\\0A\\00\"\n") 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 [71 x i8] c\"alloc-fence: %s is full - it stops keeping and makes a copy each time\\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_capover = private unnamed_addr constant [54 x i8] c\"alloc-fence: %s grew past its @max(%d) (it holds %d)\\0A\\00\"\n") emith("@.lpf_capfail = private unnamed_addr constant [78 x i8] c\"alloc-fence: failing the run (R3D_ALLOC_FENCE=fail): a capacity is a promise\\0A\\00\"\n") emith("@.lpf_ccap = private unnamed_addr constant [56 x i8] c\"overflows %lld (a list past its @max, or a table full)\\0A\\00\"\n") emith("@.lpf_scan = private unnamed_addr constant [15 x i8] c\"R3D_ALLOC_SCAN\\00\"\n") emith("@.lpf_scantop = private unnamed_addr constant [19 x i8] c\"R3D_ALLOC_SCAN_TOP\\00\"\n") emith("@.lpf_scanfile = private unnamed_addr constant [20 x i8] c\"R3D_ALLOC_SCAN_FILE\\00\"\n") emith("@.lpf_sfrow = private unnamed_addr constant [18 x i8] c\"%lld %s %s:%d %s\\0A\\00\"\n") emith("@.lpf_a = private unnamed_addr constant [2 x i8] c\"a\\00\"\n") emith("@.lpf_exitscan = private unnamed_addr constant [15 x i8] c\"R3D_ALLOC_EXIT\\00\"\n") emith("@.lpf_shdr = private unnamed_addr constant [116 x i8] c\"alloc-scan: frame %lld - %lld bytes in %lld blocks made since tracking began are reachable from no global or state\\0A\\00\"\n") emith("@.lpf_srow = private unnamed_addr constant [25 x i8] c\" %lld B %s %s:%d %s\\0A\\00\"\n") emith("@.lpf_cown = private unnamed_addr constant [49 x i8] c\"owner %s holds %lld (%+lld since judging began)\\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") emith("@.lpf_auto = private unnamed_addr constant [15 x i8] c\"R3D_ALLOC_AUTO\\00\"\n") emith("@.lpf_w = private unnamed_addr constant [2 x i8] c\"w\\00\"\n") emith("@.lpf_chdr = private unnamed_addr constant [76 x i8] c\"alloc-census frames %lld bad %lld kept %lld made %lld freed %lld over %lld\\0A\\00\"\n") emith("@.lpf_cnat = private unnamed_addr constant [116 x i8] c\"native %lld (the heap outside Ludic's blocks and the counted libraries, since judging began: drivers, Metal, libc)\\0A\\00\"\n") emith("@.lpf_cdecl = private unnamed_addr constant [58 x i8] c\"declared %lld (kept under @alloc_ok since judging began)\\0A\\00\"\n") emith("@.lpf_cjolt = private unnamed_addr constant [68 x i8] c\"jolt %lld peak %lld (since judging began, and its high-water mark)\\0A\\00\"\n") emith("@.lpf_cvk = private unnamed_addr constant [83 x i8] c\"vulkan %lld peak %lld (host memory through VkAllocationCallbacks, R3D_ALLOC_VK=1)\\0A\\00\"\n") emith("@.lpf_jb = private unnamed_addr constant [15 x i8] c\"jph_heap_bytes\\00\"\n") emith("@.lpf_jp = private unnamed_addr constant [14 x i8] c\"jph_heap_peak\\00\"\n") emith("@.lpf_vb = private unnamed_addr constant [13 x i8] c\"lvk_ac_bytes\\00\"\n") emith("@.lpf_vp = private unnamed_addr constant [12 x i8] c\"lvk_ac_peak\\00\"\n") emith("@.lpf_crow = private unnamed_addr constant [23 x i8] c\"site %lld %s %s:%d %s\\0A\\00\"\n") emith("@.lpf_from = private unnamed_addr constant [15 x i8] c\" from %s\\0A\\00\"\n") emith("@.lpf_cfrom = private unnamed_addr constant [11 x i8] c\" from %s\\0A\\00\"\n") emith("@.lpf_lp = private unnamed_addr constant [4 x i8] c\"lp_\\00\"\n") emith("@.lpf_dwin = private unnamed_addr constant [15 x i8] c\"R3D_ALLOC_DWIN\\00\"\n") emith("@.lpf_rewarm = private unnamed_addr constant [17 x i8] c\"R3D_ALLOC_REWARM\\00\"\n") emith("@.lpf_drise = private unnamed_addr constant [16 x i8] c\"R3D_ALLOC_DRISE\\00\"\n") emith("@.lpf_dunb = private unnamed_addr constant [159 x i8] c\"alloc-fence: frame %lld: declared but unbounded - @alloc_ok memory still rising after %lld windows of %lld frames (the reason says bounded; this site is not)\\0A\\00\"\n") emith("@.lpf_cdunb = private unnamed_addr constant [107 x i8] c\"unbounded %lld (declared sites whose bytes kept rising: R3D_ALLOC_DRISE windows of R3D_ALLOC_DWIN frames)\\0A\\00\"\n") emith("@.lpf_cdrow = private unnamed_addr constant [24 x i8] c\"dsite %lld %s %s:%d %s\\0A\\00\"\n") } function emit_fence_entry() -> void { 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") 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(" %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_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(" %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(" %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(" %w = load i8, ptr @lp_want\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(" %ge = icmp uge i64 %x, %lo\n") emith(" %lt = icmp ult i64 %x, %hi\n") emith(" %inar = and i1 %ge, %lt\n") emith(" %o1 = or i8 %t, %w\n") emith(" %some = icmp ne i8 %o1, 0\n") emith(" %on = or i1 %some, %inar\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(" %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(" %ist = ptrtoint ptr @lp_istore to i64\n") # an interned text is the store's: never freed emith(" %ien = add i64 %ist, 4194304\n") emith(" %ix = ptrtoint ptr %o to i64\n") emith(" %ige = icmp uge i64 %ix, %ist\n") emith(" %ilt = icmp ult i64 %ix, %ien\n") emith(" %iin = and i1 %ige, %ilt\n") emith(" br i1 %iin, label %istore, label %free0\n") emith("istore:\n") emith(" ret void\n") emith("free0:\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(" %ge = icmp uge i64 %x, %lo\n") emith(" %lt = icmp ult i64 %x, %hi\n") emith(" %in = and i1 %ge, %lt\n") emith(" br i1 %in, label %keep, label %heap\n") emith("keep:\n") emith(" ret void\n") emith("heap:\n") emith(" %t = load i8, ptr @lp_ft\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 %start\n") emith("start:\n") emith(" ; the arena starts at its first use, so boot's temporaries are scratch too: dead once the Start\n") emith(" ; handlers return, and their half is started again two frame marks on\n") emith(" call void @lp_ar_frame()\n") emith(" %on2 = load i8, ptr @lp_ar_on\n") emith(" %on2q = icmp ne i8 %on2, 0\n") emith(" br i1 %on2q, 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") emith("entry:\n") emith(" br label %spin\n") emith("spin:\n") emith(" %o = atomicrmw xchg ptr @lp_fl, i32 1 acquire\n") emith(" %b = icmp eq i32 %o, 0\n") emith(" br i1 %b, label %done, label %spin\n") emith("done:\n") emith(" ret void\n") emith("}\n") emith("define internal void @lp_funlock() {\n") emith("entry:\n") emith(" store atomic i32 0, ptr @lp_fl release, align 4\n") emith(" ret void\n") emith("}\n") emith("define internal i64 @lp_fhash(i64 %k) {\n") emith("entry:\n") emith(" %a = lshr i64 %k, 4\n") emith(" %b = mul i64 %a, -7046029254386353131\n") emith(" %c = lshr i64 %b, 29\n") emith(" %d = xor i64 %b, %c\n") emith(" ret i64 %d\n") emith("}\n") emith("define internal void @lp_ftouch(i64 %s) {\n") emith("entry:\n") emith(" %sp = getelementptr inbounds i64, ptr @lp_site_stamp, i64 %s\n") emith(" %st = load i64, ptr %sp\n") emith(" %f = load i64, ptr @lp_frame\n") emith(" %f1 = add i64 %f, 1\n") emith(" %seen = icmp eq i64 %st, %f1\n") emith(" br i1 %seen, label %out, label %mark\n") emith("mark:\n") emith(" store i64 %f1, ptr %sp\n") emith(" %n = load i32, ptr @lp_ntouch\n") emith(" %room = icmp ult i32 %n, 512\n") emith(" %n1 = add i32 %n, 1\n") emith(" store i32 %n1, ptr @lp_ntouch\n") emith(" br i1 %room, label %put, label %out\n") emith("put:\n") emith(" %tp = getelementptr inbounds [512 x i32], ptr @lp_touch, i32 0, i32 %n\n") emith(" %s32 = trunc i64 %s to i32\n") emith(" store i32 %s32, ptr %tp\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("define internal void @lp_fsite_dadd(i64 %s, i64 %n) {\n") emith("entry:\n") emith(" %sp = getelementptr inbounds i64, ptr @lp_site_dlive, i64 %s\n") emith(" %v = load i64, ptr %sp\n") emith(" %v1 = add i64 %v, %n\n") emith(" store i64 %v1, ptr %sp\n") emith(" %dl = load i64, ptr @lp_dlive\n") emith(" %dl1 = add i64 %dl, %n\n") emith(" store i64 %dl1, ptr @lp_dlive\n") emith(" ret void\n") emith("}\n") emith("define internal void @lp_fsite_add(i64 %s, i64 %n) {\n") emith("entry:\n") emith(" %sp = getelementptr inbounds i64, ptr @lp_site_live, i64 %s\n") emith(" %v = load i64, ptr %sp\n") emith(" %v1 = add i64 %v, %n\n") emith(" store i64 %v1, ptr %sp\n") emith(" %lv = load i64, ptr @lp_live\n") emith(" %lv1 = add i64 %lv, %n\n") emith(" store i64 %lv1, ptr @lp_live\n") emith(" call void @lp_ftouch(i64 %s)\n") emith(" ret void\n") emith("}\n") emith("; the last six return addresses above an allocation of site s, from the unwinder (the emitted\n") emith("; functions keep no frame-pointer chain), taken only once judging has begun: what is made then is\n") emith("; what a report names, and it is rare\n") emith("define internal i32 @lp_funw(ptr %ctx, ptr %st) {\n") emith("entry:\n") emith(" %n = load i64, ptr %st\n") emith(" %full = icmp uge i64 %n, 6\n") emith(" br i1 %full, label %stop, label %take\n") emith("take:\n") emith(" %ip = call i64 @_Unwind_GetIP(ptr %ctx)\n") emith(" %bp = getelementptr inbounds i64, ptr %st, i64 1\n") emith(" %base = load i64, ptr %bp\n") emith(" %slot = add i64 %base, %n\n") emith(" %dst = getelementptr inbounds i64, ptr @lp_site_ra, i64 %slot\n") emith(" store i64 %ip, ptr %dst\n") emith(" %n1 = add i64 %n, 1\n") emith(" store i64 %n1, ptr %st\n") emith(" ret i32 0\n") emith("stop:\n") emith(" ret i32 5\n") emith("}\n") emith("define internal void @lp_fcallers(i64 %s) noinline {\n") emith("entry:\n") emith(" %j = load i8, ptr @lp_fj\n") emith(" %judging = icmp ne i8 %j, 0\n") emith(" br i1 %judging, label %walk, label %out\n") emith("walk:\n") emith(" %st = alloca [2 x i64], align 8\n") emith(" store i64 0, ptr %st\n") emith(" %bp = getelementptr inbounds i64, ptr %st, i64 1\n") emith(" %base = mul i64 %s, 6\n") emith(" store i64 %base, ptr %bp\n") emith(" %z = getelementptr inbounds i64, ptr @lp_site_ra, i64 %base\n") emith(" call ptr @memset(ptr %z, i32 0, i64 48)\n") emith(" call i32 @_Unwind_Backtrace(ptr @lp_funw, ptr %st)\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("; the Ludic functions a site was last reached from: its callers' names, those of the fence and of\n") emith("; the site's own function left out\n") emith("define internal void @lp_fsite_from(ptr %fp, i32 %s, ptr %own) {\n") emith("entry:\n") emith(" %info = alloca [4 x ptr], align 8\n") emith(" %s64 = sext i32 %s to i64\n") emith(" %base = mul i64 %s64, 6\n") emith(" br label %loop\n") emith("loop:\n") emith(" %i = phi i64 [ 0, %entry ], [ %i1, %next ]\n") emith(" %shown = phi i32 [ 0, %entry ], [ %shown1, %next ]\n") emith(" %more = icmp ult i64 %i, 6\n") emith(" %room = icmp ult i32 %shown, 3\n") emith(" %go = and i1 %more, %room\n") emith(" br i1 %go, label %body, label %out\n") emith("body:\n") emith(" %slot = add i64 %base, %i\n") emith(" %rp = getelementptr inbounds ptr, ptr @lp_site_ra, i64 %slot\n") emith(" %ra0 = load ptr, ptr %rp\n") emith(" %ra = getelementptr i8, ptr %ra0, i64 -1\n") emith(" %nul = icmp eq ptr %ra0, null\n") emith(" br i1 %nul, label %skip, label %look\n") emith("look:\n") emith(" %ok = call i32 @dladdr(ptr %ra, ptr %info)\n") emith(" %okq = icmp ne i32 %ok, 0\n") emith(" br i1 %okq, label %named, label %skip\n") emith("named:\n") emith(" %snp = getelementptr inbounds [4 x ptr], ptr %info, i32 0, i32 2\n") emith(" %sn = load ptr, ptr %snp\n") emith(" %snnul = icmp eq ptr %sn, null\n") emith(" br i1 %snnul, label %skip, label %filter\n") emith("filter:\n") emith(" %c1 = call i32 @strncmp(ptr %sn, ptr @.lpf_lp, i64 3)\n") emith(" %islp = icmp eq i32 %c1, 0\n") emith(" %own3 = getelementptr inbounds i8, ptr %sn, i64 3\n") emith(" %c2 = call i32 @strcmp(ptr %own3, ptr %own)\n") emith(" %isown = icmp eq i32 %c2, 0\n") emith(" %drop = or i1 %islp, %isown\n") emith(" br i1 %drop, label %skip, label %print\n") emith("print:\n") emith(" %tofile = icmp ne ptr %fp, null\n") emith(" br i1 %tofile, label %pf, label %pe\n") emith("pf:\n") emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_cfrom, ptr %sn)\n") emith(" br label %counted\n") emith("pe:\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 2, ptr @.lpf_from, ptr %sn)\n") emith(" br label %counted\n") emith("counted:\n") emith(" br label %next\n") emith("skip:\n") emith(" br label %next\n") emith("next:\n") emith(" %add = phi i32 [ 1, %counted ], [ 0, %skip ]\n") emith(" %shown1 = add i32 %shown, %add\n") emith(" %i1 = add i64 %i, 1\n") emith(" br label %loop\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("define internal void @lp_fadd(ptr %p, i64 %asked) {\n") emith("entry:\n") emith(" %isnull = icmp eq ptr %p, null\n") emith(" br i1 %isnull, label %out, label %size\n") emith("size:\n") emith(" %hasms = icmp ne ptr @malloc_size, null\n") emith(" br i1 %hasms, label %real, label %go\n") emith("real:\n") emith(" %ms = call i64 @malloc_size(ptr %p)\n") emith(" br label %go\n") emith("go:\n") emith(" %n = phi i64 [ %asked, %size ], [ %ms, %real ]\n") emith(" call void @lp_flock()\n") emith(" %cnt = load i64, ptr @lp_tabn\n") emith(" %max = load i64, ptr @lp_tabmax\n") emith(" %full = icmp sge i64 %cnt, %max\n") emith(" br i1 %full, label %over, label %ins\n") emith("over:\n") emith(" %ov = load i64, ptr @lp_over\n") emith(" %ov1 = add i64 %ov, 1\n") emith(" store i64 %ov1, ptr @lp_over\n") emith(" br label %unlock\n") emith("ins:\n") emith(" %s0 = load i32, ptr @lp_site\n") emith(" %sn = load i32, ptr @lp_site_n\n") emith(" %sok = icmp ult i32 %s0, %sn\n") emith(" %s = select i1 %sok, i32 %s0, i32 0\n") emith(" %s64 = zext i32 %s to i64\n") emith(" %k = ptrtoint ptr %p to i64\n") emith(" %h = call i64 @lp_fhash(i64 %k)\n") emith(" %mask = load i64, ptr @lp_tabmask\n") emith(" %tab = load ptr, ptr @lp_tab\n") emith(" br label %probe\n") emith("probe:\n") emith(" %i = phi i64 [ %h, %ins ], [ %i1, %next ]\n") emith(" %im = and i64 %i, %mask\n") emith(" %e = getelementptr inbounds [2 x i64], ptr %tab, i64 %im\n") emith(" %ek = load i64, ptr %e\n") emith(" %empty = icmp eq i64 %ek, 0\n") emith(" br i1 %empty, label %put, label %chk\n") emith("chk:\n") emith(" %same = icmp eq i64 %ek, %k\n") emith(" br i1 %same, label %dup, label %next\n") emith("next:\n") emith(" %i1 = add i64 %im, 1\n") emith(" br label %probe\n") emith("dup:\n") emith(" %dv = getelementptr inbounds i64, ptr %e, i64 1\n") emith(" %dold = load i64, ptr %dv\n") emith(" %dn = and i64 %dold, 549755813887\n") emith(" %ds = lshr i64 %dold, 40\n") emith(" %dneg = sub i64 0, %dn\n") emith(" %dwd = and i64 %dold, 549755813888\n") emith(" %dwas = icmp ne i64 %dwd, 0\n") emith(" br i1 %dwas, label %ddecl, label %dund\n") emith("ddecl:\n") emith(" call void @lp_fsite_dadd(i64 %ds, i64 %dneg)\n") emith(" br label %dcount\n") emith("dund:\n") emith(" call void @lp_fsite_add(i64 %ds, i64 %dneg)\n") emith(" br label %dcount\n") emith("dcount:\n") emith(" %dtn = load i64, ptr @lp_tabn\n") emith(" %dtn1 = sub i64 %dtn, 1\n") emith(" store i64 %dtn1, ptr @lp_tabn\n") emith(" %dfr = load i64, ptr @lp_freed\n") emith(" %dfr1 = add i64 %dfr, 1\n") emith(" store i64 %dfr1, ptr @lp_freed\n") emith(" br label %put\n") emith("put:\n") emith(" store i64 %k, ptr %e\n") emith(" %ev = getelementptr inbounds i64, ptr %e, i64 1\n") emith(" %sh = shl i64 %s64, 40\n") emith(" %v0 = or i64 %sh, %n\n") emith(" %dc = load i32, ptr @lp_fdecl\n") emith(" %isdecl = icmp sgt i32 %dc, 0\n") emith(" %dbit = select i1 %isdecl, i64 549755813888, i64 0\n") emith(" %v = or i64 %v0, %dbit\n") emith(" store i64 %v, ptr %ev\n") emith(" %dl = load i64, ptr @lp_dlive\n") emith(" %dadd = select i1 %isdecl, i64 %n, i64 0\n") emith(" %dl1 = add i64 %dl, %dadd\n") emith(" store i64 %dl1, ptr @lp_dlive\n") emith(" %tn = load i64, ptr @lp_tabn\n") emith(" %tn1 = add i64 %tn, 1\n") emith(" store i64 %tn1, ptr @lp_tabn\n") emith(" %md = load i64, ptr @lp_made\n") emith(" %md1 = add i64 %md, 1\n") emith(" store i64 %md1, ptr @lp_made\n") emith(" br i1 %isdecl, label %pdecl, label %pund\n") emith("pdecl:\n") emith(" call void @lp_fsite_dadd(i64 %s64, i64 %n)\n") emith(" br label %unlock\n") emith("pund:\n") emith(" call void @lp_fsite_add(i64 %s64, i64 %n)\n") emith(" call void @lp_fcallers(i64 %s64)\n") emith(" br label %unlock\n") emith("unlock:\n") emith(" call void @lp_funlock()\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("define internal void @lp_fdel(ptr %p) {\n") emith("entry:\n") emith(" %isnull = icmp eq ptr %p, null\n") emith(" br i1 %isnull, label %out, label %go\n") emith("go:\n") emith(" call void @lp_flock()\n") emith(" %k = ptrtoint ptr %p to i64\n") emith(" %h = call i64 @lp_fhash(i64 %k)\n") emith(" %mask = load i64, ptr @lp_tabmask\n") emith(" %tab = load ptr, ptr @lp_tab\n") emith(" br label %probe\n") emith("probe:\n") emith(" %i = phi i64 [ %h, %go ], [ %i1, %next ]\n") emith(" %im = and i64 %i, %mask\n") emith(" %e = getelementptr inbounds [2 x i64], ptr %tab, i64 %im\n") emith(" %ek = load i64, ptr %e\n") emith(" %empty = icmp eq i64 %ek, 0\n") emith(" br i1 %empty, label %miss, label %cmp\n") emith("cmp:\n") emith(" %hit = icmp eq i64 %ek, %k\n") emith(" br i1 %hit, label %found, label %next\n") emith("next:\n") emith(" %i1 = add i64 %im, 1\n") emith(" br label %probe\n") emith("miss:\n") emith(" %has = icmp ne ptr @malloc_size, null\n") emith(" br i1 %has, label %msz, label %unlock\n") emith("msz:\n") emith(" %ms = call i64 @malloc_size(ptr %p)\n") emith(" %pr = load i64, ptr @lp_pre\n") emith(" %pr1 = add i64 %pr, %ms\n") emith(" store i64 %pr1, ptr @lp_pre\n") emith(" br label %unlock\n") emith("found:\n") emith(" %ev = getelementptr inbounds i64, ptr %e, i64 1\n") emith(" %v = load i64, ptr %ev\n") emith(" %n = and i64 %v, 549755813887\n") emith(" %s = lshr i64 %v, 40\n") emith(" %neg = sub i64 0, %n\n") emith(" %wd = and i64 %v, 549755813888\n") emith(" %wasdecl = icmp ne i64 %wd, 0\n") emith(" br i1 %wasdecl, label %fdecl, label %fund\n") emith("fdecl:\n") emith(" call void @lp_fsite_dadd(i64 %s, i64 %neg)\n") emith(" br label %fcount\n") emith("fund:\n") emith(" call void @lp_fsite_add(i64 %s, i64 %neg)\n") emith(" br label %fcount\n") emith("fcount:\n") emith(" %fr = load i64, ptr @lp_freed\n") emith(" %fr1 = add i64 %fr, 1\n") emith(" store i64 %fr1, ptr @lp_freed\n") emith(" %tn = load i64, ptr @lp_tabn\n") emith(" %tn1 = sub i64 %tn, 1\n") emith(" store i64 %tn1, ptr @lp_tabn\n") emith(" br label %sh\n") emith("sh:\n") emith(" %hole = phi i64 [ %im, %fcount ], [ %hole, %sh_skip ], [ %j, %sh_move ]\n") emith(" %jp = phi i64 [ %im, %fcount ], [ %j, %sh_skip ], [ %j, %sh_move ]\n") emith(" %j0 = add i64 %jp, 1\n") emith(" %j = and i64 %j0, %mask\n") emith(" %ej = getelementptr inbounds [2 x i64], ptr %tab, i64 %j\n") emith(" %kj = load i64, ptr %ej\n") emith(" %endq = icmp eq i64 %kj, 0\n") emith(" br i1 %endq, label %sh_end, label %sh_test\n") emith("sh_test:\n") emith(" %hj = call i64 @lp_fhash(i64 %kj)\n") emith(" %home = and i64 %hj, %mask\n") emith(" %jgt = icmp ugt i64 %j, %hole\n") emith(" %a1 = icmp ugt i64 %home, %hole\n") emith(" %a2 = icmp ule i64 %home, %j\n") emith(" %in1 = and i1 %a1, %a2\n") emith(" %in2 = or i1 %a1, %a2\n") emith(" %in = select i1 %jgt, i1 %in1, i1 %in2\n") emith(" br i1 %in, label %sh_skip, label %sh_move\n") emith("sh_skip:\n") emith(" br label %sh\n") emith("sh_move:\n") emith(" %eh = getelementptr inbounds [2 x i64], ptr %tab, i64 %hole\n") emith(" store i64 %kj, ptr %eh\n") emith(" %ejv = getelementptr inbounds i64, ptr %ej, i64 1\n") emith(" %vj = load i64, ptr %ejv\n") emith(" %ehv = getelementptr inbounds i64, ptr %eh, i64 1\n") emith(" store i64 %vj, ptr %ehv\n") emith(" br label %sh\n") emith("sh_end:\n") emith(" %ehe = getelementptr inbounds [2 x i64], ptr %tab, i64 %hole\n") emith(" store i64 0, ptr %ehe\n") emith(" br label %unlock\n") emith("unlock:\n") emith(" call void @lp_funlock()\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") } function emit_fence_control() -> void { emith("define internal i64 @lp_fenv(ptr %name, i64 %dflt) {\n") emith("entry:\n") emith(" %e = call ptr @getenv(ptr %name)\n") emith(" %has = icmp ne ptr %e, null\n") emith(" br i1 %has, label %read, label %none\n") emith("read:\n") emith(" %v = call i32 @atoi(ptr %e)\n") emith(" %v64 = sext i32 %v to i64\n") emith(" ret i64 %v64\n") emith("none:\n") emith(" ret i64 %dflt\n") emith("}\n") emith("define internal void @lp_finit() {\n") emith("entry:\n") emith(" %m0 = load i8, ptr @lp_fm\n") emith(" %done = icmp ne i8 %m0, 0\n") emith(" br i1 %done, label %out, label %go\n") emith("go:\n") emith(" %e = call ptr @getenv(ptr @.lpf_env)\n") emith(" %has = icmp ne ptr %e, null\n") emith(" br i1 %has, label %parse, label %dflt\n") emith("parse:\n") emith(" %c1 = call i32 @strcmp(ptr %e, ptr @.lpf_off)\n") emith(" %is1 = icmp eq i32 %c1, 0\n") emith(" %c2 = call i32 @strcmp(ptr %e, ptr @.lpf_count)\n") emith(" %is2 = icmp eq i32 %c2, 0\n") emith(" %c3 = call i32 @strcmp(ptr %e, ptr @.lpf_warn)\n") emith(" %is3 = icmp eq i32 %c3, 0\n") emith(" %ma = select i1 %is3, i8 3, i8 4\n") emith(" %mb = select i1 %is2, i8 2, i8 %ma\n") emith(" %mc = select i1 %is1, i8 1, i8 %mb\n") emith(" br label %set\n") emith("dflt:\n") emith(" %d = load i8, ptr @lp_fdef\n") emith(" %dz = icmp eq i8 %d, 0\n") emith(" br i1 %dz, label %dev, label %set\n") emith("dev:\n") emith(" %dv = call ptr @getenv(ptr @.lpf_dev)\n") emith(" %hd = icmp ne ptr %dv, null\n") emith(" %md = select i1 %hd, i8 4, i8 1\n") emith(" br label %set\n") emith("set:\n") emith(" %mode = phi i8 [ %mc, %parse ], [ %d, %dflt ], [ %md, %dev ]\n") emith(" store i8 %mode, ptr @lp_fm\n") emith(" %wd = load i64, ptr @lp_warm\n") emith(" %w = call i64 @lp_fenv(ptr @.lpf_warm, i64 %wd)\n") emith(" store i64 %w, ptr @lp_warm\n") emith(" %wx5 = mul i64 %w, 5\n") emith(" %wm = call i64 @lp_fenv(ptr @.lpf_warmmax, i64 %wx5)\n") emith(" store i64 %wm, ptr @lp_warm_max\n") emith(" %dwv = call i64 @lp_fenv(ptr @.lpf_dwin, i64 600)\n") emith(" store i64 %dwv, ptr @lp_dwin\n") emith(" %drv = call i64 @lp_fenv(ptr @.lpf_drise, i64 6)\n") emith(" store i64 %drv, ptr @lp_drise\n") emith(" %au = call i64 @lp_fenv(ptr @.lpf_auto, i64 1)\n") emith(" %au8 = trunc i64 %au to i8\n") emith(" store i8 %au8, ptr @lp_fauto\n") emith(" %pl = call i64 @lp_fenv(ptr @.lpf_play, i64 -1)\n") emith(" store i64 %pl, ptr @lp_autoplay\n") emith(" %want = call i64 @lp_fenv(ptr @.lpf_tab, i64 4194304)\n") emith(" br label %cap\n") emith("cap:\n") emith(" %c = phi i64 [ 1024, %set ], [ %c2x, %grow ]\n") emith(" %big = icmp sge i64 %c, %want\n") emith(" br i1 %big, label %capped, label %grow\n") emith("grow:\n") emith(" %c2x = shl i64 %c, 1\n") emith(" br label %cap\n") emith("capped:\n") emith(" %mask = sub i64 %c, 1\n") emith(" store i64 %mask, ptr @lp_tabmask\n") emith(" %q = lshr i64 %c, 2\n") emith(" %max = mul i64 %q, 3\n") emith(" store i64 %max, ptr @lp_tabmax\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("define internal void @lp_fsnap() {\n") emith("entry:\n") emith(" %lv = load i64, ptr @lp_live\n") emith(" store i64 %lv, ptr @lp_mlive\n") emith(" %dlm = load i64, ptr @lp_dlive\n") emith(" store i64 %dlm, ptr @lp_mdlive\n") emith(" %pr = load i64, ptr @lp_pre\n") emith(" store i64 %pr, ptr @lp_mpre\n") emith(" %md = load i64, ptr @lp_made\n") emith(" store i64 %md, ptr @lp_mmade\n") emith(" %fr = load i64, ptr @lp_freed\n") emith(" store i64 %fr, ptr @lp_mfreed\n") emith(" store i32 0, ptr @lp_ntouch\n") emith(" ret void\n") emith("}\n") emith("define internal void @lp_fsnap_all() {\n") emith("entry:\n") emith(" %n = load i32, ptr @lp_site_n\n") emith(" %n64 = zext i32 %n to i64\n") emith(" %b = shl i64 %n64, 3\n") emith(" call ptr @memcpy(ptr @lp_site_mark, ptr @lp_site_live, i64 %b)\n") emith(" call void @lp_fsnap()\n") emith(" ret void\n") emith("}\n") emith("define void @lp_mem_play() {\n") emith("entry:\n") emith(" call void @lp_finit()\n") emith(" %m = load i8, ptr @lp_fm\n") emith(" %off = icmp ule i8 %m, 1\n") emith(" br i1 %off, label %out, label %chk\n") emith("chk:\n") emith(" %f = load i64, ptr @lp_frame\n") emith(" %t = load i8, ptr @lp_ft\n") emith(" %on = icmp ne i8 %t, 0\n") emith(" br i1 %on, label %rewarm, label %start\n") emith("rewarm:\n") emith(" ; a screen opened: warm again, but the cap keeps its first deadline - growth that never stops must\n") emith(" ; not keep the fence from judging - and past it a rewarm has R3D_ALLOC_REWARM frames of grace\n") emith(" call void @lp_flock()\n") emith(" store i8 0, ptr @lp_fj\n") emith(" store i64 0, ptr @lp_flat\n") emith(" %rw = call i64 @lp_fenv(ptr @.lpf_rewarm, i64 120)\n") emith(" %wmx = load i64, ptr @lp_warm_max\n") emith(" %pf0 = load i64, ptr @lp_playf\n") emith(" %fr = add i64 %f, %rw\n") emith(" %pfg = sub i64 %fr, %wmx\n") emith(" %later = icmp sgt i64 %pfg, %pf0\n") emith(" %pf1 = select i1 %later, i64 %pfg, i64 %pf0\n") emith(" store i64 %pf1, ptr @lp_playf\n") emith(" call void @lp_funlock()\n") emith(" br label %out\n") emith("start:\n") emith(" %tab = load ptr, ptr @lp_tab\n") emith(" %none = icmp eq ptr %tab, null\n") emith(" br i1 %none, label %make, label %arm\n") emith("make:\n") emith(" %mask = load i64, ptr @lp_tabmask\n") emith(" %c = add i64 %mask, 1\n") emith(" %p = call ptr @calloc(i64 %c, i64 16)\n") emith(" store ptr %p, ptr @lp_tab\n") emith(" br label %arm\n") emith("arm:\n") emith(" store i64 %f, ptr @lp_playf\n") emith(" store i64 0, ptr @lp_flat\n") emith(" %cp0 = call ptr @getenv(ptr @.lpf_census)\n") emith(" %cpd = load ptr, ptr @lp_census_def\n") emith(" %hasenv = icmp ne ptr %cp0, null\n") emith(" %cp = select i1 %hasenv, ptr %cp0, ptr %cpd\n") emith(" store ptr %cp, ptr @lp_census\n") emith(" %hascp = icmp ne ptr %cp, null\n") emith(" br i1 %hascp, label %reg, label %go\n") emith("reg:\n") emith(" call i32 @atexit(ptr @lp_fcensus)\n") emith(" br label %go\n") emith("go:\n") emith(" %ex = call i64 @lp_fenv(ptr @.lpf_exitscan, i64 0)\n") emith(" %exq = icmp ne i64 %ex, 0\n") emith(" br i1 %exq, label %regx, label %go2\n") emith("regx:\n") emith(" call i32 @atexit(ptr @lp_fexitscan)\n") emith(" br label %go2\n") emith("go2:\n") emith(" call void @lp_fsnap_all()\n") emith(" store i8 1, ptr @lp_ft\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("define void @lp_mem_settled() {\n") emith("entry:\n") emith(" %t = load i8, ptr @lp_ft\n") emith(" %on = icmp ne i8 %t, 0\n") emith(" br i1 %on, label %chk, label %out\n") emith("chk:\n") emith(" %j = load i8, ptr @lp_fj\n") emith(" %already = icmp ne i8 %j, 0\n") emith(" br i1 %already, label %out, label %go\n") emith("go:\n") emith(" call void @lp_flock()\n") emith(" call void @lp_fsnap_all()\n") emith(" call void @lp_fsettle_locked()\n") emith(" call void @lp_funlock()\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("define i64 @lp_mem_kept() {\n") emith("entry:\n") emith(" %j = load i8, ptr @lp_fj\n") emith(" %on = icmp ne i8 %j, 0\n") emith(" br i1 %on, label %read, label %none\n") emith("none:\n") emith(" ret i64 0\n") emith("read:\n") emith(" call void @lp_flock()\n") emith(" %lv = load i64, ptr @lp_live\n") emith(" %sl = load i64, ptr @lp_slive\n") emith(" %pr = load i64, ptr @lp_pre\n") emith(" %sp = load i64, ptr @lp_spre\n") emith(" %a0 = sub i64 %lv, %sl\n") emith(" %dlk = load i64, ptr @lp_dlive\n") emith(" %sdl = load i64, ptr @lp_sdlive\n") emith(" %ddk = sub i64 %dlk, %sdl\n") emith(" %a = sub i64 %a0, %ddk\n") emith(" %b = sub i64 %pr, %sp\n") emith(" %k = sub i64 %a, %b\n") emith(" call void @lp_funlock()\n") emith(" ret i64 %k\n") emith("}\n") emith("define i64 @lp_mem_bad_frames() {\n") emith("entry:\n") emith(" %b = load i64, ptr @lp_fbad\n") emith(" ret i64 %b\n") emith("}\n") } function emit_fence_report() -> void { emith("define internal i64 @lp_fdelta(i32 %s, ptr %cur, ptr %base) {\n") emith("entry:\n") emith(" %sp = getelementptr inbounds i64, ptr %cur, i32 %s\n") emith(" %v = load i64, ptr %sp\n") emith(" %mp = getelementptr inbounds i64, ptr %base, i32 %s\n") emith(" %m = load i64, ptr %mp\n") emith(" %d = sub i64 %v, %m\n") emith(" ret i64 %d\n") emith("}\n") emith("define internal i32 @lp_fsite_at(i32 %i, i1 %all) {\n") emith("entry:\n") emith(" br i1 %all, label %every, label %touched\n") emith("every:\n") emith(" ret i32 %i\n") emith("touched:\n") emith(" %tp = getelementptr inbounds [512 x i32], ptr @lp_touch, i32 0, i32 %i\n") emith(" %s = load i32, ptr %tp\n") emith(" ret i32 %s\n") emith("}\n") emith("define internal { i64, i32 } @lp_fpick(ptr %cur, ptr %base, i1 %all, i32 %cnt, i64 %pb, i32 %ps) {\n") emith("entry:\n") emith(" br label %loop\n") emith("loop:\n") emith(" %i = phi i32 [ 0, %entry ], [ %i1, %body ]\n") emith(" %bb0 = phi i64 [ 0, %entry ], [ %bb1, %body ]\n") emith(" %bs0 = phi i32 [ -1, %entry ], [ %bs1, %body ]\n") emith(" %go = icmp ult i32 %i, %cnt\n") emith(" br i1 %go, label %body, label %done\n") emith("body:\n") emith(" %s = call i32 @lp_fsite_at(i32 %i, i1 %all)\n") emith(" %d = call i64 @lp_fdelta(i32 %s, ptr %cur, ptr %base)\n") emith(" %pos = icmp sgt i64 %d, 0\n") emith(" %lt = icmp slt i64 %d, %pb\n") emith(" %eqb = icmp eq i64 %d, %pb\n") emith(" %gts = icmp sgt i32 %s, %ps\n") emith(" %tie = and i1 %eqb, %gts\n") emith(" %below = or i1 %lt, %tie\n") emith(" %gtb = icmp sgt i64 %d, %bb0\n") emith(" %eqbb = icmp eq i64 %d, %bb0\n") emith(" %lts = icmp slt i32 %s, %bs0\n") emith(" %tie2 = and i1 %eqbb, %lts\n") emith(" %better = or i1 %gtb, %tie2\n") emith(" %c1 = and i1 %pos, %below\n") emith(" %take = and i1 %c1, %better\n") emith(" %bb1 = select i1 %take, i64 %d, i64 %bb0\n") emith(" %bs1 = select i1 %take, i32 %s, i32 %bs0\n") emith(" %i1 = add i32 %i, 1\n") emith(" br label %loop\n") emith("done:\n") emith(" %r0 = insertvalue { i64, i32 } undef, i64 %bb0, 0\n") emith(" %r1 = insertvalue { i64, i32 } %r0, i32 %bs0, 1\n") emith(" ret { i64, i32 } %r1\n") emith("}\n") emith("define internal void @lp_fsite_row(ptr %fp, i32 %fd, i64 %bytes, i32 %s, ptr %cfmt) {\n") emith("entry:\n") emith(" %fnp = getelementptr inbounds ptr, ptr @lp_site_fn, i32 %s\n") emith(" %fn = load ptr, ptr %fnp\n") emith(" %flp = getelementptr inbounds ptr, ptr @lp_site_file, i32 %s\n") emith(" %fl = load ptr, ptr %flp\n") emith(" %lnp = getelementptr inbounds i32, ptr @lp_site_line, i32 %s\n") emith(" %ln = load i32, ptr %lnp\n") emith(" %kdp = getelementptr inbounds ptr, ptr @lp_site_kind, i32 %s\n") emith(" %kd = load ptr, ptr %kdp\n") emith(" %tofile = icmp ne ptr %fp, null\n") emith(" br i1 %tofile, label %file, label %err\n") emith("file:\n") emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr %cfmt, i64 %bytes, ptr %fn, ptr %fl, i32 %ln, ptr %kd)\n") emith(" br label %from\n") emith("err:\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 %fd, ptr @.lpf_row, i64 %bytes, ptr %fn, ptr %fl, i32 %ln, ptr %kd)\n") emith(" br label %from\n") emith("from:\n") emith(" call void @lp_fsite_from(ptr %fp, i32 %s, ptr %fn)\n") emith(" ret void\n") emith("}\n") emith("; the largest `rows` sites by what they hold over `base`, largest first\n") emith("define internal void @lp_franked(ptr %fp, ptr %cur, ptr %base, ptr %cfmt, i1 %all, i32 %cnt, i32 %rows) {\n") emith("entry:\n") emith(" br label %pass\n") emith("pass:\n") emith(" %row = phi i32 [ 0, %entry ], [ %row1, %show ]\n") emith(" %pb = phi i64 [ 9223372036854775807, %entry ], [ %bb, %show ]\n") emith(" %ps = phi i32 [ -1, %entry ], [ %bs, %show ]\n") emith(" %more = icmp ult i32 %row, %rows\n") emith(" br i1 %more, label %scan, label %tail\n") emith("scan:\n") emith(" %r = call { i64, i32 } @lp_fpick(ptr %cur, ptr %base, i1 %all, i32 %cnt, i64 %pb, i32 %ps)\n") emith(" %bb = extractvalue { i64, i32 } %r, 0\n") emith(" %bs = extractvalue { i64, i32 } %r, 1\n") emith(" %found = icmp sge i32 %bs, 0\n") emith(" br i1 %found, label %show, label %tail\n") emith("show:\n") emith(" call void @lp_fsite_row(ptr %fp, i32 2, i64 %bb, i32 %bs, ptr %cfmt)\n") emith(" %row1 = add i32 %row, 1\n") emith(" br label %pass\n") emith("tail:\n") emith(" ret void\n") emith("}\n") emith("define internal void @lp_freport(i64 %f, i64 %kept) {\n") emith("entry:\n") emith(" %md = load i64, ptr @lp_made\n") emith(" %mm = load i64, ptr @lp_mmade\n") emith(" %made = sub i64 %md, %mm\n") emith(" %fr = load i64, ptr @lp_freed\n") emith(" %mf = load i64, ptr @lp_mfreed\n") emith(" %freed = sub i64 %fr, %mf\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 2, ptr @.lpf_hdr, i64 %f, i64 %kept, i64 %made, i64 %freed)\n") emith(" %nt = load i32, ptr @lp_ntouch\n") emith(" %all = icmp ugt i32 %nt, 512\n") emith(" %sn = load i32, ptr @lp_site_n\n") emith(" %cnt = select i1 %all, i32 %sn, i32 %nt\n") emith(" call void @lp_franked(ptr null, ptr @lp_site_live, ptr @lp_site_mark, ptr @.lpf_crow, i1 %all, i32 %cnt, i32 12)\n") emith(" ret void\n") emith("}\n") emith("; R3D_ALLOC_CENSUS=, written at exit: the run's totals since play settled, and every site\n") emith("; that holds more than it did then, largest first\n") emith("define void @lp_fcensus() {\n") emith("entry:\n") emith(" %path = load ptr, ptr @lp_census\n") emith(" %none = icmp eq ptr %path, null\n") emith(" br i1 %none, label %out, label %open\n") emith("open:\n") emith(" %zn = call i64 @lp_fzone()\n") emith(" %jn = call i64 @lp_fnat(ptr @.lpf_jb)\n") emith(" %jpk = call i64 @lp_fnat(ptr @.lpf_jp)\n") emith(" %vn = call i64 @lp_fnat(ptr @.lpf_vb)\n") emith(" %vpk = call i64 @lp_fnat(ptr @.lpf_vp)\n") emith(" %fp = call ptr @fopen(ptr %path, ptr @.lpf_w)\n") emith(" %bad = icmp eq ptr %fp, null\n") emith(" br i1 %bad, label %out, label %write\n") emith("write:\n") emith(" store i8 0, ptr @lp_ft\n") emith(" %j = load i64, ptr @lp_fjudged\n") emith(" %b = load i64, ptr @lp_fbad\n") emith(" %k = call i64 @lp_mem_kept()\n") emith(" %md = load i64, ptr @lp_made\n") emith(" %fr = load i64, ptr @lp_freed\n") emith(" %ov = load i64, ptr @lp_over\n") emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_chdr, i64 %j, i64 %b, i64 %k, i64 %md, i64 %fr, i64 %ov)\n") emith(" %jq = icmp ne i64 %j, 0\n") emith(" %zs = load i64, ptr @lp_zset\n") emith(" %zd = sub i64 %zn, %zs\n") emith(" %js = load i64, ptr @lp_jset\n") emith(" %jd = sub i64 %jn, %js\n") emith(" %vs = load i64, ptr @lp_vset\n") emith(" %vd = sub i64 %vn, %vs\n") emith(" %dnw = load i64, ptr @lp_dlive\n") emith(" %dst = load i64, ptr @lp_sdlive\n") emith(" %dgr = sub i64 %dnw, %dst\n") emith(" %nat0 = sub i64 %zd, %k\n") emith(" %nat = sub i64 %nat0, %dgr\n") emith(" %nat2 = sub i64 %nat, %jd\n") emith(" %nat3 = sub i64 %nat2, %vd\n") emith(" %nat1 = select i1 %jq, i64 %nat3, i64 0\n") emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_cnat, i64 %nat1)\n") emith(" %dnow = load i64, ptr @lp_dlive\n") emith(" %dset = load i64, ptr @lp_sdlive\n") 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(" %capn = load i64, ptr @lp_capn\n") emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_ccap, i64 %capn)\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") emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_cvk, i64 %vd1, i64 %vpk)\n") emith(" %sn = load i32, ptr @lp_site_n\n") emith(" %dun = load i64, ptr @lp_dunb\n") emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_cdunb, i64 %dun)\n") emith(" call void @lp_franked(ptr %fp, ptr @lp_site_live, ptr @lp_site_base, ptr @.lpf_crow, i1 1, i32 %sn, i32 40)\n") emith(" call void @lp_franked(ptr %fp, ptr @lp_site_dlive, ptr @lp_site_dbase, ptr @.lpf_cdrow, i1 1, i32 %sn, i32 40)\n") emith(" call void @lp_fowners(ptr %fp)\n") emith(" call i32 @fclose(ptr %fp)\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") } function emit_fence_frame() -> void { emith("define internal void @lp_fmark_touched() {\n") emith("entry:\n") emith(" %nt = load i32, ptr @lp_ntouch\n") emith(" %all = icmp ugt i32 %nt, 512\n") emith(" br i1 %all, label %every, label %some\n") emith("every:\n") emith(" call void @lp_fsnap_all()\n") emith(" ret void\n") emith("some:\n") emith(" br label %loop\n") emith("loop:\n") emith(" %i = phi i32 [ 0, %some ], [ %i1, %body ]\n") emith(" %go = icmp ult i32 %i, %nt\n") emith(" br i1 %go, label %body, label %done\n") emith("body:\n") emith(" %tp = getelementptr inbounds [512 x i32], ptr @lp_touch, i32 0, i32 %i\n") emith(" %s = load i32, ptr %tp\n") emith(" %sp = getelementptr inbounds i64, ptr @lp_site_live, i32 %s\n") emith(" %v = load i64, ptr %sp\n") emith(" %mp = getelementptr inbounds i64, ptr @lp_site_mark, i32 %s\n") emith(" store i64 %v, ptr %mp\n") emith(" %i1 = add i32 %i, 1\n") emith(" br label %loop\n") emith("done:\n") emith(" call void @lp_fsnap()\n") emith(" ret void\n") emith("}\n") emith("; malloc's live bytes over every zone (0 where there is no malloc_zone_statistics)\n") emith("define internal i64 @lp_fzone() {\n") emith("entry:\n") emith(" %has = icmp ne ptr @malloc_zone_statistics, null\n") emith(" br i1 %has, label %read, label %none\n") emith("none:\n") emith(" ret i64 0\n") emith("read:\n") emith(" %st = alloca [4 x i64], align 8\n") emith(" call void @malloc_zone_statistics(ptr null, ptr %st)\n") emith(" %p = getelementptr [4 x i64], ptr %st, i32 0, i32 1\n") emith(" %n = load i64, ptr %p\n") emith(" ret i64 %n\n") emith("}\n") emith("; a counted native library's number, found by name (ludic.physics' jph_heap_*, the Vulkan runtime's\n") emith("; lvk_ac_*): 0 when the program does not carry it, and nothing is declared that the package declares\n") emith("define internal i64 @lp_fnat(ptr %name) {\n") emith("entry:\n") emith(" %rtld_default = inttoptr i64 -2 to ptr\n") emith(" %f = call ptr @dlsym(ptr %rtld_default, ptr %name)\n") emith(" %none = icmp eq ptr %f, null\n") emith(" br i1 %none, label %zero, label %call\n") emith("zero:\n") emith(" ret i64 0\n") emith("call:\n") emith(" %v = call i64 %f()\n") emith(" ret i64 %v\n") emith("}\n") emith("; 25.5a: a list declared @max(n) grew past n, or a package's table filled (Mem.over): said under\n") emith("; warn, and under fail the run ends with exit 87 - silent when the fence is off\n") emith("define void @lp_cap_over(ptr %name, i32 %cap, i32 %len) {\n") emith("entry:\n") emith(" call void @lp_finit()\n") emith(" %m = load i8, ptr @lp_fm\n") emith(" %off = icmp ule i8 %m, 1\n") emith(" br i1 %off, label %out, label %count\n") emith("count:\n") emith(" %c = load i64, ptr @lp_capn\n") emith(" %c1 = add i64 %c, 1\n") emith(" store i64 %c1, ptr @lp_capn\n") emith(" %say = icmp uge i8 %m, 3\n") emith(" br i1 %say, label %which, label %out\n") emith("which:\n") emith(" %isfull = icmp eq i32 %cap, 0\n") emith(" br i1 %isfull, label %full, label %over\n") emith("full:\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 2, ptr @.lpf_full, ptr %name)\n") emith(" br label %judge\n") emith("over:\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 2, ptr @.lpf_capover, ptr %name, i32 %cap, i32 %len)\n") emith(" br label %judge\n") emith("judge:\n") emith(" %fail = icmp eq i8 %m, 4\n") emith(" br i1 %fail, label %die, label %out\n") emith("die:\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 2, ptr @.lpf_capfail)\n") emith(" call void @exit(i32 87)\n") emith(" unreachable\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("; 25.5b: a leak by reachability. From every global (the states among them) each word that is the\n") emith("; start of a heap block (malloc_size says so) is followed, conservatively, through every block; a\n") emith("; tracked block nothing reaches is a leak whatever a frame's totals say. R3D_ALLOC_SCAN=\n") emith("; runs it at that frame's mark (when no function is running), Mem.scan() whenever asked\n") emith("define internal i1 @lp_vput(i64 %k) {\n") emith("entry:\n") emith(" %mask = load i64, ptr @lp_vmask\n") emith(" %tab = load ptr, ptr @lp_visit_set\n") emith(" %h = call i64 @lp_fhash(i64 %k)\n") emith(" br label %probe\n") emith("probe:\n") emith(" %i = phi i64 [ %h, %entry ], [ %i1, %next ]\n") emith(" %im = and i64 %i, %mask\n") emith(" %e = getelementptr inbounds i64, ptr %tab, i64 %im\n") emith(" %ek = load i64, ptr %e\n") emith(" %empty = icmp eq i64 %ek, 0\n") emith(" br i1 %empty, label %put, label %cmp\n") emith("cmp:\n") emith(" %same = icmp eq i64 %ek, %k\n") emith(" br i1 %same, label %was, label %next\n") emith("next:\n") emith(" %i1 = add i64 %im, 1\n") emith(" br label %probe\n") emith("put:\n") emith(" store i64 %k, ptr %e\n") emith(" ret i1 1\n") emith("was:\n") emith(" ret i1 0\n") emith("}\n") emith("define internal i1 @lp_vhas(i64 %k) {\n") emith("entry:\n") emith(" %mask = load i64, ptr @lp_vmask\n") emith(" %tab = load ptr, ptr @lp_visit_set\n") emith(" %h = call i64 @lp_fhash(i64 %k)\n") emith(" br label %probe\n") emith("probe:\n") emith(" %i = phi i64 [ %h, %entry ], [ %i1, %next ]\n") emith(" %im = and i64 %i, %mask\n") emith(" %e = getelementptr inbounds i64, ptr %tab, i64 %im\n") emith(" %ek = load i64, ptr %e\n") emith(" %empty = icmp eq i64 %ek, 0\n") emith(" br i1 %empty, label %no, label %cmp\n") emith("cmp:\n") emith(" %same = icmp eq i64 %ek, %k\n") emith(" br i1 %same, label %yes, label %next\n") emith("next:\n") emith(" %i1 = add i64 %im, 1\n") emith(" br label %probe\n") emith("yes:\n") emith(" ret i1 1\n") emith("no:\n") emith(" ret i1 0\n") emith("}\n") emith("; a candidate is followed only if it could be a heap block's start: 16-aligned (malloc's), inside the\n") emith("; user address space (above the first 4 GB, below 2^47 - a word with high bits is data, and some\n") emith("; zones fault looking one up), and not in the frame arena; only then does malloc_size look at it\n") emith("define internal void @lp_visit(i64 %w) {\n") emith("entry:\n") emith(" %al = and i64 %w, 15\n") emith(" %mis = icmp ne i64 %al, 0\n") emith(" %low = icmp ult i64 %w, 4294967296\n") emith(" %high = icmp uge i64 %w, 140737488355328\n") emith(" %s1 = or i1 %mis, %low\n") emith(" %s2 = or i1 %s1, %high\n") emith(" br i1 %s2, label %out, label %arena\n") emith("arena:\n") emith(" %wp = inttoptr i64 %w to ptr\n") emith(" %inar = call i1 @lp_in_arena(ptr %wp)\n") emith(" br i1 %inar, label %out, label %size\n") emith("size:\n") emith(" %p = inttoptr i64 %w to ptr\n") emith(" %sz = call i64 @malloc_size(ptr %p)\n") emith(" %nz = icmp eq i64 %sz, 0\n") emith(" br i1 %nz, label %out, label %mark\n") emith("mark:\n") emith(" %new = call i1 @lp_vput(i64 %w)\n") emith(" br i1 %new, label %queue, label %out\n") emith("queue:\n") emith(" %n = load i64, ptr @lp_wln\n") emith(" %cap = load i64, ptr @lp_wlcap\n") emith(" %full = icmp uge i64 %n, %cap\n") emith(" br i1 %full, label %grow, label %push\n") emith("grow:\n") emith(" %nc0 = shl i64 %cap, 1\n") emith(" %small = icmp ult i64 %nc0, 65536\n") emith(" %nc = select i1 %small, i64 65536, i64 %nc0\n") emith(" %old = load ptr, ptr @lp_wl\n") emith(" %bytes = shl i64 %nc, 3\n") emith(" %nw = call ptr @realloc(ptr %old, i64 %bytes)\n") emith(" store ptr %nw, ptr @lp_wl\n") emith(" store i64 %nc, ptr @lp_wlcap\n") emith(" br label %push\n") emith("push:\n") emith(" %wl = load ptr, ptr @lp_wl\n") emith(" %slot = getelementptr inbounds i64, ptr %wl, i64 %n\n") emith(" store i64 %w, ptr %slot\n") emith(" %n1 = add i64 %n, 1\n") emith(" store i64 %n1, ptr @lp_wln\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("; R3D_ALLOC_EXIT=1: the same scan as the program quits - what nothing holds any more is what leaked\n") emith("define internal void @lp_fexitscan() {\n") emith("entry:\n") emith(" call i64 @lp_mem_scan()\n") emith(" ret void\n") emith("}\n") emith("define i64 @lp_mem_scan() {\n") emith("entry:\n") emith(" %t = load i8, ptr @lp_ft\n") emith(" %on = icmp ne i8 %t, 0\n") emith(" %hasms = icmp ne ptr @malloc_size, null\n") emith(" %go = and i1 %on, %hasms\n") emith(" br i1 %go, label %prep, label %none\n") emith("none:\n") emith(" ret i64 0\n") emith("prep:\n") emith(" call void @lp_flock()\n") emith(" %vs = load ptr, ptr @lp_visit_set\n") emith(" %vnone = icmp eq ptr %vs, null\n") emith(" br i1 %vnone, label %make, label %clear\n") emith("make:\n") emith(" %v = call ptr @calloc(i64 8388608, i64 8)\n") emith(" store ptr %v, ptr @lp_visit_set\n") emith(" store i64 8388607, ptr @lp_vmask\n") emith(" br label %roots\n") emith("clear:\n") emith(" call ptr @memset(ptr %vs, i32 0, i64 67108864)\n") emith(" br label %roots\n") emith("roots:\n") emith(" store i64 0, ptr @lp_wln\n") emith(" %nr = load i32, ptr @lp_nroots\n") emith(" br label %rl\n") emith("rl:\n") emith(" %ri = phi i32 [ 0, %roots ], [ %ri1, %rb ]\n") emith(" %rgo = icmp ult i32 %ri, %nr\n") emith(" br i1 %rgo, label %rb, label %walk\n") emith("rb:\n") emith(" %rp = getelementptr inbounds ptr, ptr @lp_roots, i32 %ri\n") emith(" %g = load ptr, ptr %rp\n") emith(" %gv = load i64, ptr %g\n") emith(" call void @lp_visit(i64 %gv)\n") emith(" %ri1 = add i32 %ri, 1\n") emith(" br label %rl\n") emith("walk:\n") emith(" %n = load i64, ptr @lp_wln\n") emith(" %done = icmp eq i64 %n, 0\n") emith(" br i1 %done, label %sweep, label %pop\n") emith("pop:\n") emith(" %n1 = sub i64 %n, 1\n") emith(" store i64 %n1, ptr @lp_wln\n") emith(" %wl = load ptr, ptr @lp_wl\n") emith(" %sp = getelementptr inbounds i64, ptr %wl, i64 %n1\n") emith(" %b = load i64, ptr %sp\n") emith(" %bp = inttoptr i64 %b to ptr\n") emith(" %bsz = call i64 @malloc_size(ptr %bp)\n") emith(" %words = lshr i64 %bsz, 3\n") emith(" br label %wordl\n") emith("wordl:\n") emith(" %wi = phi i64 [ 0, %pop ], [ %wi1, %wordb ]\n") emith(" %wgo = icmp ult i64 %wi, %words\n") emith(" br i1 %wgo, label %wordb, label %walk\n") emith("wordb:\n") emith(" %wp = getelementptr inbounds i64, ptr %bp, i64 %wi\n") emith(" %wv = load i64, ptr %wp\n") emith(" call void @lp_visit(i64 %wv)\n") emith(" %wi1 = add i64 %wi, 1\n") emith(" br label %wordl\n") emith("sweep:\n") emith(" %sn = load i32, ptr @lp_site_n\n") emith(" %sn64 = zext i32 %sn to i64\n") emith(" %sb = shl i64 %sn64, 3\n") emith(" call ptr @memset(ptr @lp_site_scan, i32 0, i64 %sb)\n") emith(" %mask = load i64, ptr @lp_tabmask\n") emith(" %cap = add i64 %mask, 1\n") emith(" %tab = load ptr, ptr @lp_tab\n") emith(" br label %tl\n") emith("tl:\n") emith(" %ti = phi i64 [ 0, %sweep ], [ %ti1, %tnext ]\n") emith(" %lost = phi i64 [ 0, %sweep ], [ %lost2, %tnext ]\n") emith(" %lostn = phi i64 [ 0, %sweep ], [ %lostn2, %tnext ]\n") emith(" %tgo = icmp ult i64 %ti, %cap\n") emith(" br i1 %tgo, label %tb, label %report\n") emith("tb:\n") emith(" %e = getelementptr inbounds [2 x i64], ptr %tab, i64 %ti\n") emith(" %ek = load i64, ptr %e\n") emith(" %empty = icmp eq i64 %ek, 0\n") emith(" br i1 %empty, label %tnext, label %tchk\n") emith("tchk:\n") emith(" %seen = call i1 @lp_vhas(i64 %ek)\n") emith(" br i1 %seen, label %tnext, label %tlost\n") emith("tlost:\n") emith(" %ev = getelementptr inbounds i64, ptr %e, i64 1\n") emith(" %val = load i64, ptr %ev\n") emith(" %sz = and i64 %val, 549755813887\n") emith(" %site = lshr i64 %val, 40\n") emith(" %ssp = getelementptr inbounds i64, ptr @lp_site_scan, i64 %site\n") emith(" %sv = load i64, ptr %ssp\n") emith(" %sv1 = add i64 %sv, %sz\n") emith(" store i64 %sv1, ptr %ssp\n") emith(" br label %tnext\n") emith("tnext:\n") emith(" %add = phi i64 [ 0, %tb ], [ 0, %tchk ], [ %sz, %tlost ]\n") emith(" %addn = phi i64 [ 0, %tb ], [ 0, %tchk ], [ 1, %tlost ]\n") emith(" %lost2 = add i64 %lost, %add\n") emith(" %lostn2 = add i64 %lostn, %addn\n") emith(" %ti1 = add i64 %ti, 1\n") emith(" br label %tl\n") emith("report:\n") emith(" store i64 %lost, ptr @lp_scan_bytes\n") emith(" %f = load i64, ptr @lp_frame\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 2, ptr @.lpf_shdr, i64 %f, i64 %lost, i64 %lostn)\n") emith(" %top = call i64 @lp_fenv(ptr @.lpf_scantop, i64 24)\n") emith(" %top32 = trunc i64 %top to i32\n") emith(" call void @lp_franked_vals(ptr @lp_site_scan, i32 %sn, i32 %top32)\n") emith(" %sfp = call ptr @getenv(ptr @.lpf_scanfile)\n") emith(" %hasf = icmp ne ptr %sfp, null\n") emith(" br i1 %hasf, label %tofile, label %fin\n") emith("tofile:\n") emith(" %fh = call ptr @fopen(ptr %sfp, ptr @.lpf_a)\n") emith(" %fok = icmp ne ptr %fh, null\n") emith(" br i1 %fok, label %rows, label %fin\n") emith("rows:\n") emith(" %ri2 = phi i32 [ 0, %tofile ], [ %ri3, %rnext ]\n") emith(" %more = icmp ult i32 %ri2, %sn\n") emith(" br i1 %more, label %row, label %close\n") emith("row:\n") emith(" %rsp = getelementptr inbounds i64, ptr @lp_site_scan, i32 %ri2\n") emith(" %rv = load i64, ptr %rsp\n") emith(" %has = icmp sgt i64 %rv, 0\n") emith(" br i1 %has, label %say, label %rnext\n") emith("say:\n") emith(" %fnp = getelementptr inbounds ptr, ptr @lp_site_fn, i32 %ri2\n") emith(" %fn = load ptr, ptr %fnp\n") emith(" %flp = getelementptr inbounds ptr, ptr @lp_site_file, i32 %ri2\n") emith(" %fl = load ptr, ptr %flp\n") emith(" %lnp = getelementptr inbounds i32, ptr @lp_site_line, i32 %ri2\n") emith(" %ln = load i32, ptr %lnp\n") emith(" %kdp = getelementptr inbounds ptr, ptr @lp_site_kind, i32 %ri2\n") emith(" %kd = load ptr, ptr %kdp\n") emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fh, ptr @.lpf_sfrow, i64 %rv, ptr %fn, ptr %fl, i32 %ln, ptr %kd)\n") emith(" br label %rnext\n") emith("rnext:\n") emith(" %ri3 = add i32 %ri2, 1\n") emith(" br label %rows\n") emith("close:\n") emith(" call i32 @fclose(ptr %fh)\n") emith(" br label %fin\n") emith("fin:\n") emith(" call void @lp_funlock()\n") emith(" ret i64 %lost\n") emith("}\n") emith("; 25.5c: the census by owner - what each state holds of what its sites made, and how much it grew\n") emith("define internal void @lp_fowners(ptr %fp) {\n") emith("entry:\n") emith(" %no = load i32, ptr @lp_nowners\n") emith(" %sn = load i32, ptr @lp_site_n\n") emith(" br label %ol\n") emith("ol:\n") emith(" %o = phi i32 [ 1, %entry ], [ %o1, %onext ]\n") emith(" %ogo = icmp ule i32 %o, %no\n") emith(" br i1 %ogo, label %sl0, label %done\n") emith("sl0:\n") emith(" br label %sl\n") emith("sl:\n") emith(" %s = phi i32 [ 0, %sl0 ], [ %s1, %snext ]\n") emith(" %live = phi i64 [ 0, %sl0 ], [ %live2, %snext ]\n") emith(" %grew = phi i64 [ 0, %sl0 ], [ %grew2, %snext ]\n") emith(" %sgo = icmp ult i32 %s, %sn\n") emith(" br i1 %sgo, label %sb, label %say\n") emith("sb:\n") emith(" %op = getelementptr inbounds i32, ptr @lp_site_owner, i32 %s\n") emith(" %ow = load i32, ptr %op\n") emith(" %mine = icmp eq i32 %ow, %o\n") emith(" %lp = getelementptr inbounds i64, ptr @lp_site_live, i32 %s\n") emith(" %lv = load i64, ptr %lp\n") emith(" %bp = getelementptr inbounds i64, ptr @lp_site_base, i32 %s\n") emith(" %bv = load i64, ptr %bp\n") emith(" %d = sub i64 %lv, %bv\n") emith(" %la = select i1 %mine, i64 %lv, i64 0\n") emith(" %da = select i1 %mine, i64 %d, i64 0\n") emith(" %live2 = add i64 %live, %la\n") emith(" %grew2 = add i64 %grew, %da\n") emith(" br label %snext\n") emith("snext:\n") emith(" %s1 = add i32 %s, 1\n") emith(" br label %sl\n") emith("say:\n") emith(" %any = icmp ne i64 %live, 0\n") emith(" br i1 %any, label %print, label %onext\n") emith("print:\n") emith(" %oi = sub i32 %o, 1\n") emith(" %np = getelementptr inbounds ptr, ptr @lp_owner_name, i32 %oi\n") emith(" %nm = load ptr, ptr %np\n") emith(" call i32 (ptr, ptr, ...) @fprintf(ptr %fp, ptr @.lpf_cown, ptr %nm, i64 %live, i64 %grew)\n") emith(" br label %onext\n") emith("onext:\n") emith(" %o1 = add i32 %o, 1\n") emith(" br label %ol\n") emith("done:\n") emith(" ret void\n") emith("}\n") emith("; the largest `rows` of a per-site array, largest first, to stderr (the scan's)\n") emith("define internal void @lp_franked_vals(ptr %vals, i32 %cnt, i32 %rows) {\n") emith("entry:\n") emith(" br label %pass\n") emith("pass:\n") emith(" %row = phi i32 [ 0, %entry ], [ %row1, %show ]\n") emith(" %pb = phi i64 [ 9223372036854775807, %entry ], [ %bb0, %show ]\n") emith(" %ps = phi i32 [ -1, %entry ], [ %bs0, %show ]\n") emith(" %more = icmp ult i32 %row, %rows\n") emith(" br i1 %more, label %scan, label %tail\n") emith("scan:\n") emith(" br label %loop\n") emith("loop:\n") emith(" %i = phi i32 [ 0, %scan ], [ %i1, %body ]\n") emith(" %bb0 = phi i64 [ 0, %scan ], [ %bb1, %body ]\n") emith(" %bs0 = phi i32 [ -1, %scan ], [ %bs1, %body ]\n") emith(" %go = icmp ult i32 %i, %cnt\n") emith(" br i1 %go, label %body, label %done\n") emith("body:\n") emith(" %vp = getelementptr inbounds i64, ptr %vals, i32 %i\n") emith(" %d = load i64, ptr %vp\n") emith(" %pos = icmp sgt i64 %d, 0\n") emith(" %lt = icmp slt i64 %d, %pb\n") emith(" %eqb = icmp eq i64 %d, %pb\n") emith(" %gts = icmp sgt i32 %i, %ps\n") emith(" %tie = and i1 %eqb, %gts\n") emith(" %below = or i1 %lt, %tie\n") emith(" %gtb = icmp sgt i64 %d, %bb0\n") emith(" %c1 = and i1 %pos, %below\n") emith(" %take = and i1 %c1, %gtb\n") emith(" %bb1 = select i1 %take, i64 %d, i64 %bb0\n") emith(" %bs1 = select i1 %take, i32 %i, i32 %bs0\n") emith(" %i1 = add i32 %i, 1\n") emith(" br label %loop\n") emith("done:\n") emith(" %found = icmp sge i32 %bs0, 0\n") emith(" br i1 %found, label %show, label %tail\n") emith("show:\n") emith(" call void @lp_fsite_row(ptr null, i32 2, i64 %bb0, i32 %bs0, ptr @.lpf_crow)\n") emith(" %row1 = add i32 %row, 1\n") emith(" br label %pass\n") emith("tail:\n") emith(" ret void\n") emith("}\n") emith("define internal void @lp_fsettle_locked() {\n") emith("entry:\n") emith(" %n = load i32, ptr @lp_site_n\n") emith(" %n64 = zext i32 %n to i64\n") emith(" %nb = shl i64 %n64, 3\n") emith(" call ptr @memcpy(ptr @lp_site_base, ptr @lp_site_live, i64 %nb)\n") emith(" %lv = load i64, ptr @lp_live\n") emith(" store i64 %lv, ptr @lp_slive\n") emith(" %dls = load i64, ptr @lp_dlive\n") emith(" store i64 %dls, ptr @lp_sdlive\n") emith(" call ptr @memcpy(ptr @lp_site_dbase, ptr @lp_site_dlive, i64 %nb)\n") emith(" call ptr @memcpy(ptr @lp_site_dhw, ptr @lp_site_dlive, i64 %nb)\n") emith(" call ptr @memset(ptr @lp_site_drise, i32 0, i64 %nb)\n") emith(" %pr = load i64, ptr @lp_pre\n") emith(" store i64 %pr, ptr @lp_spre\n") emith(" %jb = call i64 @lp_fnat(ptr @.lpf_jb)\n") emith(" store i64 %jb, ptr @lp_jset\n") emith(" %vb = call i64 @lp_fnat(ptr @.lpf_vb)\n") emith(" store i64 %vb, ptr @lp_vset\n") emith(" %z = call i64 @lp_fzone()\n") emith(" store i64 %z, ptr @lp_zset\n") emith(" store i8 1, ptr @lp_fj\n") emith(" ret void\n") emith("}\n") emith(";; every R3D_ALLOC_DWIN judged frames: a site whose declared bytes set a new high adds to its streak,\n") emith("; a flat window takes one off, a fall ends it; R3D_ALLOC_DRISE of them is \"declared but unbounded\",\n") emith("; said once per site (its callers were not recorded: a declared site is not judged per frame)\n") emith("define internal i64 @lp_fdwindow(i64 %f, i8 %m) {\n") emith("entry:\n") emith(" %n = load i32, ptr @lp_site_n\n") emith(" %need = load i64, ptr @lp_drise\n") emith(" %dw = load i64, ptr @lp_dwin\n") emith(" %say = icmp uge i8 %m, 3\n") emith(" br label %loop\n") emith("loop:\n") emith(" %i = phi i32 [ 0, %entry ], [ %i1, %next ]\n") emith(" %hits = phi i64 [ 0, %entry ], [ %hits1, %next ]\n") emith(" %go = icmp ult i32 %i, %n\n") emith(" br i1 %go, label %body, label %done\n") emith("body:\n") emith(" %lp = getelementptr inbounds i64, ptr @lp_site_dlive, i32 %i\n") emith(" %dl = load i64, ptr %lp\n") emith(" %hp = getelementptr inbounds i64, ptr @lp_site_dhw, i32 %i\n") emith(" %hw = load i64, ptr %hp\n") emith(" %rp = getelementptr inbounds i64, ptr @lp_site_drise, i32 %i\n") emith(" %r = load i64, ptr %rp\n") emith(" %up = icmp sgt i64 %dl, %hw\n") emith(" %fell = icmp slt i64 %dl, %hw\n") emith(" %rpos = icmp sgt i64 %r, 0\n") emith(" %rdec = sub i64 %r, 1\n") emith(" %rflat = select i1 %rpos, i64 %rdec, i64 0\n") emith(" %rup = add i64 %r, 1\n") emith(" %r0 = select i1 %fell, i64 0, i64 %rflat\n") emith(" %rn = select i1 %up, i64 %rup, i64 %r0\n") emith(" %sent = icmp slt i64 %r, 0\n") emith(" %rs = select i1 %sent, i64 %r, i64 %rn\n") emith(" store i64 %rs, ptr %rp\n") emith(" %hw1 = select i1 %up, i64 %dl, i64 %hw\n") emith(" store i64 %hw1, ptr %hp\n") emith(" %hit0 = icmp sge i64 %rs, %need\n") emith(" %hit = and i1 %hit0, %up\n") emith(" br i1 %hit, label %report, label %next0\n") emith("report:\n") emith(" store i64 -1, ptr %rp\n") emith(" %du = load i64, ptr @lp_dunb\n") emith(" %du1 = add i64 %du, 1\n") emith(" store i64 %du1, ptr @lp_dunb\n") emith(" br i1 %say, label %tell, label %next0\n") emith("tell:\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 2, ptr @.lpf_dunb, i64 %f, i64 %need, i64 %dw)\n") emith(" %bp = getelementptr inbounds i64, ptr @lp_site_dbase, i32 %i\n") emith(" %bs = load i64, ptr %bp\n") emith(" %grew = sub i64 %dl, %bs\n") emith(" call void @lp_fsite_row(ptr null, i32 2, i64 %grew, i32 %i, ptr @.lpf_crow)\n") emith(" br label %next0\n") emith("next0:\n") emith(" %got = phi i64 [ 0, %body ], [ 1, %report ], [ 1, %tell ]\n") emith(" br label %next\n") emith("next:\n") emith(" %hits1 = add i64 %hits, %got\n") emith(" %i1 = add i32 %i, 1\n") emith(" br label %loop\n") emith("done:\n") emith(" ret i64 %hits\n") emith("}\n") emith("; the frame's mark. Tracking starts at the first one (R3D_ALLOC_AUTO=0: at Mem.play() or\n") emith("; R3D_ALLOC_PLAY=); judging starts once R3D_ALLOC_WARM frames in a row kept nothing, or\n") 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") emith(" %m = load i8, ptr @lp_fm\n") emith(" %off = icmp ule i8 %m, 1\n") emith(" br i1 %off, label %tick, label %live\n") emith("live:\n") emith(" %t = load i8, ptr @lp_ft\n") emith(" %on = icmp ne i8 %t, 0\n") emith(" br i1 %on, label %tracking, label %maybe_play\n") emith("maybe_play:\n") emith(" %au = load i8, ptr @lp_fauto\n") emith(" %auq = icmp ne i8 %au, 0\n") emith(" %ap = load i64, ptr @lp_autoplay\n") emith(" %apset = icmp sge i64 %ap, 0\n") emith(" %apdue = icmp sge i64 %f1, %ap\n") emith(" %apgo = and i1 %apset, %apdue\n") emith(" %go = or i1 %auq, %apgo\n") emith(" br i1 %go, label %play, label %tick\n") emith("play:\n") emith(" call void @lp_mem_play()\n") emith(" br label %tick\n") emith("tracking:\n") emith(" call void @lp_flock()\n") emith(" %ov = load i64, ptr @lp_over\n") emith(" %ovq = icmp sgt i64 %ov, 0\n") emith(" %rep = load i8, ptr @lp_overrep\n") emith(" %repq = icmp eq i8 %rep, 0\n") emith(" %fullnew = and i1 %ovq, %repq\n") emith(" br i1 %fullnew, label %full, label %weigh\n") emith("full:\n") emith(" %tn = load i64, ptr @lp_tabn\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 2, ptr @.lpf_full, i64 %tn)\n") emith(" store i8 1, ptr @lp_overrep\n") emith(" store i8 0, ptr @lp_fj\n") emith(" br label %unlock\n") emith("weigh:\n") emith(" %lv = load i64, ptr @lp_live\n") emith(" %ml = load i64, ptr @lp_mlive\n") emith(" %pr = load i64, ptr @lp_pre\n") emith(" %mp = load i64, ptr @lp_mpre\n") emith(" %a0 = sub i64 %lv, %ml\n") emith(" %dln = load i64, ptr @lp_dlive\n") emith(" %dlmk = load i64, ptr @lp_mdlive\n") emith(" %dd = sub i64 %dln, %dlmk\n") emith(" %a = sub i64 %a0, %dd\n") emith(" %b = sub i64 %pr, %mp\n") emith(" %kept = sub i64 %a, %b\n") emith(" %bad = icmp sgt i64 %kept, 0\n") emith(" %j = load i8, ptr @lp_fj\n") emith(" %judging = icmp ne i8 %j, 0\n") emith(" br i1 %judging, label %judge, label %warming\n") emith("warming:\n") emith(" %fl = load i64, ptr @lp_flat\n") emith(" %fl1 = add i64 %fl, 1\n") emith(" %fl2 = select i1 %bad, i64 0, i64 %fl1\n") emith(" store i64 %fl2, ptr @lp_flat\n") emith(" %w = load i64, ptr @lp_warm\n") emith(" %wset = icmp sge i64 %w, 0\n") emith(" %wdone = icmp sge i64 %fl2, %w\n") emith(" %byflat = and i1 %wset, %wdone\n") emith(" %pf = load i64, ptr @lp_playf\n") emith(" %since = sub i64 %f1, %pf\n") emith(" %wm = load i64, ptr @lp_warm_max\n") emith(" %wmset = icmp sge i64 %wm, 0\n") emith(" %wmdone = icmp sge i64 %since, %wm\n") emith(" %bycap = and i1 %wmset, %wmdone\n") emith(" %settle = or i1 %byflat, %bycap\n") emith(" br i1 %settle, label %settle_now, label %mark\n") emith("settle_now:\n") emith(" call void @lp_fsettle_locked()\n") emith(" br label %mark\n") emith("judge:\n") emith(" %jd = load i64, ptr @lp_fjudged\n") emith(" %jd1 = add i64 %jd, 1\n") emith(" store i64 %jd1, ptr @lp_fjudged\n") emith(" %dw = load i64, ptr @lp_dwin\n") emith(" %dwon = icmp sgt i64 %dw, 0\n") emith(" %dws = select i1 %dwon, i64 %dw, i64 1\n") emith(" %dwr = urem i64 %jd1, %dws\n") emith(" %dwz = icmp eq i64 %dwr, 0\n") emith(" %dwdue = and i1 %dwon, %dwz\n") emith(" br i1 %dwdue, label %dwindow, label %verdict\n") emith("dwindow:\n") emith(" %nun = call i64 @lp_fdwindow(i64 %f, i8 %m)\n") emith(" %nunq = icmp sgt i64 %nun, 0\n") emith(" %dfail = icmp eq i8 %m, 4\n") emith(" %ddie = and i1 %nunq, %dfail\n") emith(" br i1 %ddie, label %die, label %verdict\n") emith("verdict:\n") emith(" br i1 %bad, label %kept_some, label %mark\n") emith("kept_some:\n") emith(" %fk = load i64, ptr @lp_fkept\n") emith(" %fk1 = add i64 %fk, %kept\n") emith(" store i64 %fk1, ptr @lp_fkept\n") emith(" %fb = load i64, ptr @lp_fbad\n") emith(" %fb1 = add i64 %fb, 1\n") emith(" store i64 %fb1, ptr @lp_fbad\n") emith(" %say = icmp uge i8 %m, 3\n") emith(" br i1 %say, label %say_it, label %mark\n") emith("say_it:\n") emith(" call void @lp_freport(i64 %f, i64 %kept)\n") emith(" %fail = icmp eq i8 %m, 4\n") emith(" br i1 %fail, label %die, label %mark\n") emith("die:\n") emith(" call i32 (i32, ptr, ...) @dprintf(i32 2, ptr @.lpf_failing)\n") emith(" store i8 0, ptr @lp_ft\n") emith(" call void @lp_funlock()\n") emith(" call void @exit(i32 86)\n") emith(" unreachable\n") emith("mark:\n") emith(" call void @lp_fmark_touched()\n") emith(" br label %unlock\n") emith("unlock:\n") emith(" call void @lp_funlock()\n") emith(" br label %tick\n") emith("tick:\n") emith(" store i64 %f1, ptr @lp_frame\n") emith(" %sa = load i64, ptr @lp_scan_at\n") emith(" %sunread = icmp eq i64 %sa, -2\n") emith(" br i1 %sunread, label %sread, label %scheck\n") emith("sread:\n") emith(" %sv = call i64 @lp_fenv(ptr @.lpf_scan, i64 -1)\n") emith(" store i64 %sv, ptr @lp_scan_at\n") emith(" br label %scheck\n") emith("scheck:\n") emith(" %sat = load i64, ptr @lp_scan_at\n") emith(" %sdue = icmp eq i64 %sat, %f1\n") emith(" br i1 %sdue, label %sdo, label %sout\n") emith("sdo:\n") emith(" call i64 @lp_mem_scan()\n") emith(" br label %sout\n") emith("sout:\n") emith(" ret void\n") emith("}\n") } 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") emith(" %p = tail call ptr @malloc(i64 %n)\n") emith(" ret ptr %p\n") emith("}\n") emith("define ptr @lp_calloc(i64 %n, i64 %s) {\n") emith("entry:\n") emith(" %p = tail call ptr @calloc(i64 %n, i64 %s)\n") emith(" ret ptr %p\n") emith("}\n") emith("define ptr @lp_realloc(ptr %o, i64 %n) {\n") emith("entry:\n") emith(" %p = tail call ptr @realloc(ptr %o, i64 %n)\n") emith(" ret ptr %p\n") emith("}\n") emith("define void @lp_free(ptr %o) {\n") emith("entry:\n") emith(" %ist = ptrtoint ptr @lp_istore to i64\n") # an interned text is the store's: never freed emith(" %ien = add i64 %ist, 4194304\n") emith(" %ix = ptrtoint ptr %o to i64\n") emith(" %ige = icmp uge i64 %ix, %ist\n") emith(" %ilt = icmp ult i64 %ix, %ien\n") emith(" %iin = and i1 %ige, %ilt\n") emith(" br i1 %iin, label %istore, label %free0\n") emith("istore:\n") emith(" ret void\n") emith("free0:\n") emith(" tail call void @free(ptr %o)\n") emith(" ret void\n") emith("}\n") emith("define void @lp_mem_play() {\n") emith("entry:\n") emith(" ret void\n") emith("}\n") emith("define void @lp_mem_settled() {\n") emith("entry:\n") emith(" ret void\n") emith("}\n") emith("define void @lp_mem_frame() {\n") emith("entry:\n") emith(" ret void\n") emith("}\n") emith("define i64 @lp_mem_kept() {\n") emith("entry:\n") emith(" ret i64 0\n") emith("}\n") emith("define i64 @lp_mem_bad_frames() {\n") emith("entry:\n") emith(" ret i64 0\n") emith("}\n") emith("define void @lp_cap_over(ptr %name, i32 %cap, i32 %len) {\n") emith("entry:\n") emith(" ret void\n") emith("}\n") emith("define i64 @lp_mem_scan() {\n") emith("entry:\n") emith(" ret i64 0\n") emith("}\n") } function emit_fence_intern() -> void { emith("@lp_itab = global [65536 x ptr] zeroinitializer\n") emith("@lp_icount = global i64 0\n") # the interned texts' bytes: one store in the binary, filled front to back and never given back, so # a text seen for the first time costs no allocation (a HUD's clock made one a minute); the heap # only past its 4 MB emith("@lp_istore = internal global [4194304 x i8] zeroinitializer\n") emith("@lp_ipos = internal global i64 0\n") # past the store or the table a text is made on the heap every time: the fence's overflow, said once emith("@lp_iover = internal global i8 0\n") emith("@.lpi_over = private unnamed_addr constant [44 x i8] c\"intern (4 MB of text, 49152 distinct texts)\\00\"\n") emith("define internal void @lp_intern_over() {\n") emith("entry:\n") emith(" %o = load i8, ptr @lp_iover\n") emith(" %said = icmp ne i8 %o, 0\n") emith(" br i1 %said, label %out, label %say\n") emith("say:\n") emith(" store i8 1, ptr @lp_iover\n") emith(" call void @lp_cap_over(ptr @.lpi_over, i32 0, i32 0)\n") emith(" br label %out\n") emith("out:\n") emith(" ret void\n") emith("}\n") emith("define internal ptr @lp_copystr(ptr %s, i64 %n) {\n") emith("entry:\n") emith(" %n1 = add i64 %n, 1\n") emith(" %pos = load i64, ptr @lp_ipos\n") emith(" %end = add i64 %pos, %n1\n") emith(" %fits = icmp ule i64 %end, 4194304\n") emith(" br i1 %fits, label %bump, label %heap\n") emith("bump:\n") emith(" %b = getelementptr inbounds [4194304 x i8], ptr @lp_istore, i64 0, i64 %pos\n") emith(" store i64 %end, ptr @lp_ipos\n") emith(" call ptr @memcpy(ptr %b, ptr %s, i64 %n1)\n") emith(" ret ptr %b\n") emith("heap:\n") emith(" call void @lp_intern_over()\n") emith(" %p = call ptr @lp_malloc(i64 %n1)\n") emith(" call ptr @memcpy(ptr %p, ptr %s, i64 %n1)\n") emith(" ret ptr %p\n") emith("}\n") emith("define ptr @lp_intern(ptr %s) {\n") emith("entry:\n") emith(" %null = icmp eq ptr %s, null\n") emith(" br i1 %null, label %none, label %hl\n") emith("none:\n") emith(" ret ptr null\n") emith("hl:\n") emith(" %i = phi i64 [ 0, %entry ], [ %i1, %hb ]\n") emith(" %h = phi i64 [ -3750763034362895579, %entry ], [ %h2, %hb ]\n") emith(" %cp = getelementptr i8, ptr %s, i64 %i\n") emith(" %c = load i8, ptr %cp\n") emith(" %end = icmp eq i8 %c, 0\n") emith(" br i1 %end, label %probe, label %hb\n") emith("hb:\n") emith(" %cz = zext i8 %c to i64\n") emith(" %h1 = xor i64 %h, %cz\n") emith(" %h2 = mul i64 %h1, 1099511628211\n") emith(" %i1 = add i64 %i, 1\n") emith(" br label %hl\n") emith("probe:\n") emith(" %k = phi i64 [ 0, %hl ], [ %k1, %next ]\n") emith(" %far = icmp uge i64 %k, 64\n") emith(" br i1 %far, label %copy_only, label %look\n") emith("look:\n") emith(" %slot0 = add i64 %h, %k\n") emith(" %slot = and i64 %slot0, 65535\n") emith(" %sp = getelementptr [65536 x ptr], ptr @lp_itab, i64 0, i64 %slot\n") emith(" %v = load ptr, ptr %sp\n") emith(" %empty = icmp eq ptr %v, null\n") emith(" br i1 %empty, label %store, label %cmp\n") emith("cmp:\n") emith(" %r = call i32 @strcmp(ptr %v, ptr %s)\n") emith(" %same = icmp eq i32 %r, 0\n") emith(" br i1 %same, label %found, label %next\n") emith("next:\n") emith(" %k1 = add i64 %k, 1\n") emith(" br label %probe\n") emith("found:\n") emith(" ret ptr %v\n") emith("store:\n") emith(" %cnt = load i64, ptr @lp_icount\n") emith(" %full = icmp uge i64 %cnt, 49152\n") emith(" br i1 %full, label %copy_only, label %keep\n") emith("keep:\n") emith(" %c2 = call ptr @lp_copystr(ptr %s, i64 %i)\n") emith(" store ptr %c2, ptr %sp\n") emith(" %cnt1 = add i64 %cnt, 1\n") emith(" store i64 %cnt1, ptr @lp_icount\n") emith(" ret ptr %c2\n") emith("copy_only:\n") emith(" call void @lp_intern_over()\n") emith(" %c3 = call ptr @lp_copystr(ptr %s, i64 %i)\n") emith(" ret ptr %c3\n") emith("}\n") }