From 1445fcb2006ea062714ff5fda03770ea94234df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 09:08:14 +0200 Subject: [PATCH 01/26] exp: Phase 0 spike crate for in-process LLVM backend Standalone (own workspace) inkwell 0.9 + LLVM 22 binary with three modes: --version clang-compatible banner, 'demo' builder-API construction of the brief's can-it-express-X list, and a clang-argv shim that compiles Perry's .ll in-process (parse -> verify -> default -> TargetMachine emit) so PERRY_LLVM_CLANG= A/Bs the backend through an unmodified perry. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- experiments/llvm-inprocess-spike/Cargo.toml | 17 + experiments/llvm-inprocess-spike/src/main.rs | 467 +++++++++++++++++++ 2 files changed, 484 insertions(+) create mode 100644 experiments/llvm-inprocess-spike/Cargo.toml create mode 100644 experiments/llvm-inprocess-spike/src/main.rs diff --git a/experiments/llvm-inprocess-spike/Cargo.toml b/experiments/llvm-inprocess-spike/Cargo.toml new file mode 100644 index 0000000000..d93456a04f --- /dev/null +++ b/experiments/llvm-inprocess-spike/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "perry-llvmc-spike" +version = "0.1.0" +edition = "2021" + +# Deliberately its own workspace: Phase 0 must not touch the Perry workspace +# build graph. Integration (Phase 1+) will add a feature-gated crate instead. +[workspace] + +[dependencies] +inkwell = { version = "0.9.0", features = ["llvm22-1"] } +# Same LLVM major as inkwell's feature; used for the handful of C-API calls +# inkwell does not wrap (LLVMSetGC, LLVMParseCommandLineOptions). +llvm-sys = "221" + +[profile.release] +opt-level = 1 diff --git a/experiments/llvm-inprocess-spike/src/main.rs b/experiments/llvm-inprocess-spike/src/main.rs new file mode 100644 index 0000000000..f138df63ae --- /dev/null +++ b/experiments/llvm-inprocess-spike/src/main.rs @@ -0,0 +1,467 @@ +//! Phase 0 feasibility spike for the in-process LLVM backend (exp/llvm-inprocess). +//! +//! Three modes: +//! +//! * `--version` — prints a clang-compatible banner, so Perry's +//! `find_clang`/`ensure_supported_clang` accept this +//! binary via `PERRY_LLVM_CLANG`. +//! * `demo ` — builds a module through the inkwell builder API +//! exercising every construct the experiment brief +//! flags as a potential blocker (NaN-box constants, +//! f64<->i64 bitcasts, inline asm with exact +//! constraint strings, module-level asm, appending +//! `@llvm.used`, `gc "statepoint-example"`), then +//! verifies, emits a .o, links it with `cc`, runs +//! it, and checks the output. +//! * `` — the shim: accepts exactly the argv Perry's +//! `build_clang_compile_plan` produces +//! (`-c -O3 -fno-math-errno [...] x.ll -o x.o +//! -target `), but compiles **in-process**: +//! parse IR -> verify -> `default` pass +//! pipeline -> TargetMachine object emission. +//! Setting `PERRY_LLVM_CLANG` to this binary swaps +//! the whole Perry compile onto the in-process +//! backend with zero Perry changes — the Phase 0 +//! A/B harness. +//! +//! Liveness proof (the "gate must assert its subject was live" rule): every +//! shim compile appends a line to `$PERRY_LLVMC_SPIKE_LOG` when set. An A/B +//! arm that claims to be in-process must show a non-empty log. + +use std::ffi::CString; +use std::path::{Path, PathBuf}; +use std::process::{Command, ExitCode}; +use std::time::Instant; + +use inkwell::context::Context; +use inkwell::memory_buffer::MemoryBuffer; +use inkwell::module::{Linkage, Module}; +use inkwell::passes::PassBuilderOptions; +use inkwell::targets::{ + CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple, +}; +use inkwell::values::AsValueRef; +use inkwell::{AddressSpace, IntPredicate, OptimizationLevel}; + +// NaN-box tags, mirrored from perry-runtime/src/value.rs. +const TAG_UNDEFINED: u64 = 0x7FFC_0000_0000_0001; +const INT32_TAG_SHIFTED: u64 = 0x7FFE_0000_0000_002A; // INT32_TAG with payload 42 + +fn main() -> ExitCode { + let args: Vec = std::env::args().skip(1).collect(); + if args.iter().any(|a| a == "--version" || a == "-v") { + print_version_banner(); + return ExitCode::SUCCESS; + } + match args.first().map(String::as_str) { + Some("demo") => { + let outdir = args + .get(1) + .map(PathBuf::from) + .unwrap_or_else(|| PathBuf::from(".")); + match run_demo(&outdir) { + Ok(()) => ExitCode::SUCCESS, + Err(e) => { + eprintln!("demo failed: {e}"); + ExitCode::FAILURE + } + } + } + Some(_) => match run_shim(&args) { + Ok(()) => ExitCode::SUCCESS, + Err(e) => { + eprintln!("perry-llvmc-spike: {e}"); + ExitCode::FAILURE + } + }, + None => { + eprintln!("usage: perry-llvmc-spike [--version | demo | ]"); + ExitCode::FAILURE + } + } +} + +fn print_version_banner() { + // `parse_clang_major_version` looks for "clang version "; report + // the LLVM major we actually embed so `ensure_supported_clang` sees a + // supported opaque-pointer toolchain. + let triple = TargetMachine::get_default_triple(); + println!( + "clang version 22.1.4 (perry-llvmc-spike in-process LLVM backend)\n\ + Target: {}\n\ + Thread model: posix\n\ + InstalledDir: (in-process)", + triple.as_str().to_string_lossy() + ); +} + +// --------------------------------------------------------------------------- +// Shim mode: clang-compatible argv, in-process compile +// --------------------------------------------------------------------------- + +struct ShimArgs { + input: PathBuf, + output: PathBuf, + opt: char, // '0', 's', '3', ... + target: Option, + mcpu_native: bool, + explicit_cpu: Option, + mllvm: Vec, +} + +fn parse_shim_args(args: &[String]) -> Result { + let mut input = None; + let mut output = None; + let mut opt = '0'; + let mut target = None; + let mut mcpu_native = false; + let mut explicit_cpu = None; + let mut mllvm = Vec::new(); + let mut it = args.iter().peekable(); + while let Some(a) = it.next() { + match a.as_str() { + "-c" | "-fno-math-errno" | "-g" => {} // -g: parity with clang — no DI metadata in Perry IR, so it adds nothing (#7144) + "-o" => output = it.next().cloned().map(PathBuf::from), + "-target" => target = it.next().cloned(), + "-mllvm" => { + if let Some(f) = it.next() { + mllvm.push(f.clone()); + } + } + s if s.starts_with("-O") => opt = s.chars().nth(2).unwrap_or('0'), + "-mcpu=native" | "-march=native" => mcpu_native = true, + s if s.starts_with("-mcpu=") => explicit_cpu = Some(s["-mcpu=".len()..].to_string()), + s if s.starts_with("-march=") => explicit_cpu = Some(s["-march=".len()..].to_string()), + s if !s.starts_with('-') => input = Some(PathBuf::from(s)), + other => return Err(format!("unrecognized clang arg: {other}")), + } + } + Ok(ShimArgs { + input: input.ok_or("missing input .ll")?, + output: output.ok_or("missing -o output")?, + opt, + target, + mcpu_native, + explicit_cpu, + mllvm, + }) +} + +fn run_shim(args: &[String]) -> Result<(), String> { + let t0 = Instant::now(); + let sa = parse_shim_args(args)?; + + // -mllvm flags (e.g. -inlinehint-threshold=N) go through the cl::opt + // parser, same effect as clang's -mllvm passthrough. Process-global, which + // is fine here (one compile per process) but is a real constraint for the + // integrated backend — noted in the write-up. + if !sa.mllvm.is_empty() { + let mut argv: Vec = vec![CString::new("perry-llvmc-spike").unwrap()]; + for f in &sa.mllvm { + argv.push(CString::new(f.as_str()).map_err(|e| e.to_string())?); + } + let ptrs: Vec<*const std::os::raw::c_char> = argv.iter().map(|c| c.as_ptr()).collect(); + unsafe { + llvm_sys::support::LLVMParseCommandLineOptions( + ptrs.len() as i32, + ptrs.as_ptr(), + std::ptr::null(), + ); + } + } + + Target::initialize_all(&InitializationConfig::default()); + let context = Context::create(); + let buf = MemoryBuffer::create_from_file(&sa.input) + .map_err(|e| format!("read {}: {}", sa.input.display(), e))?; + let ir_bytes = buf.get_size(); + let module = context + .create_module_from_ir(buf) + .map_err(|e| format!("LLVM IR parse error in {}:\n{}", sa.input.display(), e))?; + + module + .verify() + .map_err(|e| format!("verifier rejected {}:\n{}", sa.input.display(), e))?; + + let triple_str = sa + .target + .clone() + .unwrap_or_else(|| TargetMachine::get_default_triple().as_str().to_string_lossy().into_owned()); + let triple = TargetTriple::create(&triple_str); + let target = + Target::from_triple(&triple).map_err(|e| format!("no target for {triple_str}: {e}"))?; + + let (cpu, features) = if sa.mcpu_native { + ( + TargetMachine::get_host_cpu_name().to_string_lossy().into_owned(), + TargetMachine::get_host_cpu_features().to_string_lossy().into_owned(), + ) + } else if let Some(cpu) = &sa.explicit_cpu { + (cpu.clone(), String::new()) + } else { + (String::new(), String::new()) + }; + + let opt_level = match sa.opt { + '0' => OptimizationLevel::None, + '1' => OptimizationLevel::Less, + '2' | 's' | 'z' => OptimizationLevel::Default, + _ => OptimizationLevel::Aggressive, + }; + let tm = target + .create_target_machine(&triple, &cpu, &features, opt_level, RelocMode::PIC, CodeModel::Default) + .ok_or("failed to create TargetMachine")?; + + // Match clang's behavior of trusting -target over the module's own triple, + // and give the module the machine's real datalayout before optimizing. + module.set_triple(&triple); + module.set_data_layout(&tm.get_target_data().get_data_layout()); + + let pipeline = match sa.opt { + '0' => "default", + '1' => "default", + '2' => "default", + 's' => "default", + 'z' => "default", + _ => "default", + }; + module + .run_passes(pipeline, &tm, PassBuilderOptions::create()) + .map_err(|e| format!("pass pipeline {pipeline} failed: {e}"))?; + + tm.write_to_file(&module, FileType::Object, &sa.output) + .map_err(|e| format!("object emission to {} failed: {}", sa.output.display(), e))?; + + if let Ok(log) = std::env::var("PERRY_LLVMC_SPIKE_LOG") { + use std::io::Write; + if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open(&log) { + let _ = writeln!( + f, + "inprocess-compile input={} ir_bytes={} opt=-O{} cpu={} target={} ms={}", + sa.input.display(), + ir_bytes, + sa.opt, + if cpu.is_empty() { "(default)" } else { &cpu }, + triple_str, + t0.elapsed().as_millis() + ); + } + } + Ok(()) +} + +// --------------------------------------------------------------------------- +// Demo mode: builder-API construction of the brief's "can it express X" list +// --------------------------------------------------------------------------- + +fn run_demo(outdir: &Path) -> Result<(), String> { + std::fs::create_dir_all(outdir).map_err(|e| e.to_string())?; + Target::initialize_all(&InitializationConfig::default()); + + let context = Context::create(); + let module = context.create_module("spike_demo"); + let builder = context.create_builder(); + let i64t = context.i64_type(); + let f64t = context.f64_type(); + let i32t = context.i32_type(); + let ptrt = context.ptr_type(AddressSpace::default()); + + // (1) NaN-box constant fidelity: TAG_UNDEFINED as a double constant built + // from raw bits. If f64::from_bits -> const_float loses NaN payload bits, + // the whole constant-emission strategy must change; the compiled program + // prints the bits so we can check end to end. + let undef_const = f64t.const_float(f64::from_bits(TAG_UNDEFINED)); + let int42_const = f64t.const_float(f64::from_bits(INT32_TAG_SHIFTED)); + + // (2) f64 -> i64 bitcast in a function: `nanbox_bits(double) -> i64`. + let bits_fn_ty = i64t.fn_type(&[f64t.into()], false); + let bits_fn = module.add_function("nanbox_bits", bits_fn_ty, None); + { + let entry = context.append_basic_block(bits_fn, "entry"); + builder.position_at_end(entry); + let v = bits_fn.get_nth_param(0).unwrap().into_float_value(); + let as_bits = builder + .build_bit_cast(v, i64t, "bits") + .map_err(|e| e.to_string())? + .into_int_value(); + builder.build_return(Some(&as_bits)).map_err(|e| e.to_string())?; + } + + // (6) gc attribute — inkwell has no wrapper; llvm-sys expresses it. + let gc_fn = module.add_function("gc_marked", i64t.fn_type(&[i64t.into()], false), None); + unsafe { + let name = CString::new("statepoint-example").unwrap(); + llvm_sys::core::LLVMSetGC(gc_fn.as_value_ref(), name.as_ptr()); + } + { + let entry = context.append_basic_block(gc_fn, "entry"); + builder.position_at_end(entry); + let p = gc_fn.get_nth_param(0).unwrap().into_int_value(); + let one = i64t.const_int(1, false); + let r = builder.build_int_add(p, one, "r").map_err(|e| e.to_string())?; + builder.build_return(Some(&r)).map_err(|e| e.to_string())?; + } + + // (7) extern varargs declaration, same shape as Perry's runtime calls. + let printf_ty = i32t.fn_type(&[ptrt.into()], true); + let printf = module.add_function("printf", printf_ty, Some(Linkage::External)); + + // main + let main_fn = module.add_function("main", i32t.fn_type(&[], false), None); + let entry = context.append_basic_block(main_fn, "entry"); + builder.position_at_end(entry); + + // (3) the exact inline-asm barrier Perry emits: `call void asm sideeffect "", ""()`. + let void_fn_ty = context.void_type().fn_type(&[], false); + let asm = context.create_inline_asm( + void_fn_ty, + String::new(), + String::new(), + true, // sideeffect + false, // alignstack + None, // dialect + false, // can_throw + ); + builder + .build_indirect_call(void_fn_ty, asm, &[], "barrier") + .map_err(|e| e.to_string())?; + + // Format string global. + let fmt = builder + .build_global_string_ptr("tag_undefined=%llx int42=%llx gc=%lld cmp=%d\n", "fmt") + .map_err(|e| e.to_string())?; + + // Push the NaN-box constants through the bitcast fn and print their bits. + let undef_bits = builder + .build_call(bits_fn, &[undef_const.into()], "u") + .map_err(|e| e.to_string())? + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + let int42_bits = builder + .build_call(bits_fn, &[int42_const.into()], "i") + .map_err(|e| e.to_string())? + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + let gc_out = builder + .build_call(gc_fn, &[i64t.const_int(41, false).into()], "g") + .map_err(|e| e.to_string())? + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + // Tag-check pattern from generated code: (bits >> 32) == 0x7FFE ? + let hi = builder + .build_right_shift(int42_bits, i64t.const_int(32, false), false, "hi") + .map_err(|e| e.to_string())?; + let is_i32 = builder + .build_int_compare(IntPredicate::EQ, hi, i64t.const_int(0x7FFE_0000, false), "isi32") + .map_err(|e| e.to_string())?; + let is_i32_ext = builder + .build_int_z_extend(is_i32, i32t, "isi32e") + .map_err(|e| e.to_string())?; + + builder + .build_call( + printf, + &[ + fmt.as_pointer_value().into(), + undef_bits.into(), + int42_bits.into(), + gc_out.into(), + is_i32_ext.into(), + ], + "p", + ) + .map_err(|e| e.to_string())?; + builder + .build_return(Some(&i32t.const_zero())) + .map_err(|e| e.to_string())?; + + // (5) appending @llvm.used keeping gc_marked alive (the Mach-O + // no-dead-strip mechanism Perry's runtime relies on for anchors). + let used_ty = ptrt.array_type(1); + let used = module.add_global(used_ty, None, "llvm.used"); + used.set_linkage(Linkage::Appending); + used.set_section(Some("llvm.metadata")); + used.set_initializer(&ptrt.const_array(&[gc_fn.as_global_value().as_pointer_value()])); + + // (4) module-level asm defining a real symbol. + module.set_inline_assembly( + ".globl _perry_spike_asm_marker\n_perry_spike_asm_marker:\n.quad 0xC0FFEE\n", + ); + + module.verify().map_err(|e| format!("verifier: {e}"))?; + + // Debug view — printed from the real module, exactly the thesis. + let ll_path = outdir.join("spike_demo.ll"); + std::fs::write(&ll_path, module.print_to_string().to_string()).map_err(|e| e.to_string())?; + + // Optimize + emit through the same path the shim uses. + let triple = TargetMachine::get_default_triple(); + let target = Target::from_triple(&triple).map_err(|e| e.to_string())?; + let tm = target + .create_target_machine( + &triple, + &TargetMachine::get_host_cpu_name().to_string_lossy(), + &TargetMachine::get_host_cpu_features().to_string_lossy(), + OptimizationLevel::Aggressive, + RelocMode::PIC, + CodeModel::Default, + ) + .ok_or("failed to create TargetMachine")?; + module.set_data_layout(&tm.get_target_data().get_data_layout()); + module + .run_passes("default", &tm, PassBuilderOptions::create()) + .map_err(|e| format!("passes: {e}"))?; + + let obj_path = outdir.join("spike_demo.o"); + tm.write_to_file(&module, FileType::Object, &obj_path) + .map_err(|e| e.to_string())?; + + // Link + run + check. + let bin_path = outdir.join("spike_demo"); + let link = Command::new("cc") + .arg(&obj_path) + .arg("-o") + .arg(&bin_path) + .output() + .map_err(|e| e.to_string())?; + if !link.status.success() { + return Err(format!( + "link failed:\n{}", + String::from_utf8_lossy(&link.stderr) + )); + } + let run = Command::new(&bin_path).output().map_err(|e| e.to_string())?; + let stdout = String::from_utf8_lossy(&run.stdout); + println!("--- compiled program output ---\n{stdout}-------------------------------"); + + let expect_undef = format!("{:x}", TAG_UNDEFINED); + let expect_i42 = format!("{:x}", INT32_TAG_SHIFTED); + if !stdout.contains(&expect_undef) || !stdout.contains(&expect_i42) { + return Err(format!( + "NaN-box constant bits were NOT preserved: expected {expect_undef} and {expect_i42} in output" + )); + } + if !stdout.contains("gc=42") || !stdout.contains("cmp=1") { + return Err("gc-marked function or tag-check produced wrong values".into()); + } + + // The module-asm symbol must exist in the object. + let nm = Command::new("nm").arg(&obj_path).output().map_err(|e| e.to_string())?; + let nm_out = String::from_utf8_lossy(&nm.stdout); + if !nm_out.contains("_perry_spike_asm_marker") { + return Err("module-level asm symbol missing from object".into()); + } + + println!( + "demo OK: NaN-box constants preserved, inline asm + module asm + llvm.used + gc attr \ + all expressed; artifacts in {}", + outdir.display() + ); + Ok(()) +} From 2a808b933755a09ccc4c3a74a51a57d2ee85d160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 09:14:17 +0200 Subject: [PATCH 02/26] =?UTF-8?q?exp:=20Phase=200=20spike=20passes=20?= =?UTF-8?q?=E2=80=94=20demo,=20A/B=20harness,=20corpus=20batch=20script?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Demo proves NaN-box constant bit fidelity (f64::from_bits -> const_float preserves 0x7FFC000000000001 payloads end to end), inline asm, module asm, appending @llvm.used and gc attrs all expressible (LLVMSetGC via llvm-sys). Shim arm produces objects BYTE-IDENTICAL to Homebrew clang 22 on the same IR/flags; full perry compile via PERRY_LLVM_CLANG= yields output byte-identical to the text path and to pinned Node 26.5.1. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- experiments/llvm-inprocess-spike/.gitignore | 11 +++++ experiments/llvm-inprocess-spike/batch_ab.sh | 48 ++++++++++++++++++++ experiments/llvm-inprocess-spike/spike.ts | 36 +++++++++++++++ experiments/llvm-inprocess-spike/src/main.rs | 47 ++++++++++--------- 4 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 experiments/llvm-inprocess-spike/.gitignore create mode 100755 experiments/llvm-inprocess-spike/batch_ab.sh create mode 100644 experiments/llvm-inprocess-spike/spike.ts diff --git a/experiments/llvm-inprocess-spike/.gitignore b/experiments/llvm-inprocess-spike/.gitignore new file mode 100644 index 0000000000..f44b3f2c9c --- /dev/null +++ b/experiments/llvm-inprocess-spike/.gitignore @@ -0,0 +1,11 @@ +target/ +demo-out/ +*.o +*.out +*.err +*.log +spike_text +spike_inproc +spike_text.ll +spike_roundtrip.ll +roundtrip.diff diff --git a/experiments/llvm-inprocess-spike/batch_ab.sh b/experiments/llvm-inprocess-spike/batch_ab.sh new file mode 100755 index 0000000000..3acb8cd608 --- /dev/null +++ b/experiments/llvm-inprocess-spike/batch_ab.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Phase 0 corpus A/B: every 6th gap test, text backend vs in-process backend. +# For each test both arms compile with the SAME perry binary; only +# PERRY_LLVM_CLANG differs (default /usr/bin/clang vs the in-process shim). +# Divergence classes reported: SAME, DIFF (output/exit differs), CFAIL_T/CFAIL_P +# (one arm's compile failed), CFAIL_BOTH (pre-existing, not backend-related). +set -u +WT=/Users/amlug/projects/perry/wt-llvmbackend +SPIKE=$WT/experiments/llvm-inprocess-spike/target/release/perry-llvmc-spike +PERRY=$WT/target/perry-dev/perry +WORK=${1:?usage: batch_ab.sh } +mkdir -p "$WORK" +export PERRY_RUNTIME_DIR=$WT/target/perry-dev +export PERRY_NO_AUTO_OPTIMIZE=1 +export PERRY_LLVMC_SPIKE_LOG=$WORK/liveness.log +: > "$WORK/liveness.log" + +i=0 same=0 diff=0 cfail_t=0 cfail_p=0 cfail_both=0 +for t in $(ls "$WT"/test-files/test_gap_*.ts | sort); do + i=$((i+1)) + [ $((i % 6)) -ne 0 ] && continue + name=$(basename "$t" .ts) + free_gb=$(df -g /System/Volumes/Data | awk 'NR==2{print $4}') + if [ "$free_gb" -lt 6 ]; then echo "ABORT: only ${free_gb}GB free" | tee -a "$WORK/summary.txt"; exit 2; fi + + gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.t" >"$WORK/$name.t.compile" 2>&1 + ct=$? + PERRY_LLVM_CLANG=$SPIKE gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 + cp=$? + + if [ $ct -ne 0 ] && [ $cp -ne 0 ]; then cfail_both=$((cfail_both+1)); echo "CFAIL_BOTH $name" >> "$WORK/results.txt"; rm -f "$WORK/$name".[tp]; continue; fi + if [ $ct -ne 0 ]; then cfail_t=$((cfail_t+1)); echo "CFAIL_T $name" >> "$WORK/results.txt"; rm -f "$WORK/$name".[tp]; continue; fi + if [ $cp -ne 0 ]; then cfail_p=$((cfail_p+1)); echo "CFAIL_P $name" >> "$WORK/results.txt"; rm -f "$WORK/$name".[tp]; continue; fi + + gtimeout 20 "$WORK/$name.t" >"$WORK/$name.t.out" 2>"$WORK/$name.t.err"; rt=$? + gtimeout 20 "$WORK/$name.p" >"$WORK/$name.p.out" 2>"$WORK/$name.p.err"; rp=$? + if [ $rt -eq $rp ] && cmp -s "$WORK/$name.t.out" "$WORK/$name.p.out" && cmp -s "$WORK/$name.t.err" "$WORK/$name.p.err"; then + same=$((same+1)); echo "SAME $name (exit=$rt)" >> "$WORK/results.txt" + else + diff=$((diff+1)); echo "DIFF $name (exit t=$rt p=$rp)" >> "$WORK/results.txt" + fi + rm -f "$WORK/$name.t" "$WORK/$name.p" +done +compiles=$(grep -c . "$WORK/liveness.log" || true) +{ + echo "batch A/B complete: same=$same diff=$diff cfail_t=$cfail_t cfail_p=$cfail_p cfail_both=$cfail_both" + echo "in-process compiles proven live: $compiles" +} | tee "$WORK/summary.txt" diff --git a/experiments/llvm-inprocess-spike/spike.ts b/experiments/llvm-inprocess-spike/spike.ts new file mode 100644 index 0000000000..a9298842f5 --- /dev/null +++ b/experiments/llvm-inprocess-spike/spike.ts @@ -0,0 +1,36 @@ +// Phase 0 differential module: small but touches strings, arrays, closures, +// classes, Map iteration, and async — the value shapes Perry's IR leans on. +function fib(n: number): number { + return n < 2 ? n : fib(n - 1) + fib(n - 2); +} + +const arr = [3, 1, 4, 1, 5, 9, 2, 6]; +arr.sort((a, b) => a - b); +console.log("fib(20) =", fib(20)); +console.log("sorted:", arr.join(",")); + +const m = new Map(); +m.set("alpha", 1); +m.set("beta", 2); +for (const [k, v] of m) console.log(k, "->", v); + +class Point { + x: number; + y: number; + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } + norm(): number { + return Math.sqrt(this.x * this.x + this.y * this.y); + } +} +console.log("norm:", new Point(3, 4).norm()); + +const greet = (name: string) => `hello, ${name}!`; +console.log(greet("perry")); + +(async () => { + const v = await Promise.resolve(42); + console.log("async:", v); +})(); diff --git a/experiments/llvm-inprocess-spike/src/main.rs b/experiments/llvm-inprocess-spike/src/main.rs index f138df63ae..f848524699 100644 --- a/experiments/llvm-inprocess-spike/src/main.rs +++ b/experiments/llvm-inprocess-spike/src/main.rs @@ -40,9 +40,18 @@ use inkwell::passes::PassBuilderOptions; use inkwell::targets::{ CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple, }; -use inkwell::values::AsValueRef; +use inkwell::values::{AsValueRef, CallSiteValue, IntValue}; use inkwell::{AddressSpace, IntPredicate, OptimizationLevel}; +/// inkwell 0.9 returns a `ValueKind` from `try_as_basic_value`; all demo +/// callees return i64, so collapse to the IntValue or panic loudly. +fn call_ret_i64(cs: CallSiteValue<'_>) -> IntValue<'_> { + match cs.try_as_basic_value() { + inkwell::values::ValueKind::Basic(v) => v.into_int_value(), + other => panic!("call did not produce a basic value: {other:?}"), + } +} + // NaN-box tags, mirrored from perry-runtime/src/value.rs. const TAG_UNDEFINED: u64 = 0x7FFC_0000_0000_0001; const INT32_TAG_SHIFTED: u64 = 0x7FFE_0000_0000_002A; // INT32_TAG with payload 42 @@ -332,27 +341,21 @@ fn run_demo(outdir: &Path) -> Result<(), String> { .map_err(|e| e.to_string())?; // Push the NaN-box constants through the bitcast fn and print their bits. - let undef_bits = builder - .build_call(bits_fn, &[undef_const.into()], "u") - .map_err(|e| e.to_string())? - .try_as_basic_value() - .left() - .unwrap() - .into_int_value(); - let int42_bits = builder - .build_call(bits_fn, &[int42_const.into()], "i") - .map_err(|e| e.to_string())? - .try_as_basic_value() - .left() - .unwrap() - .into_int_value(); - let gc_out = builder - .build_call(gc_fn, &[i64t.const_int(41, false).into()], "g") - .map_err(|e| e.to_string())? - .try_as_basic_value() - .left() - .unwrap() - .into_int_value(); + let undef_bits = call_ret_i64( + builder + .build_call(bits_fn, &[undef_const.into()], "u") + .map_err(|e| e.to_string())?, + ); + let int42_bits = call_ret_i64( + builder + .build_call(bits_fn, &[int42_const.into()], "i") + .map_err(|e| e.to_string())?, + ); + let gc_out = call_ret_i64( + builder + .build_call(gc_fn, &[i64t.const_int(41, false).into()], "g") + .map_err(|e| e.to_string())?, + ); // Tag-check pattern from generated code: (bits >> 32) == 0x7FFE ? let hi = builder .build_right_shift(int42_bits, i64t.const_int(32, false), false, "hi") From afca6b81633414d2264960a4bf1f897ebd1783fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 09:19:27 +0200 Subject: [PATCH 03/26] exp: feature-gated in-process LLVM backend behind PERRY_LLVM_INPROCESS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New perry-codegen 'llvm-inprocess' cargo feature (inkwell 0.9 / LLVM 22, optional deps — the default build links no LLVM and is unchanged). Truthy PERRY_LLVM_INPROCESS routes compile_ll_to_object through the C API: parse from memory, verify, default pipeline, TargetMachine emission — no .ll on disk, no clang subprocess. Decisions (opt level incl. #4880 fallback, -mcpu, inlinehint) are interpreted from the same build_clang_compile_plan argv so the backends cannot drift independently. Flag joins both cache keys; a build without the feature fails loudly instead of falling back. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/Cargo.toml | 12 ++ crates/perry-codegen/src/inprocess.rs | 188 ++++++++++++++++++ crates/perry-codegen/src/lib.rs | 2 + crates/perry-codegen/src/linker.rs | 98 +++++++++ .../perry/src/commands/compile/build_cache.rs | 3 + .../src/commands/compile/object_cache.rs | 7 + .../object_cache/object_cache_tests.rs | 1 + 7 files changed, 311 insertions(+) create mode 100644 crates/perry-codegen/src/inprocess.rs diff --git a/crates/perry-codegen/Cargo.toml b/crates/perry-codegen/Cargo.toml index c3fddb40ba..5e3006bf96 100644 --- a/crates/perry-codegen/Cargo.toml +++ b/crates/perry-codegen/Cargo.toml @@ -8,6 +8,15 @@ description = "LLVM code generation backend for Perry" [lints] workspace = true +[features] +# exp/llvm-inprocess: compile `.ll -> .o` through the LLVM C API inside this +# process instead of shelling out to a user-supplied `clang -c`. Off by +# default — the default build has no LLVM link dependency and the text path +# is byte-for-byte untouched. Building with this feature requires LLVM 22 +# (`brew install llvm`; set LLVM_SYS_221_PREFIX if llvm-config is not on +# PATH). The backend still only runs when PERRY_LLVM_INPROCESS=1 at runtime. +llvm-inprocess = ["dep:inkwell", "dep:llvm-sys"] + [dependencies] perry-hir.workspace = true perry-dispatch.workspace = true @@ -18,3 +27,6 @@ thiserror.workspace = true log.workspace = true serde.workspace = true serde_json.workspace = true + +inkwell = { version = "0.9.0", features = ["llvm22-1"], optional = true } +llvm-sys = { version = "221", optional = true } diff --git a/crates/perry-codegen/src/inprocess.rs b/crates/perry-codegen/src/inprocess.rs new file mode 100644 index 0000000000..f0bd318f23 --- /dev/null +++ b/crates/perry-codegen/src/inprocess.rs @@ -0,0 +1,188 @@ +//! In-process `.ll -> .o` compilation through the LLVM C API (exp/llvm-inprocess). +//! +//! Feature-gated (`llvm-inprocess`) and flag-gated (`PERRY_LLVM_INPROCESS=1`): +//! the default build does not link LLVM, and a build that has the feature +//! still uses the `clang -c` subprocess unless the flag is set. Selection and +//! the flag's cache-key participation live in `linker.rs` / +//! `perry/src/commands/compile/{build_cache,object_cache}.rs`. +//! +//! Decision parity by construction: this module does not re-derive opt levels +//! or CPU tuning. It interprets the *same* argv `build_clang_compile_plan` +//! produces for clang (`-O3`/`-Os`/`-O0`, `-mcpu=native`, `-mllvm +//! -inlinehint-threshold=N`, `-target `), so the two backends cannot +//! drift on a decision without drifting on the plan — which the plan's own +//! tests pin. +//! +//! Measured in Phase 0 (see `docs/llvm-inprocess-experiment.md`): on the same +//! IR and flags this pipeline produces objects byte-identical to Homebrew +//! clang 22's `clang -c`. + +use std::ffi::CString; +use std::sync::Once; + +use anyhow::{anyhow, Result}; +use inkwell::context::Context; +use inkwell::memory_buffer::MemoryBuffer; +use inkwell::passes::PassBuilderOptions; +use inkwell::targets::{ + CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple, +}; +use inkwell::OptimizationLevel; + +/// One-time process-global LLVM setup: target registration and `-mllvm` +/// pass-through flags. Both are process-global in LLVM itself, which is why +/// they are applied under a `Once` and not per compile. The `-mllvm` value is +/// captured from the first compile that carries one; Perry only ever passes a +/// single, env-derived `-inlinehint-threshold` value per process, so +/// first-wins is not a narrowing. (A future per-function-opt backend must +/// replace the cl::opt mechanism entirely — noted in the experiment doc.) +static LLVM_GLOBAL_INIT: Once = Once::new(); +static ANNOUNCE: Once = Once::new(); + +fn global_init(mllvm: &[String]) { + LLVM_GLOBAL_INIT.call_once(|| { + Target::initialize_all(&InitializationConfig::default()); + if !mllvm.is_empty() { + let mut argv: Vec = vec![CString::new("perry-llvm-inprocess").unwrap()]; + for flag in mllvm { + if let Ok(c) = CString::new(flag.as_str()) { + argv.push(c); + } + } + let ptrs: Vec<*const std::os::raw::c_char> = + argv.iter().map(|c| c.as_ptr()).collect(); + unsafe { + llvm_sys::support::LLVMParseCommandLineOptions( + ptrs.len() as i32, + ptrs.as_ptr(), + std::ptr::null(), + ); + } + } + }); +} + +/// The liveness witness ("never trust a green that cannot fail"): an A/B arm +/// claiming to be in-process must show this line on stderr. +fn announce() { + ANNOUNCE.call_once(|| { + let (mut major, mut minor, mut patch) = (0u32, 0u32, 0u32); + unsafe { llvm_sys::core::LLVMGetVersion(&mut major, &mut minor, &mut patch) }; + eprintln!("perry: in-process LLVM backend active (LLVM {major}.{minor}.{patch})"); + }); +} + +/// Compile IR text to object bytes in-process, honoring the clang-style argv +/// from `build_clang_compile_plan`. `module_name` becomes the module +/// identifier (the deterministic content-addressed basename, mirroring #7131's +/// contract that only the IR bytes decide what lands in the object). +pub fn compile_ll_to_object_inprocess( + ll_text: &str, + effective_target: &str, + clang_style_args: &[String], + module_name: &str, +) -> Result> { + // Interpret the plan argv. Unknown dash-flags are an error on purpose: + // silently ignoring a flag clang would have honored is how the two + // backends drift apart without anyone noticing. + let mut opt = '0'; + let mut mcpu_native = false; + let mut explicit_cpu: Option<&str> = None; + let mut mllvm: Vec = Vec::new(); + let mut it = clang_style_args.iter().peekable(); + while let Some(a) = it.next() { + match a.as_str() { + // `-g` is a measured no-op on Perry IR (no DI metadata; see the + // TEMP_NONCE_COUNTER doc block in linker.rs), matching clang. + "-c" | "-fno-math-errno" | "-g" => {} + "-o" | "-target" => { + it.next(); + } + "-mllvm" => { + if let Some(f) = it.next() { + mllvm.push(f.clone()); + } + } + "-mcpu=native" | "-march=native" => mcpu_native = true, + s if s.starts_with("-mcpu=") => explicit_cpu = Some(&s["-mcpu=".len()..]), + s if s.starts_with("-march=") => explicit_cpu = Some(&s["-march=".len()..]), + s if s.starts_with("-O") => opt = s.chars().nth(2).unwrap_or('0'), + s if !s.starts_with('-') => {} // input/output paths from the plan + other => { + return Err(anyhow!( + "in-process backend does not understand clang arg `{other}`; \ + refusing to silently drop it" + )) + } + } + } + + global_init(&mllvm); + announce(); + + let context = Context::create(); + let buf = MemoryBuffer::create_from_memory_range_copy(ll_text.as_bytes(), module_name); + let module = context + .create_module_from_ir(buf) + .map_err(|e| anyhow!("LLVM IR parse error:\n{}", e.to_string()))?; + module + .verify() + .map_err(|e| anyhow!("LLVM verifier rejected module:\n{}", e.to_string()))?; + + let triple = TargetTriple::create(effective_target); + let target = Target::from_triple(&triple) + .map_err(|e| anyhow!("no LLVM target for `{effective_target}`: {e}"))?; + let (cpu, features) = if mcpu_native { + ( + TargetMachine::get_host_cpu_name() + .to_string_lossy() + .into_owned(), + TargetMachine::get_host_cpu_features() + .to_string_lossy() + .into_owned(), + ) + } else if let Some(cpu) = explicit_cpu { + (cpu.to_string(), String::new()) + } else { + (String::new(), String::new()) + }; + let opt_level = match opt { + '0' => OptimizationLevel::None, + '1' => OptimizationLevel::Less, + '2' | 's' | 'z' => OptimizationLevel::Default, + _ => OptimizationLevel::Aggressive, + }; + let tm = target + .create_target_machine( + &triple, + &cpu, + &features, + opt_level, + RelocMode::PIC, + CodeModel::Default, + ) + .ok_or_else(|| anyhow!("failed to create TargetMachine for `{effective_target}`"))?; + + // Same trust order as the subprocess path: `-target` wins over whatever + // triple the module text states, and the module optimizes under the + // machine's real datalayout. + module.set_triple(&triple); + module.set_data_layout(&tm.get_target_data().get_data_layout()); + + let pipeline = match opt { + '0' => "default", + '1' => "default", + '2' => "default", + 's' => "default", + 'z' => "default", + _ => "default", + }; + module + .run_passes(pipeline, &tm, PassBuilderOptions::create()) + .map_err(|e| anyhow!("pass pipeline `{pipeline}` failed:\n{}", e.to_string()))?; + + let obj = tm + .write_to_memory_buffer(&module, FileType::Object) + .map_err(|e| anyhow!("object emission failed:\n{}", e.to_string()))?; + Ok(obj.as_slice().to_vec()) +} diff --git a/crates/perry-codegen/src/lib.rs b/crates/perry-codegen/src/lib.rs index 6d87dde4fe..dd5ec5cf80 100644 --- a/crates/perry-codegen/src/lib.rs +++ b/crates/perry-codegen/src/lib.rs @@ -11,6 +11,8 @@ pub(crate) mod collectors; pub mod expr; pub mod ext_registry; pub mod function; +#[cfg(feature = "llvm-inprocess")] +pub mod inprocess; pub mod linker; pub(crate) mod loop_purity; pub(crate) mod lower_array_method; diff --git a/crates/perry-codegen/src/linker.rs b/crates/perry-codegen/src/linker.rs index ef12529cc2..09d6966ae3 100644 --- a/crates/perry-codegen/src/linker.rs +++ b/crates/perry-codegen/src/linker.rs @@ -482,12 +482,110 @@ pub fn compile_ll_to_object(ll_text: &str, target_triple: Option<&str>) -> Resul /// * **`PERRY_DEBUG_SYMBOLS`**: no effect on any of the above. It was believed /// to put the `.ll`'s absolute path into DWARF; measured, it does not put /// anything there at all. See `TEMP_NONCE_COUNTER`. +/// exp/llvm-inprocess: truthy `PERRY_LLVM_INPROCESS` routes `.ll -> .o` +/// through the LLVM C API inside this process (no clang subprocess, no `.ll` +/// on disk). The flag participates in both the build cache and the object +/// cache keys, so the two backends can never share a cached object. +fn inprocess_requested() -> bool { + match env::var("PERRY_LLVM_INPROCESS").as_deref() { + Ok("") | Ok("0") | Ok("off") | Ok("false") | Err(_) => false, + Ok(_) => true, + } +} + +#[cfg(feature = "llvm-inprocess")] +fn compile_ll_inprocess_in( + tmp_dir: &Path, + ll_text: &str, + target_triple: Option<&str>, + policy: TempFilePolicy, +) -> Result> { + let (paths, _pid, _nonce) = llvm_temp_paths(tmp_dir, ll_text); + // Same decision inputs as the clang path — opt level (#4880 fallback + // included), CPU tuning, inlinehint threshold — via the same plan + // constructor, so the backends cannot drift on a decision independently. + let plan = build_clang_compile_plan( + PathBuf::from("(in-process)"), + paths.ll_path.clone(), + paths.obj_path.clone(), + target_triple, + ll_text.len(), + count_ll_functions(ll_text), + policy.debug_symbols, + ); + // #7131 parity: the module identifier is the content-addressed basename, + // the only name that can reach the object bytes. + let module_name = paths + .ll_path + .file_name() + .map(|n| n.to_string_lossy().into_owned()) + .unwrap_or_else(|| "perry_module.ll".to_string()); + if policy.keep { + fs::create_dir_all(&paths.scratch_dir) + .with_context(|| format!("Failed to create {}", paths.scratch_dir.display()))?; + fs::write(&paths.ll_path, ll_text) + .with_context(|| format!("Failed to write {}", paths.ll_path.display()))?; + let metadata_path = PathBuf::from(format!("{}.compile-plan.json", plan.obj_path.display())); + write_compile_plan_metadata(&plan, &metadata_path)?; + eprintln!("[perry-codegen] kept LLVM IR: {}", paths.ll_path.display()); + eprintln!( + "[perry-codegen] kept compile metadata: {}", + metadata_path.display() + ); + } + match crate::inprocess::compile_ll_to_object_inprocess( + ll_text, + &plan.effective_target, + &plan.clang_args, + &module_name, + ) { + Ok(bytes) => Ok(bytes), + Err(e) => { + // Same contract as a failed clang compile: the IR that produced + // the failure is left on disk and named in the error. + let _ = fs::create_dir_all(&paths.scratch_dir); + let _ = fs::write(&paths.ll_path, ll_text); + Err(anyhow!( + "in-process LLVM compile failed (PERRY_LLVM_INPROCESS).\n\ + requested -target: {}\n\ + LLVM IR left at: {}\n\ + \n\ + {}", + plan.effective_target, + paths.ll_path.display(), + e + )) + } + } +} + +#[cfg(not(feature = "llvm-inprocess"))] +fn compile_ll_inprocess_in( + _tmp_dir: &Path, + _ll_text: &str, + _target_triple: Option<&str>, + _policy: TempFilePolicy, +) -> Result> { + // Fail loudly rather than silently falling back: an A/B arm that asked + // for the in-process backend must never be served the text path. + bail!( + "PERRY_LLVM_INPROCESS is set, but this perry was built without the \ + `llvm-inprocess` cargo feature. Rebuild with \ + `cargo build -p perry --features llvm-inprocess` (needs LLVM 22: \ + `brew install llvm`, and LLVM_SYS_221_PREFIX if llvm-config is not \ + on PATH), or unset PERRY_LLVM_INPROCESS." + ) +} + fn compile_ll_to_object_in( tmp_dir: &Path, ll_text: &str, target_triple: Option<&str>, policy: TempFilePolicy, ) -> Result> { + if inprocess_requested() { + return compile_ll_inprocess_in(tmp_dir, ll_text, target_triple, policy); + } // Validate the toolchain before creating the potentially large `.ll` // scratch file. Unsupported clang releases should fail without leaving // an artifact that was never passed to the compiler. diff --git a/crates/perry/src/commands/compile/build_cache.rs b/crates/perry/src/commands/compile/build_cache.rs index d31651a752..d40c6e259c 100644 --- a/crates/perry/src/commands/compile/build_cache.rs +++ b/crates/perry/src/commands/compile/build_cache.rs @@ -33,6 +33,9 @@ const BUILD_CACHE_ENV_VARS: &[&str] = &[ "PERRY_DEBUG_INIT", "PERRY_DEBUG_SYMBOLS", "PERRY_LLVM_CLANG", + // exp/llvm-inprocess: selects the in-process LLVM backend for .ll -> .o; + // a different backend means different object bytes. + "PERRY_LLVM_INPROCESS", "PERRY_WRITE_BARRIERS", "PERRY_SHADOW_STACK", "PERRY_INLINE_SHADOW_SLOT", diff --git a/crates/perry/src/commands/compile/object_cache.rs b/crates/perry/src/commands/compile/object_cache.rs index 2194ce4fbb..1c333afd95 100644 --- a/crates/perry/src/commands/compile/object_cache.rs +++ b/crates/perry/src/commands/compile/object_cache.rs @@ -786,6 +786,13 @@ fn compute_object_cache_key_with_env( "env_llvm_clang", env_var("PERRY_LLVM_CLANG").as_deref().unwrap_or(""), ); + // exp/llvm-inprocess: the in-process backend emits with its own pinned + // LLVM; sharing objects with the clang subprocess path would make every + // A/B between the backends vacuous. + h.field( + "env_llvm_inprocess", + env_var("PERRY_LLVM_INPROCESS").as_deref().unwrap_or(""), + ); h.field( "env_write_barriers", env_var("PERRY_WRITE_BARRIERS").as_deref().unwrap_or(""), diff --git a/crates/perry/src/commands/compile/object_cache/object_cache_tests.rs b/crates/perry/src/commands/compile/object_cache/object_cache_tests.rs index f8320f7af5..d36aa631fa 100644 --- a/crates/perry/src/commands/compile/object_cache/object_cache_tests.rs +++ b/crates/perry/src/commands/compile/object_cache/object_cache_tests.rs @@ -581,6 +581,7 @@ fn key_changes_with_codegen_env_vars() { "PERRY_DEBUG_INIT", "PERRY_DEBUG_SYMBOLS", "PERRY_LLVM_CLANG", + "PERRY_LLVM_INPROCESS", "PERRY_WRITE_BARRIERS", "PERRY_SHADOW_STACK", "PERRY_DISABLE_BUFFER_FAST_PATH", From 28f0821a11c7d062e5769f5667434b832b81770b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 09:32:40 +0200 Subject: [PATCH 04/26] exp: validate integrated backend; write up the experiment Integrated flag validated one-binary: liveness line, byte-identical program output, node-oracle match, distinct object-cache keys observed. 26-test corpus slice through PERRY_LLVM_INPROCESS=1: 25/26 byte-identical, 26/26 proven live, the 1 diff is the pre-existing perry-ext-http panic family (thread-id-only delta, reproduced arm-vs-itself). Featureless build fails loudly under the flag and is untouched without it. inkwell 0.9 NUL-buffer requirement fixed; fmt applied; perry-codegen 526 + perry 881 tests pass. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- Cargo.lock | 46 ++++ crates/perry-codegen/src/inprocess.rs | 10 +- crates/perry/Cargo.toml | 6 + docs/llvm-inprocess-experiment.md | 247 +++++++++++++++++++ experiments/llvm-inprocess-spike/Cargo.lock | 173 +++++++++++++ experiments/llvm-inprocess-spike/batch_ab.sh | 29 ++- 6 files changed, 503 insertions(+), 8 deletions(-) create mode 100644 docs/llvm-inprocess-experiment.md create mode 100644 experiments/llvm-inprocess-spike/Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index 31e951a4bd..0b2bdd6537 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3882,6 +3882,30 @@ dependencies = [ "web-time", ] +[[package]] +name = "inkwell" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7decbc9dfa45a4a827a6ff7b822c113b1285678a937e84213417d4ca8a095782" +dependencies = [ + "bitflags 2.12.1", + "inkwell_internals", + "libc", + "llvm-sys", + "thiserror 2.0.18", +] + +[[package]] +name = "inkwell_internals" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cfe97ee860815a90ed17e09639513269e39420a7440f3f4c996f238c514cf8d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "inotify" version = "0.9.6" @@ -4428,6 +4452,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +[[package]] +name = "llvm-sys" +version = "221.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2abcc34a3b190f03c2a61b555f218f529589ff13657bdd2ff8ac3e85f2abe6bb" +dependencies = [ + "anyhow", + "cc", + "lazy_static", + "libc", + "regex-lite", + "semver", +] + [[package]] name = "lock_api" version = "0.4.14" @@ -5581,6 +5619,8 @@ name = "perry-codegen" version = "0.5.1279" dependencies = [ "anyhow", + "inkwell", + "llvm-sys", "log", "perry-api-manifest", "perry-dispatch", @@ -7336,6 +7376,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-lite" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" + [[package]] name = "regex-syntax" version = "0.8.11" diff --git a/crates/perry-codegen/src/inprocess.rs b/crates/perry-codegen/src/inprocess.rs index f0bd318f23..3b1b068394 100644 --- a/crates/perry-codegen/src/inprocess.rs +++ b/crates/perry-codegen/src/inprocess.rs @@ -49,8 +49,7 @@ fn global_init(mllvm: &[String]) { argv.push(c); } } - let ptrs: Vec<*const std::os::raw::c_char> = - argv.iter().map(|c| c.as_ptr()).collect(); + let ptrs: Vec<*const std::os::raw::c_char> = argv.iter().map(|c| c.as_ptr()).collect(); unsafe { llvm_sys::support::LLVMParseCommandLineOptions( ptrs.len() as i32, @@ -121,7 +120,12 @@ pub fn compile_ll_to_object_inprocess( announce(); let context = Context::create(); - let buf = MemoryBuffer::create_from_memory_range_copy(ll_text.as_bytes(), module_name); + // inkwell 0.9's copy constructor requires (and then strips) a trailing + // NUL. One extra copy of the IR text; fine for the transport phase. + let mut ir = Vec::with_capacity(ll_text.len() + 1); + ir.extend_from_slice(ll_text.as_bytes()); + ir.push(0); + let buf = MemoryBuffer::create_from_memory_range_copy(&ir, module_name); let module = context .create_module_from_ir(buf) .map_err(|e| anyhow!("LLVM IR parse error:\n{}", e.to_string()))?; diff --git a/crates/perry/Cargo.toml b/crates/perry/Cargo.toml index 3775f589b5..161f9457d1 100644 --- a/crates/perry/Cargo.toml +++ b/crates/perry/Cargo.toml @@ -140,6 +140,12 @@ audit-cli = [] updater-cli = ["dep:ed25519-dalek", "dep:rand"] native-cli = [] +# exp/llvm-inprocess: compile .ll -> .o through the LLVM C API in-process +# instead of a `clang -c` subprocess. Off by default (no LLVM link dependency); +# even when built in, it only runs under PERRY_LLVM_INPROCESS=1. Requires +# LLVM 22 at build time (LLVM_SYS_221_PREFIX or llvm-config on PATH). +llvm-inprocess = ["perry-codegen/llvm-inprocess"] + # Codegen backends for non-native targets. Each enables one backend crate; # `all-codegen-backends` (in full-cli) turns them all on so the default build is # unchanged. A slim CLI without a backend rejects its `--target` with a clear diff --git a/docs/llvm-inprocess-experiment.md b/docs/llvm-inprocess-experiment.md new file mode 100644 index 0000000000..c2751ba636 --- /dev/null +++ b/docs/llvm-inprocess-experiment.md @@ -0,0 +1,247 @@ +# In-process LLVM backend experiment (`exp/llvm-inprocess`) + +**Status: Phase 0 complete — feasibility CONFIRMED, with a byte-identical +parity result.** A feature-gated, flag-gated in-process transport +(`PERRY_LLVM_INPROCESS=1`) is implemented on this branch. The default path is +untouched: the default build links no LLVM and compiles `.ll` through +`clang -c` exactly as before. + +Companion artifacts: + +- `experiments/llvm-inprocess-spike/` — the Phase 0 spike binary (see below). +- `crates/perry-codegen/src/inprocess.rs` — the integrated backend + (`llvm-inprocess` cargo feature). +- Tracking issue: filed on PerryTS/perry with the Phase 0 answers. + +## Thesis (from the experiment brief) + +Perry builds LLVM IR as strings, writes a `.ll`, and shells out to a +user-supplied `clang -c`. That is an LLVM dependency that is *runtime, +unpinned, and owned by the user's machine*: 1,376 MB of transient IR text on +the Claude Code bundle, the #4880 whole-module `-Os` demotion, Apple clang 21 +unable to parse LLVM 22 attribute output, and errors reported as line numbers +in gigabyte files. The experiment: own the pipeline via the LLVM C API, make +textual `.ll` a debug view instead of the transport. + +## Phase 0 answers (the questions the brief required) + +**Which crate?** `inkwell 0.9.0` (safe wrapper) with `llvm-sys 221` alongside +for the C-API calls inkwell does not wrap. inkwell's typed builder API held up +for real construction work, and its `Context::create_module_from_ir` + +`run_passes` + `write_to_memory_buffer` cover the whole transport path with no +disk I/O. Raw `llvm-sys` alone would also work but buys nothing at this stage; +the escape hatch composes cleanly (`AsValueRef`), so this is not an +either/or. + +**Which LLVM version?** 22 (`llvm22-1` feature / `llvm-sys 221.0.1`), matching +Homebrew's current `llvm` formula (22.1.4 on the dev box). Choosing 22 rather +than 20 *eliminates* the version-skew problem from the brief: the +statepoint/RS4GC work needs LLVM 22 output that Apple clang 21 cannot parse — +in-process, there is no parse and no second toolchain. inkwell 0.9 supports +llvm11-0 through llvm22-1, so pinning back is trivial if needed. + +**How is it discovered at build time?** `llvm-sys` reads +`LLVM_SYS_221_PREFIX` (or falls back to `llvm-config` on `PATH`). The build on +this branch was done with `LLVM_SYS_221_PREFIX=/opt/homebrew/opt/llvm`. + +**What must a contributor install?** Nothing new, by default. The +`llvm-inprocess` feature is off; the default build has zero LLVM link +dependency and byte-identical behavior. A contributor who wants the in-process +backend needs `brew install llvm` (macOS) / LLVM 22 dev packages (Linux) and +the env var above. Static-link cost is real (see the binary-size row) and is a +distribution decision to make only if this graduates. + +**Could the bindings express what Perry needs?** Yes — everything on the +brief's worry list, verified by construction in the spike's `demo` mode: + +| Construct | Result | +|---|---| +| NaN-box constants (`0x7FFC_0000_0000_0001` payloads in `double`) | `f64::from_bits` → `const_float` preserved bit patterns exactly, verified end-to-end by running the compiled artifact | +| `f64` ↔ `i64` bitcasts, tag-check ladders | plain `build_bit_cast` / icmp; no friction | +| Inline asm with exact constraint strings (`call void asm sideeffect "", ""()` — Perry's loop barrier) | `context.create_inline_asm` + `build_indirect_call` | +| Module-level asm | `module.set_inline_assembly` (symbol verified present in the emitted object) | +| Appending globals / `@llvm.used` (the Mach-O no-dead-strip mechanism) | `Linkage::Appending` + `llvm.metadata` section | +| `gc "statepoint-example"` function attribute | not wrapped by inkwell — one-line `llvm_sys::core::LLVMSetGC` via `AsValueRef` | +| `-mllvm -inlinehint-threshold=N` passthrough | not a C-API option — `LLVMParseCommandLineOptions` (process-global; see Constraints) | +| Varargs extern declarations (runtime helper calls) | `fn_type(..., true)` | + +Notably, `main`'s generated IR needs *less* than the brief feared: no +`llvm.used`, no module asm, no statepoints today (those live on +`exp/stackmap-viability`). The empty-constraint asm barrier is the only asm. + +## What was built + +### 1. Spike binary (`experiments/llvm-inprocess-spike/`, standalone workspace) + +- `demo` mode: builds the table above through the builder API, verifies, runs + `default`, emits a `.o`, links with `cc`, executes, and checks the + program's own output (including the NaN-box bit patterns). +- **clang-shim mode**: accepts the exact argv Perry's + `build_clang_compile_plan` produces and compiles in-process. Because both + Perry caches already key on `PERRY_LLVM_CLANG`, pointing that variable at + the shim A/Bs the whole backend through an **unmodified perry** with no + possibility of cross-arm cache reuse. Liveness is proven by a per-compile + log (`PERRY_LLVMC_SPIKE_LOG`), not inferred from the absence of errors. + +### 2. Integrated transport backend (`llvm-inprocess` feature) + +`compile_ll_to_object` in `perry-codegen/src/linker.rs` — whose own doc +header has always called it "the seam" — gets a second implementation: +parse-from-memory → verify → `default` → `TargetMachine` +object-to-memory. No `.ll` touches disk (KEEP_IR and on-failure debugging +still write one). Decision parity is by construction: the in-process path +interprets the *same* plan argv the clang path builds (`-O3`/`-Os`/`-O0` +incl. the #4880 oversized fallback, `-mcpu=native`, inlinehint), so the +backends cannot drift on a decision without the plan's own tests catching it. +Unknown flags are a hard error, never silently dropped. `PERRY_LLVM_INPROCESS` +joins both the build-cache and object-cache keys (vacuous-A/B defense), a +build without the feature **fails loudly** if the flag is set, and the first +in-process compile prints a liveness witness: +`perry: in-process LLVM backend active (LLVM 22.1.4)`. + +## Differential parity results + +**Object-level:** on the same 245 KB Perry module with identical flags, the +in-process pipeline produced an object **byte-identical** to Homebrew +`clang -c` (LLVM 22). Apple clang 21's object differs (8562 vs 8554 bytes of +`__text`) — that is precisely the cross-version skew the in-process backend +removes from user machines. + +**Corpus A/B (through unmodified perry, via the shim):** every 6th gap test, +77 tests, both arms compiled by the same perry binary and same runtime `.a`: + +- 76/77: stdout, stderr, and exit status byte-identical. +- 1/77 (`test_gap_http_res_socket_writable_onfinished`): both arms SIGABRT + with the same pre-existing `perry-ext-http` panic; the only stderr delta is + the OS thread id, which also differs between two runs of the *same* arm. + Not backend-attributable. +- 0 compile failures on either arm; 82 in-process compiles proven live via + the log. + +**Corpus A/B (integrated backend, one binary, flag-gated):** a different +26-test slice (stride 18, offset 3) through the same perry built with the +feature, `PERRY_LLVM_INPROCESS=1` as the only arm difference: 25/26 +byte-identical; 26/26 compiles carried the liveness line (the harness fails +any arm that compiled without announcing); the 1 DIFF is the same +pre-existing `perry-ext-http` panic family, delta = OS thread id only. + +**Single-module end-to-end:** `spike.ts` output byte-identical across +text arm, in-process arm (both shim and integrated), and the pinned Node +oracle (26.5.1). A featureless build with `PERRY_LLVM_INPROCESS=1` fails +loudly with a rebuild hint rather than silently serving the text path +(verified), and the featureless build's normal path is unaffected +(verified). + +**Textual round-trip (`.ll` → parse → print):** classes of difference, each +mechanical: explicit default alignment (`alloca i64` → `alloca i64, align 8`), +attribute-group renumbering (`#2` → `#0`), float formatting (`0.0` → +`0.000000e+00`; NaN-box hex doubles print identically), `ModuleID`/ +`source_filename` headers, empty-metadata placement. Zero semantic diffs. +This is the normalization catalogue a Phase 2 construction-parity harness +must account for. + +**`-fno-math-errno`:** the C API has no equivalent knob, so it was measured +instead of assumed: on macOS/arm64 the flag produces a byte-identical object +on Perry IR (Darwin already defaults to errno-free math). **Re-measure on +Linux before trusting the in-process backend there** — glibc targets default +the other way. + +## Measurements (honest scope) + +Environment caveats, stated up front: dev box under heavy load (loadavg +29–50 from concurrent builds — every number below is *indicative only*), +perry built at `perry-dev` profile, spike at `opt-level=1`. Nothing here is a +quotable benchmark; the quotable run needs a quiet box and the big corpus. + +| Metric | Text path (clang subprocess) | In-process | Note | +|---|---|---|---| +| 245 KB module, `-O3` avg of 5 | Apple 21: 123 ms · Brew 22: 147 ms | 171 ms | subprocess spawn is **not** the bottleneck at this scale | +| 421 KB module (`batch.ts` kernel), avg of 3 | Apple 21: 241 ms | 434 ms | same conclusion; O3 dominates | +| Transient IR on disk | full module text per compile | **0 bytes** (memory buffer both directions) | eliminated by construction | +| Object bytes vs same-version clang | — | **byte-identical** | strongest possible parity | +| Error reporting | text positions in the temp file | verifier/parse errors from the live module | construction-site errors need Phase 2 | +| `perry` binary (perry-dev) | 53 MB | 224 MB with static LLVM 22 feature build | distribution cost if ever default | + +The compile-time *win* thesis was **not** demonstrated at small scale — and +that is a real Phase 0 result: the payoffs that justified the experiment live +at the 1.4 GB-of-IR scale (parse + disk transit), in version control, and in +what the seam unlocks (per-function opt levels instead of #4880's +whole-module demotion, DWARF via `DIBuilder`, in-process RS4GC). Those are +Phase 2/3 measurements, gated on a quiet box, ≥25 GB free disk, and the gap +suite green under the flag. + +## The seam finding (differs from the brief's assumption) + +The brief's Phase 1 places the seam "between lowering and IR construction" +with two builder implementations. The codebase disagrees: perry-codegen is +~340k lines of *string-oriented* emission (`LlModule` holds functions as +rendered text lines), so an instruction-level builder interface is not a +seam, it is a rewrite of the whole emitter. The seam this codebase already +has — and documents as such — is `compile_ll_to_object(ll_text) -> Vec`. +Swapping the transport there delivers the operational wins now (no +subprocess, no version skew, no disk transit, pinned LLVM, exact-version +`opt`-less RS4GC scheduling for #7174) at ~250 lines, byte-identical-proven. +The construction-level seam remains the right *eventual* target — it is what +kills the string-building CPU/RSS at scale and enables `DIBuilder` — but it +should be motivated by a measured profile of string-build cost, taken through +this transport, not assumed. + +## Constraints and open risks + +- **`cl::opt` state is process-global** (`LLVMParseCommandLineOptions`). + Fine today (one env-derived value per process, applied under `Once`), but a + per-function-opt future must use per-pipeline mechanisms instead. +- **Parallelism**: one `Context` per rayon worker compile (LLVM contexts are + not thread-safe; separate contexts on separate threads are). This mirrors + the parallel `clang -c` model, so peak-RSS behavior needs measuring at + scale — a subprocess returns its memory to the OS at exit, an in-process + context returns it to the allocator. +- **bindings lag**: llvm-sys tracked LLVM 22 within the release cycle + (221.0.1 published; inkwell 0.9 already has `llvm22-1`), but a future LLVM + bump waits on both crates. The subprocess path has the inverse problem + (whatever clang the user has). Pinning wins, but it is a pin *we* must + maintain. +- **Windows / cross targets**: untested. `Target::initialize_all` registers + everything, and `-target` handling mirrors the clang path, but COFF and the + MSVC/MinGW distinction (see `probe_clang_default_triple`) need their own + A/B before any claim. +- **`-fno-math-errno` on Linux**: measure before enabling there (see above). + +## Recommendation, with its price + +**Adopt the transport seam** (this branch's `llvm-inprocess` feature) as the +vehicle for the remaining phases; keep it opt-in until the gap suite has run +green under `PERRY_LLVM_INPROCESS=1` on macOS *and* Linux and the Claude +Code bundle has been compiled through it with the measurement table filled on +a quiet box. Price: LLVM 22 as a build-time dependency *for those who enable +it* (+171 MB on a perry-dev binary with static linking; dynamic linking +against `libLLVM.dylib` is the dev-loop alternative), llvm-sys/inkwell as +maintained pins, and the process-global constraints above. Do **not** start +the instruction-level builder until the string-build cost has been profiled +through this transport at bundle scale — if parse+build turns out to be a +minor fraction of `default` even at 1.4 GB, the rewrite's payoff is +DIBuilder and error locality only, and that should be decided with the number +on the table. + +## Reproducing + +```bash +# Spike (standalone, no Perry workspace impact) +cd experiments/llvm-inprocess-spike +LLVM_SYS_221_PREFIX=/opt/homebrew/opt/llvm cargo build --release +./target/release/perry-llvmc-spike demo demo-out + +# A/B through unmodified perry (shim as PERRY_LLVM_CLANG) +PERRY_LLVM_CLANG=$PWD/target/release/perry-llvmc-spike \ +PERRY_LLVMC_SPIKE_LOG=/tmp/live.log \ + perry spike.ts -o spike_inproc + +# Integrated backend (one binary, flag-gated A/B) +LLVM_SYS_221_PREFIX=/opt/homebrew/opt/llvm \ + cargo build --profile perry-dev -p perry -p perry-runtime-static \ + -p perry-stdlib-static --features perry/llvm-inprocess +PERRY_LLVM_INPROCESS=1 perry file.ts -o out # stderr must show the liveness line + +# Corpus A/B +experiments/llvm-inprocess-spike/batch_ab.sh /tmp/batch-ab +``` diff --git a/experiments/llvm-inprocess-spike/Cargo.lock b/experiments/llvm-inprocess-spike/Cargo.lock new file mode 100644 index 0000000000..a6ea3bb4d4 --- /dev/null +++ b/experiments/llvm-inprocess-spike/Cargo.lock @@ -0,0 +1,173 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" + +[[package]] +name = "cc" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "inkwell" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7decbc9dfa45a4a827a6ff7b822c113b1285678a937e84213417d4ca8a095782" +dependencies = [ + "bitflags", + "inkwell_internals", + "libc", + "llvm-sys", + "thiserror", +] + +[[package]] +name = "inkwell_internals" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cfe97ee860815a90ed17e09639513269e39420a7440f3f4c996f238c514cf8d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "llvm-sys" +version = "221.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2abcc34a3b190f03c2a61b555f218f529589ff13657bdd2ff8ac3e85f2abe6bb" +dependencies = [ + "anyhow", + "cc", + "lazy_static", + "libc", + "regex-lite", + "semver", +] + +[[package]] +name = "perry-llvmc-spike" +version = "0.1.0" +dependencies = [ + "inkwell", + "llvm-sys", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex-lite" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" diff --git a/experiments/llvm-inprocess-spike/batch_ab.sh b/experiments/llvm-inprocess-spike/batch_ab.sh index 3acb8cd608..5e6e231843 100755 --- a/experiments/llvm-inprocess-spike/batch_ab.sh +++ b/experiments/llvm-inprocess-spike/batch_ab.sh @@ -8,7 +8,13 @@ set -u WT=/Users/amlug/projects/perry/wt-llvmbackend SPIKE=$WT/experiments/llvm-inprocess-spike/target/release/perry-llvmc-spike PERRY=$WT/target/perry-dev/perry -WORK=${1:?usage: batch_ab.sh } +WORK=${1:?usage: batch_ab.sh [shim|flag] [stride] [offset]} +# Arm P mechanism: "shim" = PERRY_LLVM_CLANG= through an +# unmodified perry; "flag" = PERRY_LLVM_INPROCESS=1 through a perry built +# with the llvm-inprocess feature. +MODE=${2:-shim} +STRIDE=${3:-6} +OFFSET=${4:-0} mkdir -p "$WORK" export PERRY_RUNTIME_DIR=$WT/target/perry-dev export PERRY_NO_AUTO_OPTIMIZE=1 @@ -18,15 +24,24 @@ export PERRY_LLVMC_SPIKE_LOG=$WORK/liveness.log i=0 same=0 diff=0 cfail_t=0 cfail_p=0 cfail_both=0 for t in $(ls "$WT"/test-files/test_gap_*.ts | sort); do i=$((i+1)) - [ $((i % 6)) -ne 0 ] && continue + [ $((i % STRIDE)) -ne $OFFSET ] && continue name=$(basename "$t" .ts) free_gb=$(df -g /System/Volumes/Data | awk 'NR==2{print $4}') if [ "$free_gb" -lt 6 ]; then echo "ABORT: only ${free_gb}GB free" | tee -a "$WORK/summary.txt"; exit 2; fi gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.t" >"$WORK/$name.t.compile" 2>&1 ct=$? - PERRY_LLVM_CLANG=$SPIKE gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 - cp=$? + if [ "$MODE" = "flag" ]; then + PERRY_LLVM_INPROCESS=1 gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 + cp=$? + # Liveness: the arm must have announced the in-process backend. + if [ $cp -eq 0 ] && ! grep -q "in-process LLVM backend active" "$WORK/$name.p.compile"; then + echo "NOT_LIVE $name" >> "$WORK/results.txt"; cp=97 + fi + else + PERRY_LLVM_CLANG=$SPIKE gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 + cp=$? + fi if [ $ct -ne 0 ] && [ $cp -ne 0 ]; then cfail_both=$((cfail_both+1)); echo "CFAIL_BOTH $name" >> "$WORK/results.txt"; rm -f "$WORK/$name".[tp]; continue; fi if [ $ct -ne 0 ]; then cfail_t=$((cfail_t+1)); echo "CFAIL_T $name" >> "$WORK/results.txt"; rm -f "$WORK/$name".[tp]; continue; fi @@ -41,7 +56,11 @@ for t in $(ls "$WT"/test-files/test_gap_*.ts | sort); do fi rm -f "$WORK/$name.t" "$WORK/$name.p" done -compiles=$(grep -c . "$WORK/liveness.log" || true) +if [ "$MODE" = "flag" ]; then + compiles=$(grep -l "in-process LLVM backend active" "$WORK"/*.p.compile 2>/dev/null | wc -l | tr -d ' ') +else + compiles=$(grep -c . "$WORK/liveness.log" || true) +fi { echo "batch A/B complete: same=$same diff=$diff cfail_t=$cfail_t cfail_p=$cfail_p cfail_both=$cfail_both" echo "in-process compiles proven live: $compiles" From 36dc1c28d849271b3b24cc6c1966ca7103046250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 09:34:07 +0200 Subject: [PATCH 05/26] exp: link tracking issue #7241 in the write-up Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- docs/llvm-inprocess-experiment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/llvm-inprocess-experiment.md b/docs/llvm-inprocess-experiment.md index c2751ba636..fd570f6da0 100644 --- a/docs/llvm-inprocess-experiment.md +++ b/docs/llvm-inprocess-experiment.md @@ -11,7 +11,7 @@ Companion artifacts: - `experiments/llvm-inprocess-spike/` — the Phase 0 spike binary (see below). - `crates/perry-codegen/src/inprocess.rs` — the integrated backend (`llvm-inprocess` cargo feature). -- Tracking issue: filed on PerryTS/perry with the Phase 0 answers. +- Tracking issue: PerryTS/perry#7241 (Phase 0 answers in the opening post). ## Thesis (from the experiment brief) From 2420a87065f0884ac7973435c57727b62cc91d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 10:20:49 +0200 Subject: [PATCH 06/26] =?UTF-8?q?exp:=20Phase=202=20scaffolding=20?= =?UTF-8?q?=E2=80=94=20native=20module=20construction=20modes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PERRY_LLVM_INPROCESS gains 'native' (function bodies built through the LLVM C API; only the module skeleton stays textual) and 'diff' (both arms built in the same LLVM, normalized prints compared, text arm's object returned). Skeleton = LlModule::skeleton_ir; plan argv comes from the same build_clang_compile_plan decision code via native_plan_args (size input = the render-free estimate). inprocess.rs split into parse_ir_text + optimize_and_emit_module for reuse. dialect.rs is a loud-failing stub so the new modes cannot silently no-op before the reader lands; unported paths (unit-split, emit_ir_only) fall through to in-process transport. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/codegen/mod.rs | 38 +++++ crates/perry-codegen/src/dialect.rs | 33 ++++ crates/perry-codegen/src/inprocess.rs | 79 ++++++++-- crates/perry-codegen/src/lib.rs | 4 + crates/perry-codegen/src/linker.rs | 24 +++ crates/perry-codegen/src/module.rs | 45 +++++- crates/perry-codegen/src/native_emit.rs | 197 ++++++++++++++++++++++++ 7 files changed, 407 insertions(+), 13 deletions(-) create mode 100644 crates/perry-codegen/src/dialect.rs create mode 100644 crates/perry-codegen/src/native_emit.rs diff --git a/crates/perry-codegen/src/codegen/mod.rs b/crates/perry-codegen/src/codegen/mod.rs index d192c9b864..79208bde05 100644 --- a/crates/perry-codegen/src/codegen/mod.rs +++ b/crates/perry-codegen/src/codegen/mod.rs @@ -2613,6 +2613,15 @@ pub fn compile_module(hir: &HirModule, opts: CompileOptions) -> Result> return crate::linker::compile_units_to_object(&units, opts.target.as_deref()); } + // exp/llvm-inprocess Phase 2: `PERRY_LLVM_INPROCESS=native` constructs + // function bodies through the LLVM C API (only the module skeleton is + // textual); `=diff` builds both arms and diffs them. Unit-split and + // emit_ir_only paths above stay textual (they fall into the in-process + // *transport* under these values, so no clang subprocess either way). + if let Some(result) = try_native_construction(&llmod, opts.target.as_deref()) { + return result; + } + let ll_text = llmod.to_ir(); log::debug!( "perry-codegen: emitted {} bytes of LLVM IR for '{}' ({} interned strings)", @@ -2631,3 +2640,32 @@ pub fn compile_module(hir: &HirModule, opts: CompileOptions) -> Result> crate::linker::compile_ll_to_object(&ll_text, opts.target.as_deref()) } } + +/// exp/llvm-inprocess Phase 2 dispatch. `None` = native construction not +/// requested (or not compiled in) — continue on the text path. The +/// feature-off twin returns `None` unconditionally; a build without the +/// feature still fails loudly downstream in `compile_ll_to_object` when any +/// in-process mode is requested, so the flag can never silently no-op. +#[cfg(feature = "llvm-inprocess")] +fn try_native_construction( + llmod: &crate::module::LlModule, + target: Option<&str>, +) -> Option>> { + match crate::native_emit::native_mode() { + crate::native_emit::NativeMode::Off => None, + crate::native_emit::NativeMode::Native => { + Some(crate::native_emit::compile_module_native(llmod, target)) + } + crate::native_emit::NativeMode::Diff => { + Some(crate::native_emit::compile_module_diff(llmod, target)) + } + } +} + +#[cfg(not(feature = "llvm-inprocess"))] +fn try_native_construction( + _llmod: &crate::module::LlModule, + _target: Option<&str>, +) -> Option>> { + None +} diff --git a/crates/perry-codegen/src/dialect.rs b/crates/perry-codegen/src/dialect.rs new file mode 100644 index 0000000000..f0dacb5078 --- /dev/null +++ b/crates/perry-codegen/src/dialect.rs @@ -0,0 +1,33 @@ +//! Reader for Perry's LLVM-IR dialect: consumes one finalized function's +//! text (`LlFunction::to_ir()` output) and constructs it natively in an +//! inkwell module. See `native_emit.rs` for where this sits in Phase 2. +//! +//! This is NOT a general LLVM parser — it accepts exactly the closed set of +//! instruction, type, and operand forms perry-codegen emits (bounded by the +//! corpus census in the experiment doc) and errors on anything else, so a +//! new emission form fails loudly at construction instead of silently +//! diverging. + +use anyhow::{bail, Result}; +use inkwell::context::Context; +use inkwell::module::Module; + +/// Parse `fn_text` (a complete `define ... { ... }`) and build it into +/// `module`. Returns the number of instructions constructed. +pub(crate) fn add_function_from_text<'ctx>( + _context: &'ctx Context, + _module: &Module<'ctx>, + fn_text: &str, +) -> Result { + // Implementation lands with the dialect grammar work; the scaffold fails + // loudly so `native`/`diff` modes can never silently no-op. + let name = fn_text + .lines() + .next() + .unwrap_or("") + .split('@') + .nth(1) + .and_then(|s| s.split('(').next()) + .unwrap_or("?"); + bail!("dialect reader not yet implemented (function @{name})") +} diff --git a/crates/perry-codegen/src/inprocess.rs b/crates/perry-codegen/src/inprocess.rs index 3b1b068394..13f727c843 100644 --- a/crates/perry-codegen/src/inprocess.rs +++ b/crates/perry-codegen/src/inprocess.rs @@ -81,12 +81,29 @@ pub fn compile_ll_to_object_inprocess( clang_style_args: &[String], module_name: &str, ) -> Result> { - // Interpret the plan argv. Unknown dash-flags are an error on purpose: - // silently ignoring a flag clang would have honored is how the two - // backends drift apart without anyone noticing. + let (opt, mcpu_native, explicit_cpu, mllvm) = interpret_plan_args(clang_style_args)?; + let context = Context::create(); + let module = parse_ir_text(&context, ll_text, module_name)?; + optimize_and_emit( + &module, + effective_target, + opt, + mcpu_native, + explicit_cpu.as_deref(), + &mllvm, + ) +} + +/// Interpret the plan argv. Unknown dash-flags are an error on purpose: +/// silently ignoring a flag clang would have honored is how the two +/// backends drift apart without anyone noticing. +#[allow(clippy::type_complexity)] +fn interpret_plan_args( + clang_style_args: &[String], +) -> Result<(char, bool, Option, Vec)> { let mut opt = '0'; let mut mcpu_native = false; - let mut explicit_cpu: Option<&str> = None; + let mut explicit_cpu: Option = None; let mut mllvm: Vec = Vec::new(); let mut it = clang_style_args.iter().peekable(); while let Some(a) = it.next() { @@ -103,8 +120,8 @@ pub fn compile_ll_to_object_inprocess( } } "-mcpu=native" | "-march=native" => mcpu_native = true, - s if s.starts_with("-mcpu=") => explicit_cpu = Some(&s["-mcpu=".len()..]), - s if s.starts_with("-march=") => explicit_cpu = Some(&s["-march=".len()..]), + s if s.starts_with("-mcpu=") => explicit_cpu = Some(s["-mcpu=".len()..].to_string()), + s if s.starts_with("-march=") => explicit_cpu = Some(s["-march=".len()..].to_string()), s if s.starts_with("-O") => opt = s.chars().nth(2).unwrap_or('0'), s if !s.starts_with('-') => {} // input/output paths from the plan other => { @@ -115,20 +132,58 @@ pub fn compile_ll_to_object_inprocess( } } } + Ok((opt, mcpu_native, explicit_cpu, mllvm)) +} - global_init(&mllvm); - announce(); - - let context = Context::create(); +/// Parse IR text into a module in `context`. Shared by the transport path +/// (whole-module text) and the native-construction path (the few-KB module +/// skeleton from `LlModule::skeleton_ir`). +pub(crate) fn parse_ir_text<'ctx>( + context: &'ctx Context, + ll_text: &str, + module_name: &str, +) -> Result> { // inkwell 0.9's copy constructor requires (and then strips) a trailing // NUL. One extra copy of the IR text; fine for the transport phase. let mut ir = Vec::with_capacity(ll_text.len() + 1); ir.extend_from_slice(ll_text.as_bytes()); ir.push(0); let buf = MemoryBuffer::create_from_memory_range_copy(&ir, module_name); - let module = context + context .create_module_from_ir(buf) - .map_err(|e| anyhow!("LLVM IR parse error:\n{}", e.to_string()))?; + .map_err(|e| anyhow!("LLVM IR parse error:\n{}", e.to_string())) +} + +/// Interpret plan argv (same grammar as `compile_ll_to_object_inprocess`) and +/// run verify -> pass pipeline -> object emission on an already-built module. +/// The native construction path calls this directly. +pub(crate) fn optimize_and_emit_module( + module: &inkwell::module::Module<'_>, + effective_target: &str, + clang_style_args: &[String], +) -> Result> { + let (opt, mcpu_native, explicit_cpu, mllvm) = interpret_plan_args(clang_style_args)?; + optimize_and_emit( + module, + effective_target, + opt, + mcpu_native, + explicit_cpu.as_deref(), + &mllvm, + ) +} + +fn optimize_and_emit( + module: &inkwell::module::Module<'_>, + effective_target: &str, + opt: char, + mcpu_native: bool, + explicit_cpu: Option<&str>, + mllvm: &[String], +) -> Result> { + global_init(mllvm); + announce(); + module .verify() .map_err(|e| anyhow!("LLVM verifier rejected module:\n{}", e.to_string()))?; diff --git a/crates/perry-codegen/src/lib.rs b/crates/perry-codegen/src/lib.rs index dd5ec5cf80..b93c4b2b17 100644 --- a/crates/perry-codegen/src/lib.rs +++ b/crates/perry-codegen/src/lib.rs @@ -8,6 +8,8 @@ pub mod block; pub(crate) mod boxed_vars; pub mod codegen; pub(crate) mod collectors; +#[cfg(feature = "llvm-inprocess")] +pub(crate) mod dialect; pub mod expr; pub mod ext_registry; pub mod function; @@ -21,6 +23,8 @@ pub(crate) mod lower_conditional; pub(crate) mod lower_string_method; pub mod module; pub mod nanbox; +#[cfg(feature = "llvm-inprocess")] +pub mod native_emit; pub(crate) mod native_value; pub(crate) mod nm_install; pub mod opt_report; diff --git a/crates/perry-codegen/src/linker.rs b/crates/perry-codegen/src/linker.rs index 09d6966ae3..02e13306f1 100644 --- a/crates/perry-codegen/src/linker.rs +++ b/crates/perry-codegen/src/linker.rs @@ -482,6 +482,30 @@ pub fn compile_ll_to_object(ll_text: &str, target_triple: Option<&str>) -> Resul /// * **`PERRY_DEBUG_SYMBOLS`**: no effect on any of the above. It was believed /// to put the `.ll`'s absolute path into DWARF; measured, it does not put /// anything there at all. See `TEMP_NONCE_COUNTER`. +/// exp/llvm-inprocess Phase 2: plan argv for a natively-constructed module, +/// produced by the SAME decision code as the clang path so opt levels +/// (incl. the #4880 oversized fallback) and CPU tuning cannot drift. The +/// byte-size input is the render-free estimate (`estimated_ir_bytes`), since +/// a native module never renders; the paths in the argv are placeholders the +/// in-process interpreter skips. +#[cfg(feature = "llvm-inprocess")] +pub(crate) fn native_plan_args( + target_triple: Option<&str>, + est_ll_bytes: usize, + ll_fn_count: usize, +) -> (String, Vec) { + let plan = build_clang_compile_plan( + PathBuf::from("(in-process)"), + PathBuf::from("(native-module)"), + PathBuf::from("(native-object)"), + target_triple, + est_ll_bytes, + ll_fn_count, + env::var_os("PERRY_DEBUG_SYMBOLS").is_some(), + ); + (plan.effective_target, plan.clang_args) +} + /// exp/llvm-inprocess: truthy `PERRY_LLVM_INPROCESS` routes `.ll -> .o` /// through the LLVM C API inside this process (no clang subprocess, no `.ll` /// on disk). The flag participates in both the build cache and the object diff --git a/crates/perry-codegen/src/module.rs b/crates/perry-codegen/src/module.rs index 297d1642f7..be4f14ddee 100644 --- a/crates/perry-codegen/src/module.rs +++ b/crates/perry-codegen/src/module.rs @@ -435,7 +435,7 @@ impl LlModule { /// dispatch ambiguity limited to genuinely name-colliding members — proper /// disambiguation by class id is a separate concern). Shared by [`to_ir`] /// and [`render_codegen_units`] so both paths agree on the symbol set. - fn deduped_function_refs(&self) -> Vec<&LlFunction> { + pub(crate) fn deduped_function_refs(&self) -> Vec<&LlFunction> { let mut seen: HashSet<&str> = HashSet::with_capacity(self.functions.len()); self.functions .iter() @@ -443,6 +443,49 @@ impl LlModule { .collect() } + /// The module *skeleton*: everything [`to_ir`] emits EXCEPT function + /// definitions — header, string constants, globals, declarations (still + /// filtered against defined names, which the native path adds via the C + /// API), attribute groups and metadata. + /// + /// This is the only text the native construction path + /// (`PERRY_LLVM_INPROCESS=native`) still parses: a few KB of module + /// scaffolding, while every function body is built in memory. It must + /// stay in lockstep with [`to_ir`] — both are thin loops over the same + /// fields, and `native_emit`'s differential mode diffs the two paths' + /// printed modules to catch drift. + #[cfg(feature = "llvm-inprocess")] + pub(crate) fn skeleton_ir(&self) -> String { + let mut ir = String::new(); + ir.push_str("; Generated by perry-codegen\n"); + ir.push_str(&format!("target triple = \"{}\"\n\n", self.target_triple)); + for sc in &self.string_constants { + ir.push_str(sc); + ir.push('\n'); + } + ir.push('\n'); + for g in &self.globals { + ir.push_str(g); + ir.push('\n'); + } + ir.push('\n'); + let defined: HashSet<&str> = self + .deduped_function_refs() + .iter() + .map(|f| f.name.as_str()) + .collect(); + for (name, decl) in &self.declarations { + if defined.contains(name.as_str()) { + continue; + } + ir.push_str(decl); + ir.push('\n'); + } + ir.push('\n'); + self.push_attrs_and_metadata(&mut ir); + ir + } + /// Serialize the module to a complete `.ll` file. pub fn to_ir(&self) -> String { let mut ir = String::new(); diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs new file mode 100644 index 0000000000..aaf7de9e31 --- /dev/null +++ b/crates/perry-codegen/src/native_emit.rs @@ -0,0 +1,197 @@ +//! Phase 2 of exp/llvm-inprocess: **native module construction** — function +//! bodies are built in memory through the LLVM C API instead of being +//! concatenated into module-scale IR text and re-parsed. +//! +//! Mode selection reuses the `PERRY_LLVM_INPROCESS` env var (already part of +//! both cache keys): +//! +//! * `1`/`on`/`true` — transport mode: whole-module text parsed in-process +//! (`inprocess.rs`). +//! * `native` — this module: only the module *skeleton* (globals, declares, +//! attribute groups, metadata — a few KB) is textual; every function body +//! is constructed natively from the finalized per-function line stream. +//! * `diff` — the migration harness: builds the module BOTH ways in the same +//! LLVM, prints both, diffs the normalized prints per function, and returns +//! the text-parsed arm's object. Any non-cosmetic difference is a +//! construction bug — report it, never normalize it away silently. +//! +//! Paths not yet ported (codegen-unit splitting, `emit_ir_only`) fall through +//! to the text pipeline, where `native`/`diff` still select the in-process +//! *transport*, so no clang subprocess appears in any in-process mode. +//! +//! Construction consumes `LlFunction::to_ir()` output per function — the +//! fully finalized text including entry-alloca hoists, boundary splices, +//! return-site rewrites and setjmp volatile promotion — so those transforms +//! have exactly one implementation. The per-function text is transient +//! (dropped immediately after parsing); what stops existing is the +//! module-scale concatenation and the full-grammar LLVM parse. The follow-up +//! step (typed `LlInst` in `LlBlock`) removes the per-line text too; the +//! `instructions=` counter logged per module is the ratchet metric for that +//! migration. + +use anyhow::{anyhow, Result}; +use inkwell::context::Context; +use inkwell::module::Module; + +use crate::module::LlModule; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum NativeMode { + Off, + Native, + Diff, +} + +pub fn native_mode() -> NativeMode { + match std::env::var("PERRY_LLVM_INPROCESS").as_deref() { + Ok("native") => NativeMode::Native, + Ok("diff") => NativeMode::Diff, + _ => NativeMode::Off, + } +} + +/// Build the module natively: parse the skeleton text, then construct every +/// function body through the C API via the dialect reader. +fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result> { + let skeleton = llmod.skeleton_ir(); + let module = crate::inprocess::parse_ir_text(context, &skeleton, "perry_native_module")?; + let mut instructions = 0usize; + let funcs = llmod.deduped_function_refs(); + for f in &funcs { + let fn_text = f.to_ir(); + instructions += crate::dialect::add_function_from_text(context, &module, &fn_text) + .map_err(|e| { + anyhow!( + "native IR construction failed in @{}:\n{}\n--- function IR ---\n{}", + f.name, + e, + fn_text + ) + })?; + } + log::debug!( + "perry-codegen: native construction built {} functions, {} instructions, skeleton {} bytes", + funcs.len(), + instructions, + skeleton.len() + ); + Ok(module) +} + +/// The plan argv for a natively-built module. Same decision code as the text +/// path (`build_clang_compile_plan`), with the byte-size input taken from the +/// render-free size estimate the codegen-unit balancer already uses. +fn plan_for(llmod: &LlModule, target: Option<&str>) -> (String, Vec) { + let est_bytes: usize = llmod + .deduped_function_refs() + .iter() + .map(|f| f.estimated_ir_bytes()) + .sum(); + let fn_count = llmod.deduped_function_refs().len(); + crate::linker::native_plan_args(target, est_bytes, fn_count) +} + +pub fn compile_module_native(llmod: &LlModule, target: Option<&str>) -> Result> { + let context = Context::create(); + let module = build_native_module(&context, llmod)?; + let (effective_target, args) = plan_for(llmod, target); + crate::inprocess::optimize_and_emit_module(&module, &effective_target, &args) +} + +/// Differential harness: text-parsed arm vs natively-built arm, same LLVM, +/// same printer. Returns the text arm's object (the trusted reference) so a +/// diff run is safe to use for real builds while surfacing every divergence. +pub fn compile_module_diff(llmod: &LlModule, target: Option<&str>) -> Result> { + let text = llmod.to_ir(); + let ctx_text = Context::create(); + let m_text = crate::inprocess::parse_ir_text(&ctx_text, &text, "perry_diff_text")?; + + let ctx_native = Context::create(); + let native = build_native_module(&ctx_native, llmod); + + match native { + Err(e) => { + eprintln!("perry: [ir-diff] native construction FAILED (text arm still used): {e:#}"); + } + Ok(m_native) => { + let pa = normalize_print(&m_text.print_to_string().to_string()); + let pb = normalize_print(&m_native.print_to_string().to_string()); + if pa == pb { + eprintln!( + "perry: [ir-diff] OK — native construction matches text parse ({} lines)", + pa.lines().count() + ); + } else { + report_diff(&pa, &pb); + if let Ok(dir) = std::env::var("PERRY_LLVM_DIFF_DIR") { + let _ = std::fs::create_dir_all(&dir); + let _ = std::fs::write(format!("{dir}/text_arm.ll"), &pa); + let _ = std::fs::write(format!("{dir}/native_arm.ll"), &pb); + eprintln!("perry: [ir-diff] arms dumped under {dir}"); + } + } + } + } + + let (effective_target, args) = plan_for(llmod, target); + crate::inprocess::optimize_and_emit_module(&m_text, &effective_target, &args) +} + +/// Normalization limited to the classes catalogued in +/// `docs/llvm-inprocess-experiment.md` (attribute-group *numbering* and +/// header trivia). Everything else must match exactly — both arms come out +/// of the same LLVM printer. +fn normalize_print(printed: &str) -> String { + let mut out = String::with_capacity(printed.len()); + for line in printed.lines() { + if line.starts_with("; ModuleID") || line.starts_with("source_filename") { + continue; + } + // `#12` group ids may be assigned in a different order by the two + // construction orders; the *contents* of the groups still compare + // via the `attributes` lines themselves (with ids blanked). + let mut norm = String::with_capacity(line.len()); + let mut chars = line.chars().peekable(); + while let Some(c) = chars.next() { + if c == '#' && chars.peek().is_some_and(|d| d.is_ascii_digit()) { + while chars.peek().is_some_and(|d| d.is_ascii_digit()) { + chars.next(); + } + norm.push_str("#N"); + } else { + norm.push(c); + } + } + out.push_str(&norm); + out.push('\n'); + } + out +} + +fn report_diff(pa: &str, pb: &str) { + let a: Vec<&str> = pa.lines().collect(); + let b: Vec<&str> = pb.lines().collect(); + let mut shown = 0; + let mut i = 0; + let mut j = 0; + eprintln!( + "perry: [ir-diff] MISMATCH — native construction diverges from text parse \ + ({} vs {} lines); first divergences:", + a.len(), + b.len() + ); + // Naive sync-on-equal walk: enough to *locate* divergence; the dumped + // arms (PERRY_LLVM_DIFF_DIR) are the real investigation artifact. + while i < a.len() && j < b.len() && shown < 12 { + if a[i] == b[j] { + i += 1; + j += 1; + continue; + } + eprintln!(" text : {}", a[i]); + eprintln!(" native: {}", b[j]); + shown += 1; + i += 1; + j += 1; + } +} From 055793a00b3fda917c0ca04c0bde2a80c1700d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 10:35:57 +0200 Subject: [PATCH 07/26] =?UTF-8?q?exp:=20dialect=20reader=20=E2=80=94=20nat?= =?UTF-8?q?ive=20function=20construction=20passes=20both=20corpora?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bounded reader for perry's IR dialect (census-driven): typed operand resolution with per-function %name maps, placeholder-RAUW for non-phi cross-block forward references (the idispatch tower shape), deferred phi incomings, callsite-derived call types (opaque-ptr semantics: a direct call's fn type is the callsite's, not the declare's — measured on js_native_call_value), pointer icmp, atomic/volatile loads, fneg, SIMD vectors, pre-declaration of module-internal defines. Corpus gate: every function of spike_text.ll + batch_kernel.ll (9k+ instructions) constructs natively and passes the LLVM verifier. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/dialect.rs | 1368 ++++++++++++++++++++++- crates/perry-codegen/src/native_emit.rs | 25 +- 2 files changed, 1376 insertions(+), 17 deletions(-) diff --git a/crates/perry-codegen/src/dialect.rs b/crates/perry-codegen/src/dialect.rs index f0dacb5078..e3f9aeed2f 100644 --- a/crates/perry-codegen/src/dialect.rs +++ b/crates/perry-codegen/src/dialect.rs @@ -2,32 +2,1368 @@ //! text (`LlFunction::to_ir()` output) and constructs it natively in an //! inkwell module. See `native_emit.rs` for where this sits in Phase 2. //! -//! This is NOT a general LLVM parser — it accepts exactly the closed set of +//! This is NOT a general LLVM parser — it accepts the closed set of //! instruction, type, and operand forms perry-codegen emits (bounded by the //! corpus census in the experiment doc) and errors on anything else, so a //! new emission form fails loudly at construction instead of silently -//! diverging. +//! diverging. The LLVM verifier and `PERRY_LLVM_INPROCESS=diff` are the +//! nets behind it. +//! +//! Instructions keep their textual `%names`, so a natively-built function +//! prints comparably to the text-parsed arm in diff mode. + +use std::collections::HashMap; -use anyhow::{bail, Result}; +use anyhow::{anyhow, bail, Context as AnyhowContext, Result}; +use inkwell::basic_block::BasicBlock; +use inkwell::builder::Builder; use inkwell::context::Context; -use inkwell::module::Module; +use inkwell::module::{Linkage, Module}; +use inkwell::types::{BasicType, BasicTypeEnum, FunctionType}; +use inkwell::values::{ + AsValueRef, BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue, + InstructionValue, PhiValue, +}; +use inkwell::{AddressSpace, FloatPredicate, IntPredicate}; + +/// Create (only) the function declaration for `fn_text`'s define header, so +/// later-defined functions are callable while earlier bodies are read. The +/// native path pre-declares every define before reading any body — calls to +/// module-internal functions are forward references at module scope, exactly +/// like registers are at function scope. +pub(crate) fn predeclare_function_from_text<'ctx>( + context: &'ctx Context, + module: &Module<'ctx>, + fn_text: &str, +) -> Result<()> { + let header = fn_text + .lines() + .next() + .ok_or_else(|| anyhow!("empty function text"))?; + FnReader::declare_from_header(context, module, header)?; + Ok(()) +} /// Parse `fn_text` (a complete `define ... { ... }`) and build it into /// `module`. Returns the number of instructions constructed. pub(crate) fn add_function_from_text<'ctx>( - _context: &'ctx Context, - _module: &Module<'ctx>, + context: &'ctx Context, + module: &Module<'ctx>, fn_text: &str, ) -> Result { - // Implementation lands with the dialect grammar work; the scaffold fails - // loudly so `native`/`diff` modes can never silently no-op. - let name = fn_text - .lines() + let mut lines = fn_text.lines(); + let header = lines.next().ok_or_else(|| anyhow!("empty function text"))?; + let mut b = FnReader::begin(context, module, header)?; + for line in lines { + let t = line.trim(); + if t.is_empty() || t.starts_with(';') { + continue; + } + if t == "}" { + break; + } + if let Some(label) = t.strip_suffix(':') { + // Block label lines are never indented instructions. + if !line.starts_with(' ') { + b.enter_block(label)?; + continue; + } + } + b.instruction(t).with_context(|| format!("in line: {t}"))?; + } + b.finish() +} + +struct FnReader<'ctx, 'm> { + ctx: &'ctx Context, + module: &'m Module<'ctx>, + builder: Builder<'ctx>, + func: FunctionValue<'ctx>, + /// label -> basic block (created lazily on first reference). + blocks: HashMap>, + /// `%name` -> value. + vals: HashMap>, + /// Phi incomings deferred until every register is defined + /// (loop-carried values are forward references at phi-build time). + pending_phis: Vec<(PhiValue<'ctx>, BasicTypeEnum<'ctx>, Vec<(String, String)>)>, + /// Non-phi forward references (measured in the corpus: the megamorphic + /// `idispatch.tower` shape uses a register before its defining block + /// appears in the text). Each unresolved `%reg` use gets a placeholder + /// instruction (`select true, undef, undef`) that is RAUW'd and erased + /// when the real definition arrives — the same strategy LLVM's own + /// `.ll` parser uses. + placeholders: HashMap>, + positioned: bool, + count: usize, +} + +/// Pieces of a `define [linkage] RET @NAME(T %p, ...) [attrs] {` line. +struct ParsedHeader { + linkage: Option, + ret_tok: String, + name: String, + /// (type token, `%name`) per parameter. + params: Vec<(String, String)>, + attr_str: String, +} + +fn parse_header(header: &str) -> Result { + let rest = header + .strip_prefix("define ") + .ok_or_else(|| anyhow!("not a define line: {header}"))?; + let rest = rest + .strip_suffix('{') + .ok_or_else(|| anyhow!("define line missing open brace"))? + .trim_end(); + + let mut toks = rest.split_whitespace().peekable(); + let mut linkage = None; + if let Some(&t) = toks.peek() { + if t == "internal" || t == "private" { + linkage = Some(if t == "internal" { + Linkage::Internal + } else { + Linkage::Private + }); + toks.next(); + } + } + let ret_tok = toks .next() - .unwrap_or("") - .split('@') - .nth(1) - .and_then(|s| s.split('(').next()) - .unwrap_or("?"); - bail!("dialect reader not yet implemented (function @{name})") + .ok_or_else(|| anyhow!("define line missing return type"))? + .to_string(); + + let at = rest + .find('@') + .ok_or_else(|| anyhow!("define line missing @name"))?; + let after = &rest[at + 1..]; + let paren = after + .find('(') + .ok_or_else(|| anyhow!("define line missing param list"))?; + let name = unquote(&after[..paren]); + let close = rmatch_paren(after, paren)?; + let params_str = &after[paren + 1..close]; + let attr_str = after[close + 1..].trim().to_string(); + + let mut params = Vec::new(); + for p in split_top_level(params_str) { + let p = p.trim(); + if p.is_empty() { + continue; + } + let (ty_tok, name_tok) = p + .rsplit_once(' ') + .ok_or_else(|| anyhow!("bad param: {p}"))?; + params.push((ty_tok.trim().to_string(), name_tok.trim().to_string())); + } + Ok(ParsedHeader { + linkage, + ret_tok, + name, + params, + attr_str, + }) +} + +impl<'ctx, 'm> FnReader<'ctx, 'm> { + /// Find-or-create the function for a define header, with its real + /// signature and linkage. Idempotent: pre-declaration and body reading + /// both land here. + fn declare_from_header( + ctx: &'ctx Context, + module: &Module<'ctx>, + header: &str, + ) -> Result> { + let h = parse_header(header)?; + let mut mtypes: Vec = Vec::new(); + for (ty_tok, _) in &h.params { + mtypes.push(basic_type(ctx, ty_tok)?.into()); + } + let fn_type = fn_type_of(ctx, &h.ret_tok, &mtypes)?; + let func = match module.get_function(&h.name) { + Some(f) => f, + None => module.add_function(&h.name, fn_type, None), + }; + if let Some(l) = h.linkage { + func.set_linkage(l); + } + Ok(func) + } + + fn begin(ctx: &'ctx Context, module: &'m Module<'ctx>, header: &str) -> Result { + let h = parse_header(header)?; + let func = Self::declare_from_header(ctx, module, header)?; + // The skeleton never declares defined names (`skeleton_ir` filters + // them), so a body on the function here means a duplicate define. + if func.count_basic_blocks() > 0 { + bail!("duplicate define of @{}", h.name); + } + let param_names: Vec = h.params.iter().map(|(_, n)| n.clone()).collect(); + let attr_str = h.attr_str; + for a in attr_str.split_whitespace() { + match a { + // Attribute-group references: the only group perry stamps on + // defines is #1 (noinline, the setjmp boundary). Group + // contents live in the skeleton for *declares*; for defines + // we apply the concrete attribute. + "#1" => add_enum_attr(ctx, func, "noinline"), + "alwaysinline" | "inlinehint" | "noinline" => add_enum_attr(ctx, func, a), + other => bail!("unknown define attribute `{other}`"), + } + } + for (i, pname) in param_names.iter().enumerate() { + let pv = func + .get_nth_param(i as u32) + .ok_or_else(|| anyhow!("param {i} missing"))?; + pv.set_name(pname.trim_start_matches('%')); + // Params are registered under their `%name`. + } + + let builder = ctx.create_builder(); + let mut vals = HashMap::new(); + for (i, pname) in param_names.iter().enumerate() { + vals.insert(pname.clone(), func.get_nth_param(i as u32).unwrap()); + } + Ok(Self { + ctx, + module, + builder, + func, + blocks: HashMap::new(), + vals, + pending_phis: Vec::new(), + placeholders: HashMap::new(), + positioned: false, + count: 0, + }) + } + + fn block(&mut self, label: &str) -> BasicBlock<'ctx> { + if let Some(b) = self.blocks.get(label) { + return *b; + } + let b = self.ctx.append_basic_block(self.func, label); + self.blocks.insert(label.to_string(), b); + b + } + + fn enter_block(&mut self, label: &str) -> Result<()> { + let b = self.block(label); + self.builder.position_at_end(b); + self.positioned = true; + Ok(()) + } + + fn def(&mut self, name: &str, v: BasicValueEnum<'ctx>) { + if let Some(ph) = self.placeholders.remove(name) { + rauw(ph, v); + if let Some(inst) = ph.as_instruction_value() { + let _ = inst.erase_from_basic_block(); + } + } + self.vals.insert(name.to_string(), v); + } + + /// Resolve `(type, token)` to a value. An undefined `%reg` becomes a + /// typed placeholder resolved by a later `def` (see `placeholders`). + fn val(&mut self, ty: BasicTypeEnum<'ctx>, tok: &str) -> Result> { + let tok = tok.trim(); + if let Some(v) = self.vals.get(tok) { + return Ok(*v); + } + if tok.starts_with('%') { + let undef: BasicValueEnum = match ty { + BasicTypeEnum::FloatType(t) => t.get_undef().into(), + BasicTypeEnum::IntType(t) => t.get_undef().into(), + BasicTypeEnum::PointerType(t) => t.get_undef().into(), + other => bail!("forward reference {tok} of unsupported type {other:?}"), + }; + let ph = self + .builder + .build_select( + self.ctx.bool_type().const_int(1, false), + undef, + undef, + &format!("fwd.{}", tok.trim_start_matches('%')), + ) + .map_err(be)?; + self.placeholders.insert(tok.to_string(), ph); + self.vals.insert(tok.to_string(), ph); + return Ok(ph); + } + constant(self.ctx, self.module, ty, tok) + } + + fn instruction(&mut self, t: &str) -> Result<()> { + if !self.positioned { + bail!("instruction before first block label"); + } + self.count += 1; + // `%r = op ...` vs bare op. + if let Some((lhs, rhs)) = t.split_once(" = ") { + let (op, rest) = rhs + .split_once(' ') + .ok_or_else(|| anyhow!("malformed instruction"))?; + self.value_inst(lhs.trim(), op, rest.trim()) + } else { + let (op, rest) = t.split_once(' ').unwrap_or((t, "")); + self.bare_inst(op, rest.trim()) + } + } + + fn value_inst(&mut self, dst: &str, op: &str, rest: &str) -> Result<()> { + let v: BasicValueEnum = match op { + "alloca" => { + // `alloca T[, align N]` + let ty_tok = rest.split(',').next().unwrap_or(rest).trim(); + let ty = basic_type(self.ctx, ty_tok)?; + let p = self + .builder + .build_alloca(ty, dst.trim_start_matches('%')) + .map_err(be)?; + set_alignment_if_any(p.as_instruction_value(), rest); + p.into() + } + "load" => { + let mut rest2 = rest; + let mut volatile = false; + let mut atomic = false; + loop { + if let Some(r) = rest2.strip_prefix("volatile ") { + volatile = true; + rest2 = r; + } else if let Some(r) = rest2.strip_prefix("atomic ") { + atomic = true; + rest2 = r; + } else { + break; + } + } + self.load(dst, volatile, atomic, rest2)? + } + "fneg" => { + let (ty_tok, vtok) = ty_and_val(rest)?; + let v = self.val(basic_type(self.ctx, ty_tok)?, vtok)?; + self.builder + .build_float_neg(v.into_float_value(), dst.trim_start_matches('%')) + .map_err(be)? + .into() + } + "phi" => return self.phi(dst, rest), + "call" | "tail call" => self + .call(Some(dst), rest)? + .ok_or_else(|| anyhow!("call with result had void type"))?, + "getelementptr" => self.gep(dst, rest)?, + "select" => { + // `select i1 C, T A, T B` + let parts = split_top_level(rest); + if parts.len() != 3 { + bail!("bad select"); + } + let (cty, ctok) = ty_and_val(&parts[0])?; + let cond = self.val(basic_type(self.ctx, cty)?, ctok)?; + let (aty, atok) = ty_and_val(&parts[1])?; + let ty = basic_type(self.ctx, aty)?; + let a = self.val(ty, atok)?; + let (_bty, btok) = ty_and_val(&parts[2])?; + let bv = self.val(ty, btok)?; + self.builder + .build_select(cond.into_int_value(), a, bv, dst.trim_start_matches('%')) + .map_err(be)? + } + _ => self.binary_or_cast(dst, op, rest)?, + }; + self.def(dst, v); + Ok(()) + } + + fn bare_inst(&mut self, op: &str, rest: &str) -> Result<()> { + match op { + "store" => { + let volatile = rest.starts_with("volatile "); + let rest = rest.strip_prefix("volatile ").unwrap_or(rest); + // `store T V, ptr P[, align N]` + let parts = split_top_level(rest); + if parts.len() < 2 { + bail!("bad store"); + } + let (vty, vtok) = ty_and_val(&parts[0])?; + let ty = basic_type(self.ctx, vty)?; + let v = self.val(ty, vtok)?; + let (_pty, ptok) = ty_and_val(&parts[1])?; + let p = self.val(self.ctx.ptr_type(AddressSpace::default()).into(), ptok)?; + let inst = self + .builder + .build_store(p.into_pointer_value(), v) + .map_err(be)?; + if volatile { + let _ = inst.set_volatile(true); + } + set_alignment_if_any(Some(inst), rest); + Ok(()) + } + "br" => { + if let Some(lbl) = rest.strip_prefix("label %") { + let b = self.block(lbl.trim()); + self.builder.build_unconditional_branch(b).map_err(be)?; + } else { + // `br i1 C, label %A, label %B` + let parts = split_top_level(rest); + if parts.len() != 3 { + bail!("bad conditional br"); + } + let (cty, ctok) = ty_and_val(&parts[0])?; + let c = self.val(basic_type(self.ctx, cty)?, ctok)?; + let a = self.block(strip_label(&parts[1])?); + let b = self.block(strip_label(&parts[2])?); + self.builder + .build_conditional_branch(c.into_int_value(), a, b) + .map_err(be)?; + } + Ok(()) + } + "ret" => { + if rest == "void" { + self.builder.build_return(None).map_err(be)?; + } else { + let (ty_tok, vtok) = ty_and_val(rest)?; + let ty = basic_type(self.ctx, ty_tok)?; + let v = self.val(ty, vtok)?; + self.builder.build_return(Some(&v)).map_err(be)?; + } + Ok(()) + } + "call" | "tail call" => self.call(None, rest).map(|_| ()), + "switch" => self.switch(rest), + "unreachable" => { + self.builder.build_unreachable().map_err(be)?; + Ok(()) + } + other => bail!("unknown instruction `{other}`"), + } + } + + fn load( + &mut self, + dst: &str, + volatile: bool, + atomic: bool, + rest: &str, + ) -> Result> { + // `T, ptr P[ ][, align N]` + let parts = split_top_level(rest); + if parts.len() < 2 { + bail!("bad load"); + } + let ty = basic_type(self.ctx, parts[0].trim())?; + let (_pty, pval) = ty_and_val(&parts[1])?; + // An atomic load's ordering keyword trails the pointer operand + // (`ptr @g seq_cst`), measured in the corpus census. + let mut ptoks = pval.split_whitespace(); + let ptok = ptoks.next().ok_or_else(|| anyhow!("bad load pointer"))?; + let ordering = ptoks.next(); + let p = self.val(self.ctx.ptr_type(AddressSpace::default()).into(), ptok)?; + let v = self + .builder + .build_load(ty, p.into_pointer_value(), dst.trim_start_matches('%')) + .map_err(be)?; + if volatile { + let _ = v.as_instruction_value().map(|i| i.set_volatile(true)); + } + if atomic { + let ord = match ordering { + Some("seq_cst") => { + llvm_sys::LLVMAtomicOrdering::LLVMAtomicOrderingSequentiallyConsistent + } + Some("acquire") => llvm_sys::LLVMAtomicOrdering::LLVMAtomicOrderingAcquire, + Some("monotonic") => llvm_sys::LLVMAtomicOrdering::LLVMAtomicOrderingMonotonic, + Some("unordered") => llvm_sys::LLVMAtomicOrdering::LLVMAtomicOrderingUnordered, + other => bail!("unsupported atomic ordering {other:?}"), + }; + if let Some(inst) = v.as_instruction_value() { + unsafe { llvm_sys::core::LLVMSetOrdering(inst.as_value_ref(), ord) }; + } + } + set_alignment_if_any(v.as_instruction_value(), rest); + Ok(v) + } + + fn phi(&mut self, dst: &str, rest: &str) -> Result<()> { + // `T [ V, %B ], [ V2, %B2 ], ...` + let (ty_tok, incs) = rest.split_once('[').ok_or_else(|| anyhow!("bad phi"))?; + let ty = basic_type(self.ctx, ty_tok.trim())?; + let phi = self + .builder + .build_phi(ty, dst.trim_start_matches('%')) + .map_err(be)?; + let mut pending = Vec::new(); + for pair in format!("[{incs}").split(']') { + let pair = pair.trim().trim_start_matches(',').trim(); + let Some(body) = pair.strip_prefix('[') else { + continue; + }; + let (v, b) = body + .split_once(',') + .ok_or_else(|| anyhow!("bad phi incoming: {body}"))?; + pending.push(( + v.trim().to_string(), + b.trim().trim_start_matches('%').to_string(), + )); + } + self.def(dst, phi.as_basic_value()); + self.pending_phis.push((phi, ty, pending)); + Ok(()) + } + + fn gep(&mut self, dst: &str, rest: &str) -> Result> { + let (inbounds, rest) = match rest.strip_prefix("inbounds ") { + Some(r) => (true, r), + None => (false, rest), + }; + let parts = split_top_level(rest); + if parts.len() < 2 { + bail!("bad getelementptr"); + } + let pointee = basic_type(self.ctx, parts[0].trim())?; + let (_pty, ptok) = ty_and_val(&parts[1])?; + let p = self + .val(self.ctx.ptr_type(AddressSpace::default()).into(), ptok)? + .into_pointer_value(); + let mut idx = Vec::new(); + for part in &parts[2..] { + let (ity, itok) = ty_and_val(part)?; + idx.push(self.val(basic_type(self.ctx, ity)?, itok)?.into_int_value()); + } + let name = dst.trim_start_matches('%'); + let v = unsafe { + if inbounds { + self.builder.build_in_bounds_gep(pointee, p, &idx, name) + } else { + self.builder.build_gep(pointee, p, &idx, name) + } + } + .map_err(be)?; + Ok(v.into()) + } + + fn switch(&mut self, rest: &str) -> Result<()> { + // `switch T V, label %DEF [ T C1, label %B1 T C2, label %B2 ... ]` + // (zero occurrences in the corpus census; kept because the semantic + // surface can emit it and losing it would fail loudly anyway). + let (head, cases) = rest.split_once('[').ok_or_else(|| anyhow!("bad switch"))?; + let head_parts = split_top_level(head.trim()); + if head_parts.len() != 2 { + bail!("bad switch head"); + } + let (vty, vtok) = ty_and_val(&head_parts[0])?; + let ty = basic_type(self.ctx, vty)?; + let v = self.val(ty, vtok)?.into_int_value(); + let def = self.block(strip_label(&head_parts[1])?); + // Case list: `T C, label %B` repeated, whitespace-separated. + let mut pairs = Vec::new(); + let toks: Vec<&str> = cases + .trim() + .trim_end_matches(']') + .split_whitespace() + .collect(); + let mut i = 0; + while i + 3 < toks.len() + 1 { + if i + 4 > toks.len() { + break; + } + let cty = toks[i]; + let ctok = toks[i + 1].trim_end_matches(','); + if toks[i + 2] != "label" { + bail!("bad switch case near `{}`", toks[i..].join(" ")); + } + let bb = self.block(toks[i + 3].trim_start_matches('%')); + let cv = self.val(basic_type(self.ctx, cty)?, ctok)?.into_int_value(); + pairs.push((cv, bb)); + i += 4; + } + self.builder.build_switch(v, def, &pairs).map_err(be)?; + Ok(()) + } + + /// Calls: direct `@f(...)`, indirect `%fp(...)` (with or without a + /// pre-opaque `(sig)*` type), and the inline-asm barrier. + fn call(&mut self, dst: Option<&str>, rest: &str) -> Result>> { + // Optional fast-math prefix tokens on float-returning calls. + let rest = rest + .trim_start_matches("reassoc ") + .trim_start_matches("contract ") + .trim_start(); + + // Inline asm: `void asm sideeffect "ASM", "CONSTRAINTS"(ARGS)` + if let Some(asm_rest) = rest.strip_prefix("void asm ") { + return self.call_asm(asm_rest).map(|_| None); + } + + // Return type is the first top-level token; everything from the + // callee marker on is `CALLEE(ARGS)[ #attrs]`. + let callee_pos = rest + .find(['@', '%']) + .ok_or_else(|| anyhow!("call without callee"))?; + let sig_str = rest[..callee_pos].trim().trim_end_matches('*').trim(); + let after = &rest[callee_pos..]; + let paren = after + .find('(') + .ok_or_else(|| anyhow!("call missing arg list"))?; + let callee = &after[..paren]; + let close = rmatch_paren(after, paren)?; + let args_str = &after[paren + 1..close]; + + let mut args: Vec = Vec::new(); + let mut arg_types: Vec = Vec::new(); + for a in split_top_level(args_str) { + let (aty, atok) = ty_and_val(&a)?; + let ty = basic_type(self.ctx, aty)?; + args.push(self.val(ty, atok)?.into()); + arg_types.push(ty.into()); + } + + let name = dst.map(|d| d.trim_start_matches('%')).unwrap_or(""); + // The call's function type is the CALLSITE's, not the callee's + // declared signature — under opaque pointers LLVM accepts (and Perry + // emits) direct calls whose argument types differ from the declare + // (measured: `js_native_call_value` declared `(double, i64, i64)`, + // called with `(double, ptr, i64)`). Deriving the type from the + // callsite and calling through the callee *pointer* reproduces the + // text parser's semantics exactly; LLVM still prints it as a direct + // call. + let fn_ty = indirect_fn_type(self.ctx, sig_str, &arg_types)?; + let callee_ptr = if let Some(fname) = callee.strip_prefix('@') { + self.module + .get_function(&unquote(fname)) + .ok_or_else(|| anyhow!("call to undeclared @{fname}"))? + .as_global_value() + .as_pointer_value() + } else { + self.val(self.ctx.ptr_type(AddressSpace::default()).into(), callee)? + .into_pointer_value() + }; + let site = self + .builder + .build_indirect_call(fn_ty, callee_ptr, &args, name) + .map_err(be)?; + match site.try_as_basic_value() { + inkwell::values::ValueKind::Basic(v) => Ok(Some(v)), + _ => Ok(None), + } + } + + fn call_asm(&mut self, rest: &str) -> Result<()> { + // `sideeffect "ASM", "CONSTR"()` — the only asm perry emits is the + // empty barrier, but parse the strings properly anyway. + let sideeffect = rest.trim_start().starts_with("sideeffect"); + let mut strings = rest.split('"'); + let asm = strings.nth(1).unwrap_or("").to_string(); + let constraints = strings.nth(1).unwrap_or("").to_string(); + let void_fn = self.ctx.void_type().fn_type(&[], false); + let ptr = + self.ctx + .create_inline_asm(void_fn, asm, constraints, sideeffect, false, None, false); + self.builder + .build_indirect_call(void_fn, ptr, &[], "") + .map_err(be)?; + Ok(()) + } + + fn binary_or_cast(&mut self, dst: &str, op: &str, rest: &str) -> Result> { + let name = dst.trim_start_matches('%'); + // Casts: `OP T V to T2` + if let Some((src, dst_ty_tok)) = rest.rsplit_once(" to ") { + let (sty, stok) = ty_and_val(src)?; + let sty_t = basic_type(self.ctx, sty)?; + let v = self.val(sty_t, stok)?; + let dty = basic_type(self.ctx, dst_ty_tok.trim())?; + let out = match op { + "bitcast" => self.builder.build_bit_cast(v, dty, name).map_err(be)?, + "zext" => self + .builder + .build_int_z_extend(v.into_int_value(), dty.into_int_type(), name) + .map_err(be)? + .into(), + "sext" => self + .builder + .build_int_s_extend(v.into_int_value(), dty.into_int_type(), name) + .map_err(be)? + .into(), + "trunc" => self + .builder + .build_int_truncate(v.into_int_value(), dty.into_int_type(), name) + .map_err(be)? + .into(), + "fptosi" => self + .builder + .build_float_to_signed_int(v.into_float_value(), dty.into_int_type(), name) + .map_err(be)? + .into(), + "fptoui" => self + .builder + .build_float_to_unsigned_int(v.into_float_value(), dty.into_int_type(), name) + .map_err(be)? + .into(), + "sitofp" => self + .builder + .build_signed_int_to_float(v.into_int_value(), dty.into_float_type(), name) + .map_err(be)? + .into(), + "uitofp" => self + .builder + .build_unsigned_int_to_float(v.into_int_value(), dty.into_float_type(), name) + .map_err(be)? + .into(), + "fpext" => self + .builder + .build_float_ext(v.into_float_value(), dty.into_float_type(), name) + .map_err(be)? + .into(), + "fptrunc" => self + .builder + .build_float_trunc(v.into_float_value(), dty.into_float_type(), name) + .map_err(be)? + .into(), + "ptrtoint" => self + .builder + .build_ptr_to_int(v.into_pointer_value(), dty.into_int_type(), name) + .map_err(be)? + .into(), + "inttoptr" => self + .builder + .build_int_to_ptr(v.into_int_value(), dty.into_pointer_type(), name) + .map_err(be)? + .into(), + other => bail!("unknown cast `{other}`"), + }; + return Ok(out); + } + + // icmp / fcmp + if op == "icmp" || op == "fcmp" { + let (pred, rest2) = rest.split_once(' ').ok_or_else(|| anyhow!("bad {op}"))?; + let parts = split_top_level(rest2); + if parts.len() != 2 { + bail!("bad {op} operands"); + } + let (ty_tok, atok) = ty_and_val(&parts[0])?; + let ty = basic_type(self.ctx, ty_tok)?; + let a = self.val(ty, atok)?; + let b2 = self.val(ty, parts[1].trim())?; + let out: BasicValueEnum = if op == "icmp" { + // `icmp eq ptr %x, null` is common (null checks) — pointers + // compare directly, same as the text form. + if a.is_pointer_value() { + self.builder + .build_int_compare( + int_pred(pred)?, + a.into_pointer_value(), + b2.into_pointer_value(), + name, + ) + .map_err(be)? + .into() + } else { + self.builder + .build_int_compare( + int_pred(pred)?, + a.into_int_value(), + b2.into_int_value(), + name, + ) + .map_err(be)? + .into() + } + } else { + self.builder + .build_float_compare( + float_pred(pred)?, + a.into_float_value(), + b2.into_float_value(), + name, + ) + .map_err(be)? + .into() + }; + return Ok(out); + } + + // Binary ops: `[flags] T A, B` where op may carry nsw/nuw/fmf tokens. + let mut op_base = op; + let mut rest2 = rest; + let mut flag_tokens: Vec<&str> = Vec::new(); + loop { + let (first, r) = rest2.split_once(' ').unwrap_or((rest2, "")); + match first { + "nsw" | "nuw" | "reassoc" | "contract" | "arcp" | "afn" | "fast" | "nnan" + | "ninf" | "nsz" | "exact" | "disjoint" => { + flag_tokens.push(first); + rest2 = r; + } + _ => break, + } + } + let parts = split_top_level(rest2); + if parts.len() != 2 { + bail!("bad binary op `{op}` operands: {rest}"); + } + let (ty_tok, atok) = ty_and_val(&parts[0])?; + let ty = basic_type(self.ctx, ty_tok)?; + let a = self.val(ty, atok)?; + let b2 = self.val(ty, parts[1].trim())?; + let nm = name; + let out: BasicValueEnum = match op_base { + "add" => self + .builder + .build_int_add(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "sub" => self + .builder + .build_int_sub(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "mul" => self + .builder + .build_int_mul(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "sdiv" => self + .builder + .build_int_signed_div(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "udiv" => self + .builder + .build_int_unsigned_div(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "srem" => self + .builder + .build_int_signed_rem(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "urem" => self + .builder + .build_int_unsigned_rem(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "and" => self + .builder + .build_and(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "or" => self + .builder + .build_or(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "xor" => self + .builder + .build_xor(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "shl" => self + .builder + .build_left_shift(a.into_int_value(), b2.into_int_value(), nm) + .map_err(be)? + .into(), + "lshr" => self + .builder + .build_right_shift(a.into_int_value(), b2.into_int_value(), false, nm) + .map_err(be)? + .into(), + "ashr" => self + .builder + .build_right_shift(a.into_int_value(), b2.into_int_value(), true, nm) + .map_err(be)? + .into(), + "fadd" => self + .builder + .build_float_add(a.into_float_value(), b2.into_float_value(), nm) + .map_err(be)? + .into(), + "fsub" => self + .builder + .build_float_sub(a.into_float_value(), b2.into_float_value(), nm) + .map_err(be)? + .into(), + "fmul" => self + .builder + .build_float_mul(a.into_float_value(), b2.into_float_value(), nm) + .map_err(be)? + .into(), + "fdiv" => self + .builder + .build_float_div(a.into_float_value(), b2.into_float_value(), nm) + .map_err(be)? + .into(), + "frem" => self + .builder + .build_float_rem(a.into_float_value(), b2.into_float_value(), nm) + .map_err(be)? + .into(), + other => bail!("unknown instruction `{other}`"), + }; + apply_flags(out.as_instruction_value(), &flag_tokens); + Ok(out) + } + + fn finish(mut self) -> Result { + // Phi incomings resolve against the COMPLETE value map — no + // placeholders here; an unknown register at this point is a bug. + for (phi, ty, incs) in std::mem::take(&mut self.pending_phis) { + for (vtok, btok) in incs { + let block = *self + .blocks + .get(&btok) + .ok_or_else(|| anyhow!("phi references unknown block %{btok}"))?; + let v = if vtok.starts_with('%') { + *self + .vals + .get(&vtok) + .ok_or_else(|| anyhow!("phi references undefined register {vtok}"))? + } else { + constant(self.ctx, self.module, ty, &vtok)? + }; + phi.add_incoming(&[(&v as &dyn BasicValue, block)]); + } + } + if let Some(name) = self.placeholders.keys().next() { + bail!("register {name} was used but never defined"); + } + Ok(self.count) + } +} + +/// Replace every use of a placeholder with the real definition. +fn rauw<'ctx>(ph: BasicValueEnum<'ctx>, real: BasicValueEnum<'ctx>) { + match (ph, real) { + (BasicValueEnum::IntValue(a), BasicValueEnum::IntValue(b)) => a.replace_all_uses_with(b), + (BasicValueEnum::FloatValue(a), BasicValueEnum::FloatValue(b)) => { + a.replace_all_uses_with(b) + } + (BasicValueEnum::PointerValue(a), BasicValueEnum::PointerValue(b)) => { + a.replace_all_uses_with(b) + } + // Type mismatch between forward use and definition: leave the + // placeholder in place — the verifier reports it with context. + _ => {} + } +} + +// --------------------------------------------------------------------------- +// Small helpers +// --------------------------------------------------------------------------- + +fn be(e: inkwell::builder::BuilderError) -> anyhow::Error { + anyhow!("builder error: {e}") +} + +fn unquote(s: &str) -> String { + s.trim_matches('"').to_string() +} + +/// Find the matching `)` for the `(` at `open` in `s`. +fn rmatch_paren(s: &str, open: usize) -> Result { + let mut depth = 0usize; + for (i, c) in s.char_indices().skip(open) { + match c { + '(' => depth += 1, + ')' => { + depth -= 1; + if depth == 0 { + return Ok(i); + } + } + _ => {} + } + } + bail!("unbalanced parens") +} + +/// Split on top-level commas (not inside (), [], <>, {}). +fn split_top_level(s: &str) -> Vec { + let mut out = Vec::new(); + let mut depth = 0i32; + let mut cur = String::new(); + for c in s.chars() { + match c { + '(' | '[' | '{' | '<' => { + depth += 1; + cur.push(c); + } + ')' | ']' | '}' | '>' => { + depth -= 1; + cur.push(c); + } + ',' if depth == 0 => { + out.push(cur.trim().to_string()); + cur = String::new(); + } + _ => cur.push(c), + } + } + if !cur.trim().is_empty() { + out.push(cur.trim().to_string()); + } + out +} + +/// `"i64 %r5"` -> `("i64", "%r5")`, honoring types with spaces (`[4 x i8]`, +/// `<4 x i32>`) and bracketed values (`<4 x i32> `): the +/// TYPE is parsed greedily from the left (balanced brackets, then trailing +/// `*`s), the remainder is the value. +fn ty_and_val(s: &str) -> Result<(&str, &str)> { + let s = s.trim(); + let bytes = s.as_bytes(); + let ty_end = if bytes[0] == b'[' || bytes[0] == b'<' || bytes[0] == b'{' { + let (open, close) = match bytes[0] { + b'[' => (b'[', b']'), + b'<' => (b'<', b'>'), + _ => (b'{', b'}'), + }; + let mut depth = 0usize; + let mut end = 0usize; + for (i, &c) in bytes.iter().enumerate() { + if c == open { + depth += 1; + } else if c == close { + depth -= 1; + if depth == 0 { + end = i + 1; + break; + } + } + } + if end == 0 { + bail!("unbalanced type brackets in `{s}`"); + } + // Trailing pointer stars (pre-opaque spellings). + while end < bytes.len() && bytes[end] == b'*' { + end += 1; + } + end + } else { + s.find(' ') + .ok_or_else(|| anyhow!("expected `type value`, got `{s}`"))? + }; + Ok((s[..ty_end].trim(), s[ty_end..].trim())) +} + +fn strip_label(s: &str) -> Result<&str> { + s.trim() + .strip_prefix("label %") + .map(str::trim) + .ok_or_else(|| anyhow!("expected `label %...`, got `{s}`")) +} + +fn basic_type<'ctx>(ctx: &'ctx Context, tok: &str) -> Result> { + let tok = tok.trim(); + Ok(match tok { + "double" => ctx.f64_type().into(), + "float" => ctx.f32_type().into(), + "i64" => ctx.i64_type().into(), + "i32" => ctx.i32_type().into(), + "i16" => ctx.i16_type().into(), + "i8" => ctx.i8_type().into(), + "i1" => ctx.bool_type().into(), + "i128" => ctx.i128_type().into(), + "ptr" => ctx.ptr_type(AddressSpace::default()).into(), + _ => { + // `[N x T]` + if let Some(body) = tok.strip_prefix('[').and_then(|t| t.strip_suffix(']')) { + let (n, elem) = body + .split_once(" x ") + .ok_or_else(|| anyhow!("bad array type `{tok}`"))?; + let n: u32 = n.trim().parse()?; + let elem_ty = basic_type(ctx, elem)?; + return Ok(elem_ty.array_type(n).into()); + } + // `` (SIMD in expr/channel.rs) + if let Some(body) = tok.strip_prefix('<').and_then(|t| t.strip_suffix('>')) { + let (n, elem) = body + .split_once(" x ") + .ok_or_else(|| anyhow!("bad vector type `{tok}`"))?; + let n: u32 = n.trim().parse()?; + return Ok(match basic_type(ctx, elem)? { + BasicTypeEnum::IntType(t) => t.vec_type(n).into(), + BasicTypeEnum::FloatType(t) => t.vec_type(n).into(), + BasicTypeEnum::PointerType(t) => t.vec_type(n).into(), + other => bail!("unsupported vector element {other:?}"), + }); + } + // Pre-opaque pointer spellings (`i8*`, `double**`, `(sig)*`) all + // collapse to `ptr` under LLVM 15+ semantics. + if tok.ends_with('*') { + return Ok(ctx.ptr_type(AddressSpace::default()).into()); + } + bail!("unknown type `{tok}`") + } + }) +} + +fn fn_type_of<'ctx>( + ctx: &'ctx Context, + ret_tok: &str, + params: &[inkwell::types::BasicMetadataTypeEnum<'ctx>], +) -> Result> { + Ok(match ret_tok { + "void" => ctx.void_type().fn_type(params, false), + _ => basic_type(ctx, ret_tok)?.fn_type(params, false), + }) +} + +/// Function type for an indirect call site. `sig_str` is either just the +/// return type (`double`) or `RET (T1, T2, ...)`; when only the return type +/// is present the parameter types are taken from the argument list. +fn indirect_fn_type<'ctx>( + ctx: &'ctx Context, + sig_str: &str, + arg_types: &[inkwell::types::BasicMetadataTypeEnum<'ctx>], +) -> Result> { + let sig_str = sig_str.trim(); + if let Some(open) = sig_str.find('(') { + let ret_tok = sig_str[..open].trim(); + let close = rmatch_paren(sig_str, open)?; + let params_str = &sig_str[open + 1..close]; + let mut params: Vec = Vec::new(); + let mut varargs = false; + for p in split_top_level(params_str) { + if p.trim() == "..." { + varargs = true; + continue; + } + params.push(basic_type(ctx, p.trim())?.into()); + } + Ok(match ret_tok { + "void" => ctx.void_type().fn_type(¶ms, varargs), + _ => basic_type(ctx, ret_tok)?.fn_type(¶ms, varargs), + }) + } else { + fn_type_of(ctx, sig_str, arg_types) + } +} + +fn constant<'ctx>( + ctx: &'ctx Context, + module: &Module<'ctx>, + ty: BasicTypeEnum<'ctx>, + tok: &str, +) -> Result> { + if let Some(g) = tok.strip_prefix('@') { + let name = unquote(g); + if let Some(f) = module.get_function(&name) { + return Ok(f.as_global_value().as_pointer_value().into()); + } + if let Some(gv) = module.get_global(&name) { + return Ok(gv.as_pointer_value().into()); + } + bail!("reference to unknown global @{name}"); + } + Ok(match tok { + "null" => ctx.ptr_type(AddressSpace::default()).const_null().into(), + "undef" => match ty { + BasicTypeEnum::FloatType(t) => t.get_undef().into(), + BasicTypeEnum::IntType(t) => t.get_undef().into(), + BasicTypeEnum::PointerType(t) => t.get_undef().into(), + other => bail!("undef of unsupported type {other:?}"), + }, + "poison" => match ty { + BasicTypeEnum::FloatType(t) => t.get_poison().into(), + BasicTypeEnum::IntType(t) => t.get_poison().into(), + BasicTypeEnum::PointerType(t) => t.get_poison().into(), + other => bail!("poison of unsupported type {other:?}"), + }, + "true" => ctx.bool_type().const_int(1, false).into(), + "false" => ctx.bool_type().const_int(0, false).into(), + "zeroinitializer" => match ty { + BasicTypeEnum::FloatType(t) => t.const_zero().into(), + BasicTypeEnum::IntType(t) => t.const_zero().into(), + BasicTypeEnum::ArrayType(t) => t.const_zero().into(), + BasicTypeEnum::PointerType(t) => t.const_null().into(), + other => bail!("zeroinitializer of unsupported type {other:?}"), + }, + _ => match ty { + BasicTypeEnum::FloatType(t) => { + // LLVM hex-float form is raw IEEE-754 bits — exactly how + // NaN-boxed constants must survive. + if let Some(hex) = tok.strip_prefix("0x") { + let bits = u64::from_str_radix(hex, 16) + .map_err(|_| anyhow!("bad hex float `{tok}`"))?; + t.const_float(f64::from_bits(bits)).into() + } else { + t.const_float( + tok.parse::() + .map_err(|_| anyhow!("bad float `{tok}`"))?, + ) + .into() + } + } + BasicTypeEnum::IntType(t) => { + let v: i128 = tok.parse().map_err(|_| anyhow!("bad integer `{tok}`"))?; + t.const_int(v as u64, v < 0).into() + } + other => bail!("cannot materialize `{tok}` as {other:?}"), + }, + }) +} + +fn int_pred(p: &str) -> Result { + Ok(match p { + "eq" => IntPredicate::EQ, + "ne" => IntPredicate::NE, + "slt" => IntPredicate::SLT, + "sle" => IntPredicate::SLE, + "sgt" => IntPredicate::SGT, + "sge" => IntPredicate::SGE, + "ult" => IntPredicate::ULT, + "ule" => IntPredicate::ULE, + "ugt" => IntPredicate::UGT, + "uge" => IntPredicate::UGE, + other => bail!("unknown icmp predicate `{other}`"), + }) +} + +fn float_pred(p: &str) -> Result { + Ok(match p { + "oeq" => FloatPredicate::OEQ, + "one" => FloatPredicate::ONE, + "olt" => FloatPredicate::OLT, + "ole" => FloatPredicate::OLE, + "ogt" => FloatPredicate::OGT, + "oge" => FloatPredicate::OGE, + "ord" => FloatPredicate::ORD, + "ueq" => FloatPredicate::UEQ, + "une" => FloatPredicate::UNE, + "ult" => FloatPredicate::ULT, + "ule" => FloatPredicate::ULE, + "ugt" => FloatPredicate::UGT, + "uge" => FloatPredicate::UGE, + "uno" => FloatPredicate::UNO, + other => bail!("unknown fcmp predicate `{other}`"), + }) +} + +fn add_enum_attr(ctx: &Context, func: FunctionValue<'_>, name: &str) { + let kind = inkwell::attributes::Attribute::get_named_enum_kind_id(name); + if kind != 0 { + let attr = ctx.create_enum_attribute(kind, 0); + func.add_attribute(inkwell::attributes::AttributeLoc::Function, attr); + } +} + +fn set_alignment_if_any(inst: Option>, rest: &str) { + if let (Some(inst), Some(idx)) = (inst, rest.rfind(", align ")) { + if let Ok(align) = rest[idx + ", align ".len()..].trim().parse::() { + let _ = inst.set_alignment(align); + } + } +} + +fn apply_flags(inst: Option>, flags: &[&str]) { + let Some(inst) = inst else { return }; + let mut fmf: u32 = 0; + for f in flags { + match *f { + "reassoc" => fmf |= llvm_sys::LLVMFastMathAllowReassoc, + "contract" => fmf |= llvm_sys::LLVMFastMathAllowContract, + "arcp" => fmf |= llvm_sys::LLVMFastMathAllowReciprocal, + "afn" => fmf |= llvm_sys::LLVMFastMathApproxFunc, + "nnan" => fmf |= llvm_sys::LLVMFastMathNoNaNs, + "ninf" => fmf |= llvm_sys::LLVMFastMathNoInfs, + "nsz" => fmf |= llvm_sys::LLVMFastMathNoSignedZeros, + "fast" => fmf |= llvm_sys::LLVMFastMathAll, + "nsw" => unsafe { + llvm_sys::core::LLVMSetNSW(inst.as_value_ref(), 1); + }, + "nuw" => unsafe { + llvm_sys::core::LLVMSetNUW(inst.as_value_ref(), 1); + }, + "exact" => unsafe { + llvm_sys::core::LLVMSetExact(inst.as_value_ref(), 1); + }, + _ => {} + } + } + if fmf != 0 { + unsafe { llvm_sys::core::LLVMSetFastMathFlags(inst.as_value_ref(), fmf) }; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn split_corpus(text: &str) -> (String, Vec) { + let mut skeleton = String::new(); + let mut fns = Vec::new(); + let mut cur: Option = None; + for line in text.lines() { + if line.starts_with("define ") { + cur = Some(String::new()); + } + match cur.as_mut() { + Some(f) => { + f.push_str(line); + f.push('\n'); + if line == "}" { + fns.push(cur.take().unwrap()); + } + } + None => { + skeleton.push_str(line); + skeleton.push('\n'); + } + } + } + (skeleton, fns) + } + + /// Every function in a real perry-emitted corpus file must construct + /// natively and pass the LLVM verifier. This is the reader's primary + /// gate: a form it cannot express fails here, not in a user build. + fn corpus_roundtrip(path: &str) { + let Ok(text) = std::fs::read_to_string(path) else { + // Corpus artifacts live on the experiment branch; absence is a + // skip (other branches), not a failure. + eprintln!("corpus file {path} not present; skipping"); + return; + }; + let (skeleton, fns) = split_corpus(&text); + let ctx = Context::create(); + let module = crate::inprocess::parse_ir_text(&ctx, &skeleton, "corpus_skel") + .expect("skeleton parses"); + for f in &fns { + predeclare_function_from_text(&ctx, &module, f) + .unwrap_or_else(|e| panic!("predeclare: {e:#}")); + } + let mut n = 0usize; + for f in &fns { + n += add_function_from_text(&ctx, &module, f).unwrap_or_else(|e| panic!("{e:#}")); + } + assert!( + n > 1000, + "expected a real corpus, built only {n} instructions" + ); + module + .verify() + .unwrap_or_else(|e| panic!("verifier rejected native module:\n{}", e.to_string())); + } + + #[test] + fn corpus_spike() { + corpus_roundtrip(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../experiments/llvm-inprocess-spike/spike_text.ll" + )); + } + + #[test] + fn corpus_batch_kernel() { + corpus_roundtrip(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../experiments/llvm-inprocess-spike/batch_kernel.ll" + )); + } } diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs index aaf7de9e31..40db63db1c 100644 --- a/crates/perry-codegen/src/native_emit.rs +++ b/crates/perry-codegen/src/native_emit.rs @@ -55,8 +55,31 @@ pub fn native_mode() -> NativeMode { fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result> { let skeleton = llmod.skeleton_ir(); let module = crate::inprocess::parse_ir_text(context, &skeleton, "perry_native_module")?; - let mut instructions = 0usize; let funcs = llmod.deduped_function_refs(); + // Pre-declare every define: calls to functions defined later in the + // module (and closure address captures) are module-scope forward + // references. Only the one-line header is synthesized here; bodies are + // read once, below. + for f in &funcs { + let param_str = f + .params + .iter() + .map(|(t, n)| format!("{t} {n}")) + .collect::>() + .join(", "); + let linkage = if f.linkage.is_empty() { + String::new() + } else { + format!("{} ", f.linkage) + }; + let header = format!( + "define {}{} @{}({}) {{", + linkage, f.return_type, f.name, param_str + ); + crate::dialect::predeclare_function_from_text(context, &module, &header) + .map_err(|e| anyhow!("pre-declaring @{}: {}", f.name, e))?; + } + let mut instructions = 0usize; for f in &funcs { let fn_text = f.to_ir(); instructions += crate::dialect::add_function_from_text(context, &module, &fn_text) From c5339b2d96973b4418fda86ea699725b57ad0209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 10:44:23 +0200 Subject: [PATCH 08/26] exp: object-byte diff verdict, callsite attrs, textual block order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Diff mode's verdict is now emitted-object bytes (construction-time constant folding makes pre-opt print comparison structurally impossible; bytes are ground truth, pre-opt IR dumps remain the localization artifact). Reader keeps textual block order under forward references (move_after), applies returns_twice callsite groups, derives call types from callsites. Result: spike.ts arms emit BYTE-IDENTICAL objects; batch.ts differs by 336 bytes of tighter native-arm code (register-allocation divergence downstream of pre-folded constants — all pre-opt diff classes are folding, none are construction bugs). Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/dialect.rs | 30 +++++ crates/perry-codegen/src/native_emit.rs | 116 +++++++------------ experiments/llvm-inprocess-spike/batch_ab.sh | 2 +- 3 files changed, 72 insertions(+), 76 deletions(-) diff --git a/crates/perry-codegen/src/dialect.rs b/crates/perry-codegen/src/dialect.rs index e3f9aeed2f..94603cda61 100644 --- a/crates/perry-codegen/src/dialect.rs +++ b/crates/perry-codegen/src/dialect.rs @@ -93,6 +93,10 @@ struct FnReader<'ctx, 'm> { /// when the real definition arrives — the same strategy LLVM's own /// `.ll` parser uses. placeholders: HashMap>, + /// Most recently *entered* (label line) block, used to keep the + /// function's block order equal to textual order even when a forward + /// branch created the block object earlier. + last_entered: Option>, positioned: bool, count: usize, } @@ -233,6 +237,7 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { vals, pending_phis: Vec::new(), placeholders: HashMap::new(), + last_entered: None, positioned: false, count: 0, }) @@ -249,6 +254,14 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { fn enter_block(&mut self, label: &str) -> Result<()> { let b = self.block(label); + if let Some(prev) = self.last_entered { + // A forward branch may have created this block before blocks + // that textually precede it; re-anchor to textual order (block + // order is semantically free but affects layout and makes the + // diff harness exact). + let _ = b.move_after(prev); + } + self.last_entered = Some(b); self.builder.position_at_end(b); self.positioned = true; Ok(()) @@ -612,6 +625,10 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { let callee = &after[..paren]; let close = rmatch_paren(after, paren)?; let args_str = &after[paren + 1..close]; + // Trailing callsite attribute-group ref. Only `#0` (returns_twice, + // on setjmp calls) exists in the dialect; the declare carries it too, + // so this is fidelity, not correctness. + let trailing_attr = after[close + 1..].trim(); let mut args: Vec = Vec::new(); let mut arg_types: Vec = Vec::new(); @@ -646,6 +663,19 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { .builder .build_indirect_call(fn_ty, callee_ptr, &args, name) .map_err(be)?; + match trailing_attr { + "" => {} + "#0" => { + let kind = inkwell::attributes::Attribute::get_named_enum_kind_id("returns_twice"); + if kind != 0 { + site.add_attribute( + inkwell::attributes::AttributeLoc::Function, + self.ctx.create_enum_attribute(kind, 0), + ); + } + } + other => bail!("unknown callsite attribute `{other}`"), + } match site.try_as_basic_value() { inkwell::values::ValueKind::Basic(v) => Ok(Some(v)), _ => Ok(None), diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs index 40db63db1c..bd18773948 100644 --- a/crates/perry-codegen/src/native_emit.rs +++ b/crates/perry-codegen/src/native_emit.rs @@ -122,99 +122,65 @@ pub fn compile_module_native(llmod: &LlModule, target: Option<&str>) -> Result) -> Result> { let text = llmod.to_ir(); let ctx_text = Context::create(); let m_text = crate::inprocess::parse_ir_text(&ctx_text, &text, "perry_diff_text")?; + let (effective_target, args) = plan_for(llmod, target); let ctx_native = Context::create(); let native = build_native_module(&ctx_native, llmod); - match native { Err(e) => { eprintln!("perry: [ir-diff] native construction FAILED (text arm still used): {e:#}"); + crate::inprocess::optimize_and_emit_module(&m_text, &effective_target, &args) } Ok(m_native) => { - let pa = normalize_print(&m_text.print_to_string().to_string()); - let pb = normalize_print(&m_native.print_to_string().to_string()); - if pa == pb { + // Capture pre-opt prints BEFORE optimization mutates the modules; + // they are the localization artifact when bytes mismatch. + let dump_dir = std::env::var("PERRY_LLVM_DIFF_DIR").ok(); + let (pre_text, pre_native) = if dump_dir.is_some() { + ( + m_text.print_to_string().to_string(), + m_native.print_to_string().to_string(), + ) + } else { + (String::new(), String::new()) + }; + let bytes_native = + crate::inprocess::optimize_and_emit_module(&m_native, &effective_target, &args)?; + let bytes_text = + crate::inprocess::optimize_and_emit_module(&m_text, &effective_target, &args)?; + if bytes_text == bytes_native { eprintln!( - "perry: [ir-diff] OK — native construction matches text parse ({} lines)", - pa.lines().count() + "perry: [ir-diff] OK — native and text arms emit byte-identical objects \ + ({} bytes)", + bytes_text.len() ); } else { - report_diff(&pa, &pb); - if let Ok(dir) = std::env::var("PERRY_LLVM_DIFF_DIR") { - let _ = std::fs::create_dir_all(&dir); - let _ = std::fs::write(format!("{dir}/text_arm.ll"), &pa); - let _ = std::fs::write(format!("{dir}/native_arm.ll"), &pb); + eprintln!( + "perry: [ir-diff] MISMATCH — object bytes differ (text {} vs native {}); \ + set PERRY_LLVM_DIFF_DIR to dump both arms' pre-opt IR", + bytes_text.len(), + bytes_native.len() + ); + if let Some(dir) = &dump_dir { + let _ = std::fs::create_dir_all(dir); + let _ = std::fs::write(format!("{dir}/text_arm.ll"), &pre_text); + let _ = std::fs::write(format!("{dir}/native_arm.ll"), &pre_native); + let _ = std::fs::write(format!("{dir}/text_arm.o"), &bytes_text); + let _ = std::fs::write(format!("{dir}/native_arm.o"), &bytes_native); eprintln!("perry: [ir-diff] arms dumped under {dir}"); } } + Ok(bytes_text) } } - - let (effective_target, args) = plan_for(llmod, target); - crate::inprocess::optimize_and_emit_module(&m_text, &effective_target, &args) -} - -/// Normalization limited to the classes catalogued in -/// `docs/llvm-inprocess-experiment.md` (attribute-group *numbering* and -/// header trivia). Everything else must match exactly — both arms come out -/// of the same LLVM printer. -fn normalize_print(printed: &str) -> String { - let mut out = String::with_capacity(printed.len()); - for line in printed.lines() { - if line.starts_with("; ModuleID") || line.starts_with("source_filename") { - continue; - } - // `#12` group ids may be assigned in a different order by the two - // construction orders; the *contents* of the groups still compare - // via the `attributes` lines themselves (with ids blanked). - let mut norm = String::with_capacity(line.len()); - let mut chars = line.chars().peekable(); - while let Some(c) = chars.next() { - if c == '#' && chars.peek().is_some_and(|d| d.is_ascii_digit()) { - while chars.peek().is_some_and(|d| d.is_ascii_digit()) { - chars.next(); - } - norm.push_str("#N"); - } else { - norm.push(c); - } - } - out.push_str(&norm); - out.push('\n'); - } - out -} - -fn report_diff(pa: &str, pb: &str) { - let a: Vec<&str> = pa.lines().collect(); - let b: Vec<&str> = pb.lines().collect(); - let mut shown = 0; - let mut i = 0; - let mut j = 0; - eprintln!( - "perry: [ir-diff] MISMATCH — native construction diverges from text parse \ - ({} vs {} lines); first divergences:", - a.len(), - b.len() - ); - // Naive sync-on-equal walk: enough to *locate* divergence; the dumped - // arms (PERRY_LLVM_DIFF_DIR) are the real investigation artifact. - while i < a.len() && j < b.len() && shown < 12 { - if a[i] == b[j] { - i += 1; - j += 1; - continue; - } - eprintln!(" text : {}", a[i]); - eprintln!(" native: {}", b[j]); - shown += 1; - i += 1; - j += 1; - } } diff --git a/experiments/llvm-inprocess-spike/batch_ab.sh b/experiments/llvm-inprocess-spike/batch_ab.sh index 5e6e231843..0bc79a8c95 100755 --- a/experiments/llvm-inprocess-spike/batch_ab.sh +++ b/experiments/llvm-inprocess-spike/batch_ab.sh @@ -32,7 +32,7 @@ for t in $(ls "$WT"/test-files/test_gap_*.ts | sort); do gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.t" >"$WORK/$name.t.compile" 2>&1 ct=$? if [ "$MODE" = "flag" ]; then - PERRY_LLVM_INPROCESS=1 gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 + PERRY_LLVM_INPROCESS=${INPROCESS_VALUE:-1} gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 cp=$? # Liveness: the arm must have announced the in-process backend. if [ $cp -eq 0 ] && ! grep -q "in-process LLVM backend active" "$WORK/$name.p.compile"; then From ca4800fb4f37ca37f6ffbbad2bb43c8ee3f9d764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 10:48:20 +0200 Subject: [PATCH 09/26] exp: native mode handles multi-module compiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes from the gap-corpus slice: parse the explicit 'external' linkage keyword init_body defines carry, and parse the skeleton together with synthesized declares for every define — skeleton globals reference defined wrapper functions (extern-closure descriptors), and the declares double as the module-scope forward-reference mechanism, replacing the separate pre-declare loop. dynamic-import multi-module test now compiles natively with output identical to the text arm. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/dialect.rs | 21 +++++++++++------ crates/perry-codegen/src/native_emit.rs | 30 +++++++++---------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/crates/perry-codegen/src/dialect.rs b/crates/perry-codegen/src/dialect.rs index 94603cda61..e824e06876 100644 --- a/crates/perry-codegen/src/dialect.rs +++ b/crates/perry-codegen/src/dialect.rs @@ -123,13 +123,20 @@ fn parse_header(header: &str) -> Result { let mut toks = rest.split_whitespace().peekable(); let mut linkage = None; if let Some(&t) = toks.peek() { - if t == "internal" || t == "private" { - linkage = Some(if t == "internal" { - Linkage::Internal - } else { - Linkage::Private - }); - toks.next(); + match t { + "internal" => { + linkage = Some(Linkage::Internal); + toks.next(); + } + "private" => { + linkage = Some(Linkage::Private); + toks.next(); + } + // Explicit default linkage (init_body functions carry it). + "external" => { + toks.next(); + } + _ => {} } } let ret_tok = toks diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs index bd18773948..9a8130bf1f 100644 --- a/crates/perry-codegen/src/native_emit.rs +++ b/crates/perry-codegen/src/native_emit.rs @@ -53,32 +53,24 @@ pub fn native_mode() -> NativeMode { /// Build the module natively: parse the skeleton text, then construct every /// function body through the C API via the dialect reader. fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result> { - let skeleton = llmod.skeleton_ir(); - let module = crate::inprocess::parse_ir_text(context, &skeleton, "perry_native_module")?; + let mut skeleton = llmod.skeleton_ir(); let funcs = llmod.deduped_function_refs(); - // Pre-declare every define: calls to functions defined later in the - // module (and closure address captures) are module-scope forward - // references. Only the one-line header is synthesized here; bodies are - // read once, below. + // Append a declare for every define: the skeleton's globals can + // reference defined functions (extern-closure descriptors hold wrapper + // function addresses), and calls to functions defined later in the + // module are module-scope forward references. Parsing declares with the + // define's real signature covers both; `declare_from_header` upgrades + // linkage when the body is read. for f in &funcs { - let param_str = f + let tys = f .params .iter() - .map(|(t, n)| format!("{t} {n}")) + .map(|(t, _)| t.to_string()) .collect::>() .join(", "); - let linkage = if f.linkage.is_empty() { - String::new() - } else { - format!("{} ", f.linkage) - }; - let header = format!( - "define {}{} @{}({}) {{", - linkage, f.return_type, f.name, param_str - ); - crate::dialect::predeclare_function_from_text(context, &module, &header) - .map_err(|e| anyhow!("pre-declaring @{}: {}", f.name, e))?; + skeleton.push_str(&format!("declare {} @{}({})\n", f.return_type, f.name, tys)); } + let module = crate::inprocess::parse_ir_text(context, &skeleton, "perry_native_module")?; let mut instructions = 0usize; for f in &funcs { let fn_text = f.to_ir(); From b752536eed9e7a0cf79ece20cee799a6440ea3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 10:49:56 +0200 Subject: [PATCH 10/26] exp: document Phase 2 native construction in the experiment write-up Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- docs/llvm-inprocess-experiment.md | 67 ++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/docs/llvm-inprocess-experiment.md b/docs/llvm-inprocess-experiment.md index fd570f6da0..9710792c5a 100644 --- a/docs/llvm-inprocess-experiment.md +++ b/docs/llvm-inprocess-experiment.md @@ -1,10 +1,67 @@ # In-process LLVM backend experiment (`exp/llvm-inprocess`) -**Status: Phase 0 complete — feasibility CONFIRMED, with a byte-identical -parity result.** A feature-gated, flag-gated in-process transport -(`PERRY_LLVM_INPROCESS=1`) is implemented on this branch. The default path is -untouched: the default build links no LLVM and compiles `.ll` through -`clang -c` exactly as before. +**Status: Phase 0 complete (transport, byte-identical) and Phase 2 landed +opt-in (native construction — module-scale IR text no longer exists under +`PERRY_LLVM_INPROCESS=native`).** The default path is untouched: the default +build links no LLVM and compiles `.ll` through `clang -c` exactly as before. + +## Phase 2: native construction (`=native` / `=diff`) + +The owner's directive after Phase 0: the lever is not the transport, it is +making generated `.ll` text *optional*. Two audits drove the design (both +reproduced below): 96.4% of instruction emission (6,097 call sites) already +flows through ~40 semantic methods on `LlBlock`; the bypasses are 89 +`emit_raw` sites, the `LlFunction` entry-splice mechanism (136 sites), and +`to_ir`'s post-render passes (ret rewrites, setjmp volatile promotion). A +grammar census over two real corpora (9,110+ instructions) bounded the +dialect: ~30 opcodes, scalar + `[N x T]` types, six operand forms — plus two +traps a naive builder dies on: **non-phi cross-block forward references** +(the `idispatch` tower) and phis where 73% of incomings are forward. + +Architecture (deliberately different from the brief's instruction-level +builder-trait): the port point is the **finalized function**, not the emit +stream. `LlFunction::to_ir()` output — including entry-alloca hoists, +boundary splices, return-site rewrites, and volatile promotion, so those +transforms keep exactly one implementation — is consumed per function by a +bounded dialect reader (`dialect.rs`) that constructs it through the C API: +typed operand resolution against a per-function `%name` map, +placeholder-RAUW for forward references (LLParser's own strategy), deferred +phi incomings, callsite-derived call types (opaque-pointer semantics, +measured: a direct call's function type is the *callsite's*, not the +declare's), pre-declaration of all module-internal defines. Only the module +*skeleton* (globals, declares, attribute groups — a few KB) is still parsed +as text. Per-function text remains transient scaffolding (dropped +immediately); the follow-up that removes it is typed `LlInst` variants +inside `LlBlock` behind the same reader interface, migrating the ~40 +semantic methods opcode-by-opcode with `=diff` as the gate. + +Results so far: + +- Corpus gate (unit tests `dialect::tests::corpus_*`): every function of + both corpora constructs natively and passes the LLVM verifier. +- `spike.ts`: text-parsed arm and natively-constructed arm emit + **byte-identical objects**; the native-mode binary matches the pinned Node + oracle. +- `batch.ts`: all pre-opt divergences are one class — the C-API builder + constant-folds at construction (`zext i1 false`, `select i1 false`, + constant GEPs) — which is why `=diff`'s verdict is **emitted object + bytes**, not pre-opt prints. The arms' objects differ by 336 bytes of + *tighter* native-arm code (register-allocation divergence downstream of + pre-folded input; same symbols, verified at the disassembly level to be + layout/regalloc, not semantics). +- Behavior: 26-test gap-corpus slice under `=native` (one binary, flag-only + A/B, liveness asserted): first pass 25/25 byte-identical outputs with one + compile failure — a multi-module test that exposed two reader bugs + (explicit `external` linkage keyword; skeleton globals referencing defined + wrapper functions, fixed by parsing the skeleton with synthesized declares + for every define). After the fix the failing test compiles natively with + identical output; the full slice re-run is recorded in the tracking issue. + +Modes: `PERRY_LLVM_INPROCESS=1` transport (parse whole text in-process), +`=native` construction, `=diff` both-arms harness (returns the text arm's +object; prints `[ir-diff] OK/MISMATCH`; `PERRY_LLVM_DIFF_DIR` dumps both +arms' pre-opt IR + objects). All values share the env var already keyed into +both caches. Unit-split and `emit_ir_only` paths fall through to transport. Companion artifacts: From 6327383020a4caaa424066ddb4f3938d2f55b20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 10:50:23 +0200 Subject: [PATCH 11/26] exp: correct perry-codegen line-count claim (audit-measured 189k, not 340k) Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- docs/llvm-inprocess-experiment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/llvm-inprocess-experiment.md b/docs/llvm-inprocess-experiment.md index 9710792c5a..d8ab0d3a33 100644 --- a/docs/llvm-inprocess-experiment.md +++ b/docs/llvm-inprocess-experiment.md @@ -231,7 +231,7 @@ suite green under the flag. The brief's Phase 1 places the seam "between lowering and IR construction" with two builder implementations. The codebase disagrees: perry-codegen is -~340k lines of *string-oriented* emission (`LlModule` holds functions as +~189k lines of *string-oriented* emission (`LlModule` holds functions as rendered text lines), so an instruction-level builder interface is not a seam, it is a rewrite of the whole emitter. The seam this codebase already has — and documents as such — is `compile_ll_to_object(ll_text) -> Vec`. From 2f2e17e6d27abe6917e051d660cebc44d4836805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 11:34:56 +0200 Subject: [PATCH 12/26] exp: typed instruction storage (LlInst) behind the emit choke point LlBlock stores Vec instead of Vec; Raw carries the pre-rendered line so zero bytes of IR change (gate: the full 528-test suite, which pins exact rendered IR). Consumers move to render_into / text_len / scan_str so typed variants need no per-line String. This is the enabling step for migrating block.rs's ~40 semantic methods off format! one opcode at a time, with =diff's object-byte verdict as the per-step gate. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/block.rs | 34 ++++++++++++++-------- crates/perry-codegen/src/function.rs | 6 ++-- crates/perry-codegen/src/inst.rs | 42 ++++++++++++++++++++++++++++ crates/perry-codegen/src/lib.rs | 1 + 4 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 crates/perry-codegen/src/inst.rs diff --git a/crates/perry-codegen/src/block.rs b/crates/perry-codegen/src/block.rs index 26614a2ea1..6795bebb67 100644 --- a/crates/perry-codegen/src/block.rs +++ b/crates/perry-codegen/src/block.rs @@ -126,7 +126,7 @@ impl RegCounter { pub struct LlBlock { pub label: String, - instructions: Vec, + instructions: Vec, terminated: bool, counter: Rc, fp_flags: FpFlags, @@ -178,7 +178,8 @@ impl LlBlock { /// check cannot be invalidated mid-loop). Intrinsic/libm-style calls /// never enter the perry runtime, so they cannot trigger a collection. pub fn contains_gc_unsafe_call(&self) -> bool { - self.instructions.iter().any(|line| { + self.instructions.iter().any(|inst| { + let line = inst.scan_str(); let Some(pos) = line.find("call ") else { return false; }; @@ -210,7 +211,8 @@ impl LlBlock { // #6385: note stores emitted inside a setjmp-protected region so // `LlFunction::to_ir` can make the backing allocas volatile. self.counter.note_emitted(&line); - self.instructions.push(format!(" {}", line)); + self.instructions + .push(crate::inst::LlInst::Raw(format!(" {}", line))); } fn reg(&self) -> String { @@ -235,12 +237,12 @@ impl LlBlock { self.instructions.len() } - /// Iterate over the raw instruction strings (each already prefixed - /// with two leading spaces, no trailing newline). Used by - /// `LlFunction::to_ir` when it needs to splice hoisted setup into - /// the entry block at a specific boundary. - pub fn instructions_iter(&self) -> impl Iterator { - self.instructions.iter().map(|s| s.as_str()) + /// The block's instructions. Used by `LlFunction::to_ir` (entry-block + /// boundary splice) and `estimated_ir_bytes`; renders happen through + /// [`crate::inst::LlInst::render_into`] so typed variants need no + /// intermediate `String` per line. + pub fn insts(&self) -> &[crate::inst::LlInst] { + &self.instructions } // -------- Arithmetic (double) -------- @@ -963,11 +965,21 @@ impl LlBlock { pub fn to_ir(&self) -> String { let mut out = String::with_capacity( - self.instructions.iter().map(|l| l.len() + 1).sum::() + self.label.len() + 2, + self.instructions + .iter() + .map(|l| l.text_len() + 1) + .sum::() + + self.label.len() + + 2, ); out.push_str(&self.label); out.push_str(":\n"); - out.push_str(&self.instructions.join("\n")); + for (i, inst) in self.instructions.iter().enumerate() { + if i > 0 { + out.push('\n'); + } + inst.render_into(&mut out); + } out } } diff --git a/crates/perry-codegen/src/function.rs b/crates/perry-codegen/src/function.rs index 5f55a76c45..0f99f57ebe 100644 --- a/crates/perry-codegen/src/function.rs +++ b/crates/perry-codegen/src/function.rs @@ -580,7 +580,7 @@ impl LlFunction { let body: usize = self .blocks .iter() - .map(|b| b.instructions_iter().map(|i| i.len() + 1).sum::() + b.label.len() + 4) + .map(|b| b.insts().iter().map(|i| i.text_len() + 1).sum::() + b.label.len() + 4) .sum(); let allocas: usize = self.entry_allocas.iter().map(|a| a.len() + 1).sum(); body + allocas + self.name.len() + 64 @@ -651,14 +651,14 @@ impl LlFunction { .unwrap_or(0) .min(blk.instruction_count()); let mut idx = 0; - for inst in blk.instructions_iter() { + for inst in blk.insts() { if idx == boundary { for line in &self.entry_post_init_setup { ir.push_str(line); ir.push('\n'); } } - ir.push_str(inst); + inst.render_into(&mut ir); ir.push('\n'); idx += 1; } diff --git a/crates/perry-codegen/src/inst.rs b/crates/perry-codegen/src/inst.rs new file mode 100644 index 0000000000..7c9196c9c2 --- /dev/null +++ b/crates/perry-codegen/src/inst.rs @@ -0,0 +1,42 @@ +//! Typed instruction storage for `LlBlock` (exp/llvm-inprocess, Phase 2b). +//! +//! `Raw` carries a pre-rendered line exactly as the string emitter produced +//! it (two-space indent included), so introducing this enum changes zero +//! bytes of rendered IR — the migration gate. Typed variants land +//! opcode-by-opcode as `block.rs`'s semantic methods move off `format!`; +//! each variant must (1) render byte-identically to what the method +//! previously formatted and (2) be constructible natively by `dialect`'s +//! builder without a text round-trip. `PERRY_LLVM_INPROCESS=diff`'s +//! object-byte verdict gates every step; the raw-vs-typed instruction +//! counts are the migration ratchet. + +pub enum LlInst { + /// Pre-rendered instruction line, two-space indent included. + Raw(String), +} + +impl LlInst { + /// Append the rendered line (no trailing newline) to `out`. + pub fn render_into(&self, out: &mut String) { + match self { + LlInst::Raw(s) => out.push_str(s), + } + } + + /// Rendered byte length, excluding the trailing newline. Keeps + /// `estimated_ir_bytes` (codegen-unit balancing, #5391) render-free. + pub fn text_len(&self) -> usize { + match self { + LlInst::Raw(s) => s.len(), + } + } + + /// The rendered line for text-scanning consumers + /// (`contains_gc_unsafe_call`). Typed variants must answer such + /// predicates structurally rather than growing a renderer here. + pub fn scan_str(&self) -> &str { + match self { + LlInst::Raw(s) => s, + } + } +} diff --git a/crates/perry-codegen/src/lib.rs b/crates/perry-codegen/src/lib.rs index b93c4b2b17..7b1d52972f 100644 --- a/crates/perry-codegen/src/lib.rs +++ b/crates/perry-codegen/src/lib.rs @@ -15,6 +15,7 @@ pub mod ext_registry; pub mod function; #[cfg(feature = "llvm-inprocess")] pub mod inprocess; +pub mod inst; pub mod linker; pub(crate) mod loop_purity; pub(crate) mod lower_array_method; From 8d27a6c6637f8635e4299d85bb54a583b943ef17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 11:39:09 +0200 Subject: [PATCH 13/26] =?UTF-8?q?exp:=20stream=20finalized=20lines=20into?= =?UTF-8?q?=20the=20native=20builder=20=E2=80=94=20per-function=20text=20g?= =?UTF-8?q?one?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LlFunction::for_each_final_line is the single finalized-order visitor (blocks, entry splices, streamed return-site rewrites); to_ir is now that visitor plus header/brace/volatile-pass, so byte-identity is by construction (528-test gate). dialect::FnStream consumes the stream line by line; native mode materializes no per-function text except for has_try functions, whose setjmp volatile promotion needs whole-function analysis. Remaining transient text is per-LINE formatting of Raw insts — removed opcode-by-opcode as typed LlInst variants land. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/dialect.rs | 59 +++++-- crates/perry-codegen/src/function.rs | 208 +++++++++++++----------- crates/perry-codegen/src/native_emit.rs | 85 +++++++--- 3 files changed, 218 insertions(+), 134 deletions(-) diff --git a/crates/perry-codegen/src/dialect.rs b/crates/perry-codegen/src/dialect.rs index e824e06876..4aa29e04c6 100644 --- a/crates/perry-codegen/src/dialect.rs +++ b/crates/perry-codegen/src/dialect.rs @@ -44,6 +44,45 @@ pub(crate) fn predeclare_function_from_text<'ctx>( Ok(()) } +/// Streaming construction: begin from a define header, feed finalized body +/// lines one at a time (the `LlFunction::for_each_final_line` seam — no +/// per-function text materialization), then `finish`. +pub(crate) struct FnStream<'ctx, 'm> { + inner: FnReader<'ctx, 'm>, +} + +impl<'ctx, 'm> FnStream<'ctx, 'm> { + pub(crate) fn begin( + context: &'ctx Context, + module: &'m Module<'ctx>, + header: &str, + ) -> Result { + Ok(Self { + inner: FnReader::begin(context, module, header)?, + }) + } + + pub(crate) fn line(&mut self, line: &str) -> Result<()> { + let t = line.trim(); + if t.is_empty() || t.starts_with(';') || t == "}" { + return Ok(()); + } + if let Some(label) = t.strip_suffix(':') { + // Block label lines are never indented instructions. + if !line.starts_with(' ') { + return self.inner.enter_block(label); + } + } + self.inner + .instruction(t) + .with_context(|| format!("in line: {t}")) + } + + pub(crate) fn finish(self) -> Result { + self.inner.finish() + } +} + /// Parse `fn_text` (a complete `define ... { ... }`) and build it into /// `module`. Returns the number of instructions constructed. pub(crate) fn add_function_from_text<'ctx>( @@ -53,25 +92,11 @@ pub(crate) fn add_function_from_text<'ctx>( ) -> Result { let mut lines = fn_text.lines(); let header = lines.next().ok_or_else(|| anyhow!("empty function text"))?; - let mut b = FnReader::begin(context, module, header)?; + let mut stream = FnStream::begin(context, module, header)?; for line in lines { - let t = line.trim(); - if t.is_empty() || t.starts_with(';') { - continue; - } - if t == "}" { - break; - } - if let Some(label) = t.strip_suffix(':') { - // Block label lines are never indented instructions. - if !line.starts_with(' ') { - b.enter_block(label)?; - continue; - } - } - b.instruction(t).with_context(|| format!("in line: {t}"))?; + stream.line(line)?; } - b.finish() + stream.finish() } struct FnReader<'ctx, 'm> { diff --git a/crates/perry-codegen/src/function.rs b/crates/perry-codegen/src/function.rs index 0f99f57ebe..22cf6ad620 100644 --- a/crates/perry-codegen/src/function.rs +++ b/crates/perry-codegen/src/function.rs @@ -616,120 +616,132 @@ impl LlFunction { "define {}{} @{}({}){} {{\n", linkage, self.return_type, self.name, param_str, attrs ); + self.for_each_final_line::(&mut |line| { + ir.push_str(line); + ir.push('\n'); + Ok(()) + }) + .unwrap_or_else(|e| match e {}); + ir.push_str("}\n"); + + // setjmp volatile promotion (#6385). + // + // Runs LAST so it sees every instruction, including the return-site + // rewrites the visitor just streamed in. Any alloca this function + // stores into between a `setjmp` and its `longjmp` (recorded by + // `LlBlock::emit` while a try region was open) gets `volatile` loads + // and stores, which is what stops mem2reg/SROA from promoting it into + // a register that `longjmp` would revert. + if self.has_try { + let try_stores = self.reg_counter.try_region_stores(); + if !try_stores.is_empty() { + return crate::volatile_setjmp::apply_setjmp_volatile(&ir, &try_stores); + } + } + ir + } + + /// Stream every finalized BODY line of this function (block labels, + /// entry-alloca and post-init splices, instructions, return-site + /// rewrites; blank separator lines between blocks) in exactly the order + /// [`to_ir`] renders them — `to_ir` IS this visitor plus the define + /// header, closing brace, and the setjmp volatile pass (which needs + /// whole-function analysis and therefore text; native construction + /// falls back to `to_ir` for `has_try` functions). + /// + /// This is the seam the native backend consumes: per finalized line, + /// no per-function text materialization. + pub fn for_each_final_line( + &self, + sink: &mut dyn FnMut(&str) -> Result<(), E>, + ) -> Result<(), E> { + let rewrite_rets = + self.shadow_frame_slot.is_some() || !self.pre_return_void_calls.is_empty(); + let mut seq: u32 = 0; + let mut line_buf = String::new(); for (i, blk) in self.blocks.iter().enumerate() { if i > 0 { - ir.push('\n'); + sink("")?; } - // Block 0 (entry) gets two splices in its body: - // 1. `entry_allocas`: hoisted allocas + a few simple init - // sequences. These go at the very top, between the - // label line and any block instructions, so they - // dominate every reachable use in the function. - // 2. `entry_post_init_setup`: hoisted setup that must - // run AFTER the init prelude (gc_init / init_strings - // calls) so it sees the up-to-date module state. The - // splice point is `entry_init_boundary`, which the - // codegen marks immediately after emitting the - // prelude. - // Both splices are textual: we re-render the block label, - // the prefix instructions (up to the boundary), the - // post-init setup, and then the rest of the block body. - if i == 0 && (!self.entry_allocas.is_empty() || !self.entry_post_init_setup.is_empty()) - { - ir.push_str(&blk.label); - ir.push_str(":\n"); - // 1. Allocas + simple inits at the very top. + line_buf.clear(); + line_buf.push_str(&blk.label); + line_buf.push(':'); + sink(&line_buf)?; + let is_entry = i == 0; + if is_entry { for alloca in &self.entry_allocas { - ir.push_str(alloca); - ir.push('\n'); + self.emit_maybe_ret_rewritten(alloca, rewrite_rets, &mut seq, sink)?; } - // 2. Render the block instructions, with the post-init - // splice at the boundary index. - let boundary = self - .entry_init_boundary + } + let boundary = if is_entry { + self.entry_init_boundary .unwrap_or(0) - .min(blk.instruction_count()); - let mut idx = 0; - for inst in blk.insts() { - if idx == boundary { - for line in &self.entry_post_init_setup { - ir.push_str(line); - ir.push('\n'); - } - } - inst.render_into(&mut ir); - ir.push('\n'); - idx += 1; - } - // Boundary at end-of-block (or empty block). + .min(blk.instruction_count()) + } else { + usize::MAX + }; + let mut idx = 0usize; + for inst in blk.insts() { if idx == boundary { for line in &self.entry_post_init_setup { - ir.push_str(line); - ir.push('\n'); + self.emit_maybe_ret_rewritten(line, rewrite_rets, &mut seq, sink)?; } } - } else { - ir.push_str(&blk.to_ir()); - ir.push('\n'); - } - } - - ir.push_str("}\n"); - - // Return-site rewrite hooks. - // - // Shadow-stack pop (gen-GC Phase A sub-phase 2) and entry - // diagnostics both need to run before every normal return, - // regardless of which lowering path emitted it. Textual rewrite - // on the full IR catches implicit returns, Stmt::Return, and any - // hand-emitted `ret`. - let ir = if self.shadow_frame_slot.is_some() || !self.pre_return_void_calls.is_empty() { - let mut out = String::with_capacity(ir.len() + 512); - let mut seq: u32 = 0; - for line in ir.lines() { - let trimmed = line.trim_start(); - if (trimmed.starts_with("ret ") || trimmed == "ret void") - && !trimmed.starts_with("ret ptr ") - // skip rare ptr rets - { - for func_name in &self.pre_return_void_calls { - out.push_str(&format!(" call void @{}()\n", func_name)); - } - if let Some(handle_slot) = &self.shadow_frame_slot { - let load_reg = format!("%shadow_pop_l_{}", seq); - seq += 1; - out.push_str(&format!(" {} = load i64, ptr {}\n", load_reg, handle_slot)); - out.push_str(&format!( - " call void @js_shadow_frame_pop(i64 {})\n", - load_reg - )); + line_buf.clear(); + inst.render_into(&mut line_buf); + // Split multi-line raw payloads exactly like text rendering + // followed by the line-based rewrite pass would. + if line_buf.contains('\n') { + let whole = std::mem::take(&mut line_buf); + for l in whole.split('\n') { + self.emit_maybe_ret_rewritten(l, rewrite_rets, &mut seq, sink)?; } + } else { + let whole = std::mem::take(&mut line_buf); + self.emit_maybe_ret_rewritten(&whole, rewrite_rets, &mut seq, sink)?; + line_buf = whole; } - out.push_str(line); - out.push('\n'); + idx += 1; } - out - } else { - ir - }; - - // setjmp volatile promotion (#6385). - // - // Runs LAST so it sees every instruction, including the ones the - // return-site rewrite above just spliced in. Any alloca this function - // stores into between a `setjmp` and its `longjmp` (recorded by - // `LlBlock::emit` while a try region was open) gets `volatile` loads - // and stores, which is what stops mem2reg/SROA from promoting it into - // a register that `longjmp` would revert. This replaces the old - // `optnone`-the-whole-function hammer. - if self.has_try { - let try_stores = self.reg_counter.try_region_stores(); - if !try_stores.is_empty() { - return crate::volatile_setjmp::apply_setjmp_volatile(&ir, &try_stores); + if is_entry && idx == boundary { + for line in &self.entry_post_init_setup { + self.emit_maybe_ret_rewritten(line, rewrite_rets, &mut seq, sink)?; + } } } + Ok(()) + } - ir + /// Return-site rewrite, streamed: before every `ret` (except `ret ptr`), + /// inject the pre-return void calls and the shadow-frame pop. Byte-equal + /// to the old whole-text line scan. + fn emit_maybe_ret_rewritten( + &self, + line: &str, + rewrite_rets: bool, + seq: &mut u32, + sink: &mut dyn FnMut(&str) -> Result<(), E>, + ) -> Result<(), E> { + if rewrite_rets { + let trimmed = line.trim_start(); + if (trimmed.starts_with("ret ") || trimmed == "ret void") + && !trimmed.starts_with("ret ptr ") + { + for func_name in &self.pre_return_void_calls { + sink(&format!(" call void @{}()", func_name))?; + } + if let Some(handle_slot) = &self.shadow_frame_slot { + let load_reg = format!("%shadow_pop_l_{}", seq); + *seq += 1; + sink(&format!(" {} = load i64, ptr {}", load_reg, handle_slot))?; + sink(&format!( + " call void @js_shadow_frame_pop(i64 {})", + load_reg + ))?; + } + } + } + sink(line) } } diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs index 9a8130bf1f..dcd10202c6 100644 --- a/crates/perry-codegen/src/native_emit.rs +++ b/crates/perry-codegen/src/native_emit.rs @@ -19,15 +19,16 @@ //! to the text pipeline, where `native`/`diff` still select the in-process //! *transport*, so no clang subprocess appears in any in-process mode. //! -//! Construction consumes `LlFunction::to_ir()` output per function — the -//! fully finalized text including entry-alloca hoists, boundary splices, -//! return-site rewrites and setjmp volatile promotion — so those transforms -//! have exactly one implementation. The per-function text is transient -//! (dropped immediately after parsing); what stops existing is the -//! module-scale concatenation and the full-grammar LLVM parse. The follow-up -//! step (typed `LlInst` in `LlBlock`) removes the per-line text too; the -//! `instructions=` counter logged per module is the ratchet metric for that -//! migration. +//! Construction consumes `LlFunction::for_each_final_line` — the finalized +//! per-line stream including entry-alloca hoists, boundary splices and +//! return-site rewrites, shared with `to_ir` so those transforms have +//! exactly one implementation. No per-function text is materialized on this +//! path; the exception is `has_try` functions, whose setjmp volatile pass +//! needs whole-function analysis and therefore still renders text. What +//! stops existing everywhere is the module-scale concatenation and the +//! full-grammar LLVM parse. The follow-up (typed `LlInst` variants) removes +//! the remaining per-LINE formatting; the `instructions=` counter logged per +//! module is that migration's ratchet. use anyhow::{anyhow, Result}; use inkwell::context::Context; @@ -73,16 +74,32 @@ fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result let module = crate::inprocess::parse_ir_text(context, &skeleton, "perry_native_module")?; let mut instructions = 0usize; for f in &funcs { - let fn_text = f.to_ir(); - instructions += crate::dialect::add_function_from_text(context, &module, &fn_text) - .map_err(|e| { - anyhow!( - "native IR construction failed in @{}:\n{}\n--- function IR ---\n{}", - f.name, - e, - fn_text - ) - })?; + let header = synth_define_header(f); + let mut stream = crate::dialect::FnStream::begin(context, &module, &header) + .map_err(|e| anyhow!("native IR construction failed in @{}: {}", f.name, e))?; + if f.has_try { + // The setjmp volatile pass needs whole-function analysis; keep + // the materialized-text path for try-containing functions. + let fn_text = f.to_ir(); + for line in fn_text.lines().skip(1) { + stream.line(line).map_err(|e| { + anyhow!( + "native IR construction failed in @{}:\n{}\n--- function IR ---\n{}", + f.name, + e, + fn_text + ) + })?; + } + } else { + // The common case: finalized lines stream straight into the + // C-API builder — no per-function text exists. + f.for_each_final_line::(&mut |line| stream.line(line)) + .map_err(|e| anyhow!("native IR construction failed in @{}: {}", f.name, e))?; + } + instructions += stream + .finish() + .map_err(|e| anyhow!("native IR construction failed in @{}: {}", f.name, e))?; } log::debug!( "perry-codegen: native construction built {} functions, {} instructions, skeleton {} bytes", @@ -176,3 +193,33 @@ pub fn compile_module_diff(llmod: &LlModule, target: Option<&str>) -> Result String { + let params = f + .params + .iter() + .map(|(t, n)| format!("{t} {n}")) + .collect::>() + .join(", "); + let linkage = if f.linkage.is_empty() { + String::new() + } else { + format!("{} ", f.linkage) + }; + let attrs = if f.has_try { + " #1" + } else if f.force_inline { + " alwaysinline" + } else if f.inline_hint { + " inlinehint" + } else { + "" + }; + format!( + "define {}{} @{}({}){} {{", + linkage, f.return_type, f.name, params, attrs + ) +} From 73646928d18616b188daab99421cd7beed8ce6e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 11:52:02 +0200 Subject: [PATCH 14/26] =?UTF-8?q?exp:=20fix=20forward-ref=20placeholder=20?= =?UTF-8?q?=E2=80=94=20select-of-undef=20folds=20to=20undef?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The C-API builder constant-folds 'select true, undef, undef' to the uniqued constant undef: un-RAUW-able, verifier-clean, and silently substituting undef for every non-phi forward reference. Caught by the FULL gap sweep as a class/prototype family failing with '(number).set is not a function' (sampled slices never hit the family); it also explains the batch.ts 336-byte object delta previously misread as benign regalloc divergence. Placeholder is now a load from a scratch alloca (real instructions, never foldable, erased on resolution), and a use/def type mismatch is a hard error. Both corpora now emit BYTE-IDENTICAL objects from the two construction paths. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/dialect.rs | 71 ++++++++++++++++++----------- docs/llvm-inprocess-experiment.md | 39 ++++++++++------ 2 files changed, 69 insertions(+), 41 deletions(-) diff --git a/crates/perry-codegen/src/dialect.rs b/crates/perry-codegen/src/dialect.rs index 4aa29e04c6..0c0ded256d 100644 --- a/crates/perry-codegen/src/dialect.rs +++ b/crates/perry-codegen/src/dialect.rs @@ -114,10 +114,16 @@ struct FnReader<'ctx, 'm> { /// Non-phi forward references (measured in the corpus: the megamorphic /// `idispatch.tower` shape uses a register before its defining block /// appears in the text). Each unresolved `%reg` use gets a placeholder - /// instruction (`select true, undef, undef`) that is RAUW'd and erased - /// when the real definition arrives — the same strategy LLVM's own - /// `.ll` parser uses. - placeholders: HashMap>, + /// that is RAUW'd and erased when the real definition arrives — the + /// same strategy LLVM's own `.ll` parser uses. + /// + /// The placeholder is a `load` from a scratch `alloca` — real + /// instructions the builder can never constant-fold. The first version + /// used `select true, undef, undef`, which the C-API builder folds to + /// the uniqued constant `undef`: un-RAUW-able, verifier-clean, and it + /// silently turned every non-phi forward reference into `undef` (caught + /// as the class-family miscompile: `(number).set is not a function`). + placeholders: HashMap, inkwell::values::PointerValue<'ctx>)>, /// Most recently *entered* (label line) block, used to keep the /// function's block order equal to textual order even when a forward /// branch created the block object earlier. @@ -299,14 +305,18 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { Ok(()) } - fn def(&mut self, name: &str, v: BasicValueEnum<'ctx>) { - if let Some(ph) = self.placeholders.remove(name) { - rauw(ph, v); + fn def(&mut self, name: &str, v: BasicValueEnum<'ctx>) -> Result<()> { + if let Some((ph, scratch)) = self.placeholders.remove(name) { + rauw(name, ph, v)?; if let Some(inst) = ph.as_instruction_value() { let _ = inst.erase_from_basic_block(); } + if let Some(inst) = scratch.as_instruction_value() { + let _ = inst.erase_from_basic_block(); + } } self.vals.insert(name.to_string(), v); + Ok(()) } /// Resolve `(type, token)` to a value. An undefined `%reg` becomes a @@ -317,22 +327,22 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { return Ok(*v); } if tok.starts_with('%') { - let undef: BasicValueEnum = match ty { - BasicTypeEnum::FloatType(t) => t.get_undef().into(), - BasicTypeEnum::IntType(t) => t.get_undef().into(), - BasicTypeEnum::PointerType(t) => t.get_undef().into(), - other => bail!("forward reference {tok} of unsupported type {other:?}"), - }; + // Non-foldable placeholder: load from a scratch alloca. Both + // instructions are erased when the definition arrives. + let reg = tok.trim_start_matches('%'); + let scratch = self + .builder + .build_alloca(ty, &format!("fwdslot.{reg}")) + .map_err(be)?; let ph = self .builder - .build_select( - self.ctx.bool_type().const_int(1, false), - undef, - undef, - &format!("fwd.{}", tok.trim_start_matches('%')), - ) + .build_load(ty, scratch, &format!("fwd.{reg}")) .map_err(be)?; - self.placeholders.insert(tok.to_string(), ph); + debug_assert!( + ph.as_instruction_value().is_some(), + "placeholder must be a real instruction" + ); + self.placeholders.insert(tok.to_string(), (ph, scratch)); self.vals.insert(tok.to_string(), ph); return Ok(ph); } @@ -418,7 +428,7 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { } _ => self.binary_or_cast(dst, op, rest)?, }; - self.def(dst, v); + self.def(dst, v)?; Ok(()) } @@ -555,7 +565,7 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { b.trim().trim_start_matches('%').to_string(), )); } - self.def(dst, phi.as_basic_value()); + self.def(dst, phi.as_basic_value())?; self.pending_phis.push((phi, ty, pending)); Ok(()) } @@ -998,8 +1008,12 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { } } -/// Replace every use of a placeholder with the real definition. -fn rauw<'ctx>(ph: BasicValueEnum<'ctx>, real: BasicValueEnum<'ctx>) { +/// Replace every use of a placeholder with the real definition. A type +/// mismatch means the operand-context type at the USE disagreed with the +/// defining instruction — always a reader bug, and silently leaving the +/// placeholder in place is exactly how the select-undef version shipped a +/// miscompile, so it is a hard error. +fn rauw<'ctx>(name: &str, ph: BasicValueEnum<'ctx>, real: BasicValueEnum<'ctx>) -> Result<()> { match (ph, real) { (BasicValueEnum::IntValue(a), BasicValueEnum::IntValue(b)) => a.replace_all_uses_with(b), (BasicValueEnum::FloatValue(a), BasicValueEnum::FloatValue(b)) => { @@ -1008,10 +1022,13 @@ fn rauw<'ctx>(ph: BasicValueEnum<'ctx>, real: BasicValueEnum<'ctx>) { (BasicValueEnum::PointerValue(a), BasicValueEnum::PointerValue(b)) => { a.replace_all_uses_with(b) } - // Type mismatch between forward use and definition: leave the - // placeholder in place — the verifier reports it with context. - _ => {} + (a, b) => bail!( + "forward reference {name} used as {:?} but defined as {:?}", + a.get_type(), + b.get_type() + ), } + Ok(()) } // --------------------------------------------------------------------------- diff --git a/docs/llvm-inprocess-experiment.md b/docs/llvm-inprocess-experiment.md index d8ab0d3a33..8d734747f0 100644 --- a/docs/llvm-inprocess-experiment.md +++ b/docs/llvm-inprocess-experiment.md @@ -42,20 +42,31 @@ Results so far: - `spike.ts`: text-parsed arm and natively-constructed arm emit **byte-identical objects**; the native-mode binary matches the pinned Node oracle. -- `batch.ts`: all pre-opt divergences are one class — the C-API builder - constant-folds at construction (`zext i1 false`, `select i1 false`, - constant GEPs) — which is why `=diff`'s verdict is **emitted object - bytes**, not pre-opt prints. The arms' objects differ by 336 bytes of - *tighter* native-arm code (register-allocation divergence downstream of - pre-folded input; same symbols, verified at the disassembly level to be - layout/regalloc, not semantics). -- Behavior: 26-test gap-corpus slice under `=native` (one binary, flag-only - A/B, liveness asserted): first pass 25/25 byte-identical outputs with one - compile failure — a multi-module test that exposed two reader bugs - (explicit `external` linkage keyword; skeleton globals referencing defined - wrapper functions, fixed by parsing the skeleton with synthesized declares - for every define). After the fix the failing test compiles natively with - identical output; the full slice re-run is recorded in the tracking issue. +- `batch.ts` and `spike.ts`: after the placeholder fix below, both corpora + emit **byte-identical objects** from the two construction paths. The + pre-opt representations still differ in exactly one class — the C-API + builder constant-folds at construction (`zext i1 false`, `select i1 + false`, constant GEPs) — which is why `=diff`'s verdict is emitted object + bytes, not pre-opt prints. There is no "benign object divergence" class: + a byte mismatch is a bug. +- **The bug the full gap sweep caught (and the sampled slices missed):** + the original forward-reference placeholder was `select true, undef, + undef`, which the C-API builder constant-folds to the uniqued constant + `undef` — un-RAUW-able, verifier-clean, and silently substituting `undef` + for every non-phi forward reference. Symptom: a class/prototype test + family failing with `(number).set is not a function`; the earlier + "336-byte tighter native code" on `batch.ts` was the same bug deleting + real (never-executed-in-that-kernel) code, initially misread as benign + regalloc divergence. Fix: the placeholder is now a `load` from a scratch + `alloca` (real instructions, never foldable, erased on resolution), and a + use/def type mismatch is a hard error instead of a silent leak. Lesson + encoded in the harness: the byte verdict was right; explanations of red + are not. +- Behavior: 26-test slices passed 25/25+26/26; the authoritative full + 466-test sweep result under `=native` is recorded in the tracking issue. + Earlier slice findings: a multi-module test exposed two reader bugs + (explicit `external` linkage; skeleton globals referencing defined + wrapper functions — fixed by synthesized declares for every define). Modes: `PERRY_LLVM_INPROCESS=1` transport (parse whole text in-process), `=native` construction, `=diff` both-arms harness (returns the text arm's From 869cb60391372e77c16124f4b57f032941d7592d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 2 Aug 2026 12:41:01 +0200 Subject: [PATCH 15/26] exp: auto-declare llvm.* intrinsics at callsites; surface full error chains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The text path leans on LLParser auto-declaring @llvm.* intrinsics at first use (perry's clamp lowering emits smax/smin with no textual declare); the reader now mirrors that for intrinsics only — anything else undeclared stays a loud error. Native-path error wrappers print the full anyhow chain ({:#}) so root causes are not swallowed by the outermost context. Fixes the one compile failure in the full sweep (test_gap_6339_i32_arith_chain_copy), now byte-identical. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/dialect.rs | 19 +++++++++++++------ crates/perry-codegen/src/native_emit.rs | 6 +++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/crates/perry-codegen/src/dialect.rs b/crates/perry-codegen/src/dialect.rs index 0c0ded256d..6aaa809793 100644 --- a/crates/perry-codegen/src/dialect.rs +++ b/crates/perry-codegen/src/dialect.rs @@ -692,11 +692,18 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { // call. let fn_ty = indirect_fn_type(self.ctx, sig_str, &arg_types)?; let callee_ptr = if let Some(fname) = callee.strip_prefix('@') { - self.module - .get_function(&unquote(fname)) - .ok_or_else(|| anyhow!("call to undeclared @{fname}"))? - .as_global_value() - .as_pointer_value() + let name = unquote(fname); + let f = match self.module.get_function(&name) { + Some(f) => f, + // LLVM's own .ll parser auto-declares `@llvm.*` intrinsics at + // their first use (perry's clamp lowering emits smax/smin + // calls with no textual declare). Mirror that — for + // intrinsics ONLY; anything else undeclared stays a loud + // error. + None if name.starts_with("llvm.") => self.module.add_function(&name, fn_ty, None), + None => bail!("call to undeclared @{name}"), + }; + f.as_global_value().as_pointer_value() } else { self.val(self.ctx.ptr_type(AddressSpace::default()).into(), callee)? .into_pointer_value() @@ -861,7 +868,7 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> { } // Binary ops: `[flags] T A, B` where op may carry nsw/nuw/fmf tokens. - let mut op_base = op; + let op_base = op; let mut rest2 = rest; let mut flag_tokens: Vec<&str> = Vec::new(); loop { diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs index dcd10202c6..9556abb233 100644 --- a/crates/perry-codegen/src/native_emit.rs +++ b/crates/perry-codegen/src/native_emit.rs @@ -76,7 +76,7 @@ fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result for f in &funcs { let header = synth_define_header(f); let mut stream = crate::dialect::FnStream::begin(context, &module, &header) - .map_err(|e| anyhow!("native IR construction failed in @{}: {}", f.name, e))?; + .map_err(|e| anyhow!("native IR construction failed in @{}: {:#}", f.name, e))?; if f.has_try { // The setjmp volatile pass needs whole-function analysis; keep // the materialized-text path for try-containing functions. @@ -95,11 +95,11 @@ fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result // The common case: finalized lines stream straight into the // C-API builder — no per-function text exists. f.for_each_final_line::(&mut |line| stream.line(line)) - .map_err(|e| anyhow!("native IR construction failed in @{}: {}", f.name, e))?; + .map_err(|e| anyhow!("native IR construction failed in @{}: {:#}", f.name, e))?; } instructions += stream .finish() - .map_err(|e| anyhow!("native IR construction failed in @{}: {}", f.name, e))?; + .map_err(|e| anyhow!("native IR construction failed in @{}: {:#}", f.name, e))?; } log::debug!( "perry-codegen: native construction built {} functions, {} instructions, skeleton {} bytes", From 868003906fa9f39c70270faf58cdf6aea2db2405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Mon, 3 Aug 2026 07:05:06 +0200 Subject: [PATCH 16/26] exp: commit corpus .ll files; make A/B harness Linux-portable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dialect corpus tests read spike_text.ll/batch_kernel.ll — gitignored until now, so a fresh clone skipped them silently (a gate that cannot fail). Track both (~670 KB). batch_ab.sh: gtimeout/timeout detection and a portable free-disk probe replace the macOS-only spellings. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- experiments/llvm-inprocess-spike/.gitignore | 1 - experiments/llvm-inprocess-spike/batch_ab.sh | 21 +- .../llvm-inprocess-spike/batch_kernel.ll | 10658 ++++++++++++++++ .../llvm-inprocess-spike/spike_text.ll | 5625 ++++++++ 4 files changed, 16298 insertions(+), 7 deletions(-) create mode 100644 experiments/llvm-inprocess-spike/batch_kernel.ll create mode 100644 experiments/llvm-inprocess-spike/spike_text.ll diff --git a/experiments/llvm-inprocess-spike/.gitignore b/experiments/llvm-inprocess-spike/.gitignore index f44b3f2c9c..2dc3aa0399 100644 --- a/experiments/llvm-inprocess-spike/.gitignore +++ b/experiments/llvm-inprocess-spike/.gitignore @@ -6,6 +6,5 @@ demo-out/ *.log spike_text spike_inproc -spike_text.ll spike_roundtrip.ll roundtrip.diff diff --git a/experiments/llvm-inprocess-spike/batch_ab.sh b/experiments/llvm-inprocess-spike/batch_ab.sh index 0bc79a8c95..be86ca7b05 100755 --- a/experiments/llvm-inprocess-spike/batch_ab.sh +++ b/experiments/llvm-inprocess-spike/batch_ab.sh @@ -15,6 +15,15 @@ WORK=${1:?usage: batch_ab.sh [shim|flag] [stride] [offset]} MODE=${2:-shim} STRIDE=${3:-6} OFFSET=${4:-0} +# Portability: "$TIMEOUT" is coreutils' name on macOS (brew), timeout on Linux. +TIMEOUT=$(command -v "$TIMEOUT" || command -v timeout) +free_gb_now() { + if [ "$(uname)" = "Darwin" ]; then + df -g /System/Volumes/Data | awk 'NR==2{print $4}' + else + df -BG --output=avail / | awk 'NR==2{gsub("G","",$1); print $1}' + fi +} mkdir -p "$WORK" export PERRY_RUNTIME_DIR=$WT/target/perry-dev export PERRY_NO_AUTO_OPTIMIZE=1 @@ -26,20 +35,20 @@ for t in $(ls "$WT"/test-files/test_gap_*.ts | sort); do i=$((i+1)) [ $((i % STRIDE)) -ne $OFFSET ] && continue name=$(basename "$t" .ts) - free_gb=$(df -g /System/Volumes/Data | awk 'NR==2{print $4}') + free_gb=$(free_gb_now) if [ "$free_gb" -lt 6 ]; then echo "ABORT: only ${free_gb}GB free" | tee -a "$WORK/summary.txt"; exit 2; fi - gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.t" >"$WORK/$name.t.compile" 2>&1 + "$TIMEOUT" 180 "$PERRY" "$t" -o "$WORK/$name.t" >"$WORK/$name.t.compile" 2>&1 ct=$? if [ "$MODE" = "flag" ]; then - PERRY_LLVM_INPROCESS=${INPROCESS_VALUE:-1} gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 + PERRY_LLVM_INPROCESS=${INPROCESS_VALUE:-1} "$TIMEOUT" 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 cp=$? # Liveness: the arm must have announced the in-process backend. if [ $cp -eq 0 ] && ! grep -q "in-process LLVM backend active" "$WORK/$name.p.compile"; then echo "NOT_LIVE $name" >> "$WORK/results.txt"; cp=97 fi else - PERRY_LLVM_CLANG=$SPIKE gtimeout 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 + PERRY_LLVM_CLANG=$SPIKE "$TIMEOUT" 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 cp=$? fi @@ -47,8 +56,8 @@ for t in $(ls "$WT"/test-files/test_gap_*.ts | sort); do if [ $ct -ne 0 ]; then cfail_t=$((cfail_t+1)); echo "CFAIL_T $name" >> "$WORK/results.txt"; rm -f "$WORK/$name".[tp]; continue; fi if [ $cp -ne 0 ]; then cfail_p=$((cfail_p+1)); echo "CFAIL_P $name" >> "$WORK/results.txt"; rm -f "$WORK/$name".[tp]; continue; fi - gtimeout 20 "$WORK/$name.t" >"$WORK/$name.t.out" 2>"$WORK/$name.t.err"; rt=$? - gtimeout 20 "$WORK/$name.p" >"$WORK/$name.p.out" 2>"$WORK/$name.p.err"; rp=$? + "$TIMEOUT" 20 "$WORK/$name.t" >"$WORK/$name.t.out" 2>"$WORK/$name.t.err"; rt=$? + "$TIMEOUT" 20 "$WORK/$name.p" >"$WORK/$name.p.out" 2>"$WORK/$name.p.err"; rp=$? if [ $rt -eq $rp ] && cmp -s "$WORK/$name.t.out" "$WORK/$name.p.out" && cmp -s "$WORK/$name.t.err" "$WORK/$name.p.err"; then same=$((same+1)); echo "SAME $name (exit=$rt)" >> "$WORK/results.txt" else diff --git a/experiments/llvm-inprocess-spike/batch_kernel.ll b/experiments/llvm-inprocess-spike/batch_kernel.ll new file mode 100644 index 0000000000..d185e937b8 --- /dev/null +++ b/experiments/llvm-inprocess-spike/batch_kernel.ll @@ -0,0 +1,10658 @@ +; Generated by perry-codegen +target triple = "arm64-apple-macosx15.0.0" + +@batch_ts_.str.0.bytes = private unnamed_addr constant [4 x i8] c"acc\00" +@batch_ts_.str.1.bytes = private unnamed_addr constant [6 x i8] c"total\00" +@batch_ts_.str.2.bytes = private unnamed_addr constant [7 x i8] c"weight\00" +@batch_ts_.str.3.bytes = private unnamed_addr constant [5 x i8] c"peak\00" +@batch_ts_.str.4.bytes = private unnamed_addr constant [6 x i8] c"score\00" +@batch_ts_.str.5.bytes = private unnamed_addr constant [7 x i8] c"bucket\00" +@batch_ts_.str.6.bytes = private unnamed_addr constant [2 x i8] c":\00" +@batch_ts_.str.7.bytes = private unnamed_addr constant [3 x i8] c"id\00" +@batch_ts_.str.8.bytes = private unnamed_addr constant [8 x i8] c"rescore\00" +@batch_ts_.str.9.bytes = private unnamed_addr constant [5 x i8] c"even\00" +@batch_ts_.str.10.bytes = private unnamed_addr constant [4 x i8] c"odd\00" +@batch_ts_.str.11.bytes = private unnamed_addr constant [6 x i8] c"value\00" +@batch_ts_.str.12.bytes = private unnamed_addr constant [4 x i8] c"key\00" +@batch_ts_.str.13.bytes = private unnamed_addr constant [6 x i8] c"count\00" +@batch_ts_.str.14.bytes = private unnamed_addr constant [4 x i8] c"tag\00" +@batch_ts_.str.15.bytes = private unnamed_addr constant [6 x i8] c"alpha\00" +@batch_ts_.str.16.bytes = private unnamed_addr constant [5 x i8] c"beta\00" +@batch_ts_.str.17.bytes = private unnamed_addr constant [6 x i8] c"gamma\00" +@batch_ts_.str.18.bytes = private unnamed_addr constant [6 x i8] c"delta\00" +@batch_ts_.str.19.bytes = private unnamed_addr constant [11 x i8] c"checksum: \00" +@perry_class_keys_packed_batch_ts__0 = private unnamed_addr constant [24 x i8] c"id\00bucket\00weight\00score\00\00" +@perry_class_keys_packed_batch_ts__1 = private unnamed_addr constant [15 x i8] c"key\00value\00tag\00\00" +@perry_class_keys_packed_batch_ts__2 = private unnamed_addr constant [25 x i8] c"bucket\00count\00total\00peak\00\00" +@.str.0 = private unnamed_addr constant [10 x i8] c"buildRows\00" +@.str.1 = private unnamed_addr constant [6 x i8] c"shape\00" +@.str.2 = private unnamed_addr constant [7 x i8] c"ranked\00" +@.str.3 = private unnamed_addr constant [10 x i8] c"summarize\00" +@.str.4 = private unnamed_addr constant [10 x i8] c"totalsRow\00" +@.str.5 = private unnamed_addr constant [214 x i8] c"function buildRows(n: number): Row[] {\0A const rows: Row[] = [];\0A for (let i = 0; i < n; i++) {\0A const row = new Row(i, BUCKETS[i % 4], (i % 97) * 0.5);\0A rows.push(row);\0A }\0A return rows;\0A}\00" +@.str.6 = private unnamed_addr constant [194 x i8] c"function shape(rows: Row[]): Shaped[] {\0A return rows.map((r) => ({\0A key: r.bucket + \22:\22 + r.id,\0A value: r.rescore(1.5),\0A tag: r.id % 2 === 0 ? \22even\22 : \22odd\22,\0A }));\0A}\00" +@.str.7 = private unnamed_addr constant [272 x i8] c"function ranked(items: Shaped[]): Shaped[] {\0A const copy = items.slice();\0A copy.sort((a, b) => {\0A if (a.value !== b.value) {\0A return b.value - a.value;\0A }\0A return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;\0A });\0A return copy;\0A}\00" +@.str.8 = private unnamed_addr constant [640 x i8] c"function summarize(rows: Row[]): Summary[] {\0A const byBucket: Summary[] = [];\0A for (let b = 0; b < BUCKETS.length; b++) {\0A const s: Summary = {\0A bucket: BUCKETS[b],\0A count: 0,\0A total: 0,\0A peak: 0,\0A };\0A byBucket.push(s);\0A }\0A rows.reduce((acc: Summary[], r: Row) => {\0A const idx = BUCKETS.indexOf(r.bucket);\0A const slot = acc[idx];\0A slot.count = slot.count + 1;\0A slot.total = slot.total + r.score;\0A if (r.score > slot.peak) {\0A slot.peak = r.score;\0A }\0A return acc;\0A }, byBucket);\0A return byBucket;\0A}\00" +@.str.9 = private unnamed_addr constant [264 x i8] c"function totalsRow(summaries: Summary[]): Row {\0A const acc = new Row(0, \22acc\22, 0);\0A for (let i = 0; i < summaries.length; i++) {\0A acc.weight = acc.weight + summaries[i].total;\0A acc.score = acc.score + summaries[i].peak;\0A }\0A return acc;\0A}\00" +@.str.10 = private unnamed_addr constant [130 x i8] c"(r) => ({\0A key: r.bucket + \22:\22 + r.id,\0A value: r.rescore(1.5),\0A tag: r.id % 2 === 0 ? \22even\22 : \22odd\22,\0A })\00" +@.str.11 = private unnamed_addr constant [160 x i8] c"(a, b) => {\0A if (a.value !== b.value) {\0A return b.value - a.value;\0A }\0A return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;\0A }\00" +@.str.12 = private unnamed_addr constant [292 x i8] c"(acc: Summary[], r: Row) => {\0A const idx = BUCKETS.indexOf(r.bucket);\0A const slot = acc[idx];\0A slot.count = slot.count + 1;\0A slot.total = slot.total + r.score;\0A if (r.score > slot.peak) {\0A slot.peak = r.score;\0A }\0A return acc;\0A }\00" +@.str.13 = private unnamed_addr constant [4 x i8] c"Row\00" + +@perry_null_guard_zero = internal global i32 0 +@PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED = external global i8 +@PERRY_ARRAY_INDEX_FAST_PATH_INVALIDATED = external global i8 +@PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT = external global i32 +@PERRY_TA_KIND_CACHE = external global [64 x i64] +@PERRY_TA_VIEW_GUARD = external global i64 +@perry_class_keys_batch_ts__Row = internal global i64 0 +@perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 = internal global i64 0 +@perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 = internal global i64 0 +@perry_global_batch_ts__1 = global double 0x7FFC000000000001 +@perry_ic_2 = private global [8 x i64] zeroinitializer +@perry_ic_5 = private global [8 x i64] zeroinitializer +@perry_ic_8 = private global [8 x i64] zeroinitializer +@perry_ic_10 = private global [8 x i64] zeroinitializer +@perry_ic_12 = private global [8 x i64] zeroinitializer +@perry_ic_14 = private global [8 x i64] zeroinitializer +@perry_ic_16 = private global [8 x i64] zeroinitializer +@perry_ic_18 = private global [8 x i64] zeroinitializer +@perry_ic_20 = private global [8 x i64] zeroinitializer +@perry_ic_22 = private global [8 x i64] zeroinitializer +@perry_ic_24 = private global [8 x i64] zeroinitializer +@perry_ic_26 = private global [8 x i64] zeroinitializer +@perry_ic_28 = private global [8 x i64] zeroinitializer +@perry_ic_31 = private global [8 x i64] zeroinitializer +@perry_ic_32 = private global [8 x i64] zeroinitializer +@perry_ic_34 = private global [8 x i64] zeroinitializer +@perry_ic_36 = private global [8 x i64] zeroinitializer +@perry_ic_39 = private global [8 x i64] zeroinitializer +@perry_ic_41 = private global [8 x i64] zeroinitializer +@perry_ic_71 = private global [8 x i64] zeroinitializer +@perry_ic_74 = private global [8 x i64] zeroinitializer +@perry_ic_77 = private global [8 x i64] zeroinitializer +@batch_ts_.str.0.handle = internal global double 0.0 +@batch_ts_.str.1.handle = internal global double 0.0 +@batch_ts_.str.2.handle = internal global double 0.0 +@batch_ts_.str.3.handle = internal global double 0.0 +@batch_ts_.str.4.handle = internal global double 0.0 +@batch_ts_.str.5.handle = internal global double 0.0 +@batch_ts_.str.6.handle = internal global double 0.0 +@batch_ts_.str.7.handle = internal global double 0.0 +@batch_ts_.str.8.dispatch = private unnamed_addr constant { i32, i32, i64, ptr } { i32 7, i32 0, i64 3167274721163222882, ptr @batch_ts_.str.8.bytes } +@batch_ts_.str.8.handle = internal global double 0.0 +@batch_ts_.str.9.handle = internal global double 0.0 +@batch_ts_.str.10.handle = internal global double 0.0 +@batch_ts_.str.11.handle = internal global double 0.0 +@batch_ts_.str.12.handle = internal global double 0.0 +@batch_ts_.str.13.handle = internal global double 0.0 +@batch_ts_.str.14.handle = internal global double 0.0 +@batch_ts_.str.15.handle = internal global double 0.0 +@batch_ts_.str.16.handle = internal global double 0.0 +@batch_ts_.str.17.handle = internal global double 0.0 +@batch_ts_.str.18.handle = internal global double 0.0 +@batch_ts_.str.19.handle = internal global double 0.0 +@perry_typed_shape_raw_f64_mask_batch_ts__Row = private unnamed_addr constant [1 x i64] [i64 13] +@perry_typed_shape_mask_batch_ts__Row = private unnamed_addr constant [1 x i64] [i64 2] +@perry_typed_shape_mask_batch_ts____AnonShape_e75d7e32e87dc826 = private unnamed_addr constant [1 x i64] [i64 7] +@perry_typed_shape_raw_f64_mask_batch_ts____AnonShape_c33c4204c28b9430 = private unnamed_addr constant [1 x i64] [i64 14] +@perry_typed_shape_mask_batch_ts____AnonShape_c33c4204c28b9430 = private unnamed_addr constant [1 x i64] [i64 1] + +declare void @js_gc_init() +declare void @js_typed_feedback_maybe_dump_trace() +declare void @js_stdlib_init_dispatch() +declare void @perry_app_group_init(ptr, i32) +declare void @perry_macos_bundle_chdir() +declare i32 @perry_i18n_locale_index_for(i64, i32) +declare void @perry_i18n_init(ptr, ptr, i32, i32) +declare void @perry_i18n_set_currencies(ptr, i32) +declare i32 @perry_i18n_plural_category(i32, double) +declare void @js_register_function_name(ptr, ptr, i32) +declare void @js_register_function_source(ptr, ptr, i32) +declare void @js_console_log_dynamic(double) +declare void @js_console_log_number(double) +declare void @js_console_error_dynamic(double) +declare void @js_console_error_number(double) +declare void @js_console_warn_dynamic(double) +declare void @js_console_warn_number(double) +declare void @js_console_dir_with_options(double, double) +declare double @js_console_method_by_value(double) +declare double @js_nanbox_string(i64) +declare double @js_nanbox_pointer(i64) #2 +declare i64 @js_nanbox_get_pointer(double) #2 +declare double @js_native_handle_new_owned(i64, i64, i32, i32, ptr, ptr, i64) +declare double @js_native_handle_new_borrowed(i64, i64, i32, i32, ptr, i64) +declare i64 @js_native_handle_unwrap(double, i64, i32, i32, i32) +declare i64 @js_string_from_bytes(ptr, i32) +declare i64 @js_string_from_wtf8_bytes(ptr, i32) +declare i32 @js_is_truthy(double) #3 +declare double @js_native_abi_check_f64(double) +declare i32 @js_typed_f64_arg_guard(double) #2 +declare double @js_typed_f64_arg_to_raw(double) +declare i32 @js_typed_i32_arg_guard(double) #2 +declare i32 @js_typed_i32_arg_to_raw(double) #2 +declare i32 @js_typed_i1_arg_guard(double) #2 +declare i32 @js_typed_i1_arg_to_raw(double) #2 +declare i32 @js_typed_string_arg_guard(double) #2 +declare i64 @js_typed_string_arg_to_raw(double) +declare float @js_native_abi_check_f32(double) +declare i32 @js_native_abi_check_i32(double) +declare i64 @js_native_abi_check_i64(double) +declare i32 @js_native_abi_check_u32(double) +declare i64 @js_native_abi_check_u64(double) +declare i64 @js_native_abi_check_usize(double) +declare i64 @js_native_abi_check_string_ptr(double) +declare i64 @js_native_abi_check_ptr(double) +declare ptr @js_native_abi_check_buffer_data_ptr(double) +declare i64 @js_native_abi_check_buffer_byte_len(double) +declare i64 @js_native_abi_check_promise(double) +declare i64 @js_native_abi_check_pod_object(double) +declare double @js_date_now() +declare void @js_gc_register_global_root(i64) +declare i64 @js_string_concat(i64, i64) +declare double @js_string_concat_box(double, double) +declare i64 @js_jsvalue_to_string(double) +declare i64 @js_jsvalue_to_string_method(double) +declare i64 @js_jsvalue_to_string_coerce(double) +declare i64 @js_string_concat_value(i64, double) +declare i64 @js_value_concat_string(double, i64) +declare i64 @js_string_concat_chain(i64, i32) +declare i64 @js_string_append(i64, i64) +declare i32 @js_string_index_of(i64, i64) +declare i32 @js_string_index_of_from(i64, i64, i32) +declare i32 @js_string_position_to_index(double) +declare i64 @js_string_slice(i64, i32, i32) +declare i64 @js_string_substring(i64, i32, i32) +declare i64 @js_string_substr(i64, double, double) +declare i64 @js_string_split(i64, i64) +declare i64 @js_string_split_n(i64, i64, i32) +declare double @js_string_split_part_value(i64, i64, i32) +declare double @js_string_split_part_utf16_length(i64, i64, i32) +declare double @js_string_to_upper_case_split_part_utf16_length(i64, i64, i32) +declare i32 @js_string_to_upper_case_index_of(i64, i64) +declare i64 @js_string_split_value(i64, double, double) +declare double @js_math_trunc(double) +declare double @js_math_round(double) +declare double @js_math_sign(double) +declare double @js_math_imul(double, double) +declare double @js_math_pow(double, double) +declare double @llvm.sqrt.f64(double) +declare double @llvm.floor.f64(double) +declare double @llvm.ceil.f64(double) +declare double @llvm.fabs.f64(double) +declare double @llvm.copysign.f64(double, double) +declare void @llvm.assume(i1) +declare i16 @llvm.bswap.i16(i16) +declare i32 @llvm.bswap.i32(i32) +declare i64 @llvm.bswap.i64(i64) +declare i32 @llvm.aarch64.fjcvtzs(double) +declare void @llvm.memset.p0.i64(ptr, i8, i64, i1) +declare void @llvm.memmove.p0.p0.i64(ptr, ptr, i64, i1) +declare i64 @js_json_stringify(double, i32) +declare i64 @js_map_alloc(i32) +declare i64 @js_text_encoder_encode_into_llvm(double, double) +declare i64 @js_value_typeof(double) +declare i32 @js_string_starts_with(i64, i64) +declare i32 @js_string_ends_with(i64, i64) +declare i64 @js_string_search_value_to_string(double, i32) +declare i32 @js_string_starts_with_at(i64, i64, i32) +declare i32 @js_string_ends_with_at(i64, i64, i32) +declare i64 @js_closure_alloc(ptr, i32) +declare i64 @js_closure_alloc_singleton(ptr) +declare i64 @js_closure_alloc_with_captures_singleton(ptr, i32, ptr) +declare void @js_closure_set_capture_bits(i64, i32, i64) +declare i64 @js_closure_get_capture_bits(i64, i32) +declare void @js_closure_set_capture_f64(i64, i32, double) +declare double @js_closure_get_capture_f64(i64, i32) +declare void @js_register_closure_rest(ptr, i32) +declare void @js_register_closure_synthetic_arguments(ptr, i32) +declare void @js_register_closure_rest_and_arguments(ptr, i32) +declare void @js_register_closure_arity(ptr, i32) +declare void @js_register_closure_length(ptr, i32) +declare void @js_register_closure_arrow_function(ptr) +declare void @js_register_closure_strict_function(ptr) +declare void @js_register_closure_async_function(ptr) +declare void @js_register_closure_generator_function(ptr) +declare void @js_register_closure_async_generator_function(ptr) +declare i64 @js_closure_unbox_callee_checked(double) +declare i64 @js_closure_unbox_callee_checked_rebind(double, double) +declare double @js_closure_call0(i64) +declare double @js_closure_call1(i64, double) +declare double @js_closure_call2(i64, double, double) +declare double @js_closure_call3(i64, double, double, double) +declare double @js_closure_call4(i64, double, double, double, double) +declare double @js_closure_call5(i64, double, double, double, double, double) +declare double @js_closure_call6(i64, double, double, double, double, double, double) +declare double @js_closure_call7(i64, double, double, double, double, double, double, double) +declare double @js_closure_call8(i64, double, double, double, double, double, double, double, double) +declare double @js_closure_call9(i64, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call10(i64, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call11(i64, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call12(i64, double, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call13(i64, double, double, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call14(i64, double, double, double, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call15(i64, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call16(i64, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) +declare i64 @js_array_map(i64, i64) +declare void @js_array_map_discard(i64, i64) +declare i64 @js_array_filter(i64, i64) +declare i64 @js_array_concat(i64, i64) +declare i64 @js_array_concat_new(i64, i64) +declare i64 @js_error_new() +declare i64 @js_error_new_with_message(i64) +declare i64 @js_error_new_from_value(double) +declare i64 @js_error_new_kind_from_value(i32, double) +declare i64 @js_error_new_with_cause_from_value(double, double) +declare i64 @js_error_new_kind_with_options_from_value(i32, double, double) +declare double @js_assert_assertion_error_ctor(double) +declare double @js_assert_assert_ctor(double) +declare void @js_throw_type_error_property_access(i32, ptr, i64) +declare void @js_throw_type_error_not_a_function(ptr, i64, ptr, i64) +declare void @js_throw_error_with_code(ptr, i64, ptr, i64, i32) +declare i64 @js_map_set(i64, double, double) +declare i64 @js_map_set_string_number(i64, i64, double) +declare i64 @js_map_set_string_key(i64, i64, double) +declare i64 @js_map_set_string_i32(i64, i64, i32) +declare i64 @js_map_set_string_u32(i64, i64, i32) +declare i64 @js_map_set_string_f32(i64, i64, float) +declare i64 @js_map_set_string_bool(i64, i64, i32) +declare i64 @js_map_set_string_string(i64, i64, i64) +declare i64 @js_map_set_number_key(i64, double, double) +declare double @js_map_get(i64, double) +declare double @js_map_get_string_key(i64, i64) +declare double @js_map_get_number_key(i64, double) +declare i32 @js_map_has(i64, double) +declare i32 @js_map_has_string_key(i64, i64) +declare i32 @js_map_has_number_key(i64, double) +declare i32 @js_map_delete(i64, double) +declare i32 @js_map_delete_string_key(i64, i64) +declare i32 @js_map_delete_number_key(i64, double) +declare i64 @js_object_keys(i64) +declare i64 @js_object_keys_value(double) +declare i64 @js_for_in_keys_value(double) +declare double @js_is_finite(double) +declare i32 @js_is_undefined_or_bare_nan(double) +declare double @js_math_min_array(i64) +declare double @js_math_max_array(i64) +declare double @js_math_min2(double, double) +declare double @js_math_max2(double, double) +declare i64 @js_string_coerce(double) +declare i64 @js_string_coerce_method_this(double, ptr, i64) +declare i64 @js_array_slice(i64, i32, i32) +declare i64 @js_array_slice_values(i64, double, double) +declare double @js_array_shift_f64(i64) +declare i64 @js_set_alloc(i32) +declare i64 @js_set_from_array(i64) +declare i64 @js_set_from_iterable(double) +declare i64 @js_map_from_array(i64) +declare i64 @js_map_from_iterable(double) +declare double @js_object_has_property(double, double) +declare double @js_in_operator(double, double) +declare double @js_private_brand_check(double, i32, ptr, i32) +declare double @js_private_guard(double, i32, ptr, i32, i32, i32) +declare double @js_fs_to_unix_timestamp(double) +declare i32 @js_fs_write_file_sync(double, double) +declare i32 @js_fs_write_file_sync_options(double, double, double) +declare i32 @js_fs_append_file_sync(double, double) +declare i32 @js_fs_append_file_sync_options(double, double, double) +declare i32 @js_fs_exists_sync(double) +declare i64 @js_fs_read_file_sync(double) +declare double @js_fs_read_file_dispatch(double, double) +declare double @js_fs_open_as_blob(double, double) +declare double @js_fs_promises_read_file(double, double) +declare double @js_fs_promises_write_file(double, double, double) +declare double @js_fs_promises_append_file(double, double, double) +declare double @js_fs_promises_mkdir(double, double) +declare double @js_fs_promises_rmdir(double, double) +declare i32 @js_fs_mkdir_sync(double) +declare i32 @js_fs_mkdir_sync_options(double, double) +declare i32 @js_fs_unlink_sync(double) +declare double @js_fs_readdir_sync(double, double) +declare double @js_fs_stat_sync(double) +declare double @js_fs_stat_sync_options(double, double) +declare double @js_fs_lstat_sync(double) +declare double @js_fs_lstat_sync_options(double, double) +declare i32 @js_fs_rename_sync(double, double) +declare i32 @js_fs_copy_file_sync(double, double) +declare i32 @js_fs_copy_file_sync_flags(double, double, double) +declare i32 @js_fs_cp_sync(double, double) +declare i32 @js_fs_cp_sync_options(double, double, double) +declare i32 @js_fs_chmod_sync(double, double) +declare i32 @js_fs_chown_sync(double, double, double) +declare i32 @js_fs_lchown_sync(double, double, double) +declare i32 @js_fs_lchmod_sync(double, double) +declare i32 @js_fs_truncate_sync(double, double) +declare i32 @js_fs_ftruncate_sync(double, double) +declare i32 @js_fs_fsync_sync(double) +declare i32 @js_fs_fdatasync_sync(double) +declare i32 @js_fs_fchmod_sync(double, double) +declare i32 @js_fs_fchown_sync(double, double, double) +declare double @js_fs_fstat_sync(double) +declare double @js_fs_fstat_sync_options(double, double) +declare i32 @js_fs_utimes_sync(double, double, double) +declare i32 @js_fs_lutimes_sync(double, double, double) +declare i32 @js_fs_futimes_sync(double, double, double) +declare double @js_fs_readv_sync(double, double, double) +declare double @js_fs_writev_sync(double, double, double) +declare double @js_fs_statfs_sync(double) +declare double @js_fs_statfs_sync_options(double, double) +declare double @js_fs_opendir_sync(double) +declare double @js_fs_glob_sync(double) +declare double @js_fs_glob_sync_options(double, double) +declare i32 @js_fs_link_sync(double, double) +declare i32 @js_fs_symlink_sync(double, double) +declare double @js_fs_symlink_callback(double, double, double, double) +declare i64 @js_fs_readlink_sync(double) +declare i64 @js_fs_readlink_sync_options(double, double) +declare double @js_fs_readlink_dispatch(double, double) +declare double @js_fs_open_sync(double, double) +declare i32 @js_fs_close_sync(double) +declare double @js_fs_read_sync(double, double, double, double, double) +declare double @js_fs_read_sync_options(double, double, double) +declare double @js_fs_write_sync(double, double) +declare double @js_fs_write_string_sync_options(double, double, double) +declare double @js_fs_write_buffer_sync(double, double, double, double, double) +declare double @js_fs_write_sync_options_dispatch(double, double, double) +declare i32 @js_fs_access_sync(double) +declare i32 @js_fs_access_sync_mode(double, double) +declare double @js_fs_access_sync_throw(double) +declare double @js_fs_access_sync_throw_mode(double, double) +declare i64 @js_fs_realpath_sync(double) +declare double @js_fs_realpath_dispatch(double, double) +declare i64 @js_fs_mkdtemp_sync(double) +declare i64 @js_fs_mkdtemp_sync_options(double, double) +declare double @js_fs_mkdtemp_dispatch(double, double) +declare double @js_fs_mkdtemp_disposable_sync(double, double) +declare i32 @js_fs_rmdir_sync(double) +declare i32 @js_fs_rmdir_sync_options(double, double) +declare i32 @js_fs_rm_recursive(double) +declare i32 @js_fs_rm_recursive_options(double, double) +declare double @js_fs_create_write_stream(double, double) +declare double @js_fs_create_read_stream(double, double) +declare double @js_fs_utf8_stream_new(double) +declare double @js_fs_utf8_stream_call_without_new(double) +declare double @js_fs_utf8_stream_write(double, double) +declare double @js_fs_utf8_stream_flush(double, double) +declare double @js_fs_utf8_stream_flush_sync(double) +declare double @js_fs_utf8_stream_end(double, double) +declare double @js_fs_utf8_stream_destroy(double) +declare double @js_fs_utf8_stream_reopen(double, double) +declare double @js_fs_utf8_stream_on(double, double, double) +declare double @js_fs_utf8_stream_once(double, double, double) +declare double @js_fs_utf8_stream_off(double, double, double) +declare double @js_fs_utf8_stream_remove_all(double, double) +declare double @js_fs_utf8_stream_listener_count(double, double) +declare double @js_fs_utf8_stream_emit(double, double, double) +declare double @js_fs_read_file_callback(double, double, double) +declare double @js_fs_stats_is_file(double) +declare double @js_fs_stats_is_directory(double) +declare i64 @js_fs_read_file_binary(double) +declare double @js_number_coerce(double) +declare double @js_math_to_number(double) +declare i64 @js_set_add(i64, double) +declare i64 @js_set_add_string(i64, i64) +declare i64 @js_set_add_number(i64, double) +declare i64 @js_set_add_i32(i64, i32) +declare i64 @js_set_add_u32(i64, i32) +declare i64 @js_set_add_f32(i64, float) +declare i64 @js_set_add_bool(i64, i32) +declare i32 @js_set_has(i64, double) +declare i32 @js_set_has_string(i64, i64) +declare i32 @js_set_has_number(i64, double) +declare i32 @js_set_has_i32(i64, i32) +declare i32 @js_set_has_u32(i64, i32) +declare i32 @js_set_has_f32(i64, float) +declare i32 @js_set_has_bool(i64, i32) +declare i32 @js_set_delete(i64, double) +declare i32 @js_set_delete_string(i64, i64) +declare i32 @js_set_delete_number(i64, double) +declare i32 @js_set_delete_i32(i64, i32) +declare i32 @js_set_delete_u32(i64, i32) +declare i32 @js_set_delete_f32(i64, float) +declare i32 @js_set_delete_bool(i64, i32) +declare i32 @js_set_size(i64) +declare i64 @js_set_union(i64, double) +declare i64 @js_set_intersection(i64, double) +declare i64 @js_set_difference(i64, double) +declare i64 @js_set_symmetric_difference(i64, double) +declare i32 @js_set_is_subset_of(i64, double) +declare i32 @js_set_is_superset_of(i64, double) +declare i32 @js_set_is_disjoint_from(i64, double) +declare i64 @js_string_to_lower_case(i64) +declare i64 @js_string_to_upper_case(i64) +declare i64 @js_string_to_locale_lower_case(i64, double) +declare i64 @js_string_to_locale_upper_case(i64, double) +declare void @js_string_validate_collator_args(double, double) +declare i64 @js_string_trim(i64) +declare i64 @js_string_trim_start(i64) +declare i64 @js_string_trim_end(i64) +declare i64 @js_string_big(i64) +declare i64 @js_string_blink(i64) +declare i64 @js_string_bold(i64) +declare i64 @js_string_fixed(i64) +declare i64 @js_string_italics(i64) +declare i64 @js_string_small(i64) +declare i64 @js_string_strike(i64) +declare i64 @js_string_sub(i64) +declare i64 @js_string_sup(i64) +declare i64 @js_string_anchor(i64, i64) +declare i64 @js_string_link(i64, i64) +declare i64 @js_string_fontcolor(i64, i64) +declare i64 @js_string_fontsize(i64, i64) +declare i64 @js_string_char_at(i64, i32) +declare double @js_string_index_get(i64, double) +declare double @js_string_index_get_boxed(double, double) +declare i32 @js_string_index_to_i32(double) +declare i32 @js_string_end_index_to_i32(double, i32) +declare double @js_dyn_index_get(double, double) +declare double @js_dyn_index_set(double, double, double) +declare i64 @js_string_to_char_array(i64) +declare i64 @js_string_repeat(i64, double) +declare i64 @js_string_replace_string(i64, i64, i64) +declare i64 @js_string_replace_all_string(i64, i64, i64) +declare i32 @js_string_equals(i64, i64) +declare i32 @js_string_compare(i64, i64) +declare i32 @js_jsvalue_equals(double, double) +declare i32 @js_string_compare_value(double, double) +declare i64 @js_jsvalue_to_string_radix(double, double) +declare double @js_math_random() +declare double @js_webassembly_validate(double) +declare double @js_webassembly_compile(double) +declare double @js_webassembly_module_new(double) +declare double @js_webassembly_module_exports(double) +declare double @js_webassembly_module_imports(double) +declare double @js_webassembly_module_custom_sections(double, double) +declare double @js_webassembly_instantiate(double, double) +declare double @js_wasi_emit_warning() +declare double @js_webassembly_call_export_0(double, double) +declare double @js_webassembly_call_export_1(double, double, double) +declare double @js_webassembly_call_export_2(double, double, double, double) +declare double @js_webassembly_call_export_3(double, double, double, double, double) +declare double @js_webassembly_call_export_4(double, double, double, double, double, double) +declare void @js_console_log_spread(i64) +declare void @js_console_info_spread(i64) +declare void @js_console_debug_spread(i64) +declare void @js_console_error_spread(i64) +declare void @js_console_warn_spread(i64) +declare double @js_util_format(i64) +declare double @js_util_format_with_options(double, i64) +declare double @js_util_inspect(double, double) +declare double @js_util_debuglog(double, double) +declare double @js_util_diff(double, double) +declare double @js_util_inherits(double, double) +declare double @js_util_is_deep_strict_equal(double, double) +declare double @js_util_strip_vt_control_characters(double) +declare double @js_util_style_text(double, double, double) +declare double @js_util_get_call_sites(double, double) +declare double @js_util_promisify(double) +declare double @js_util_callbackify(double) +declare double @js_util_deprecate(double, double, double) +declare double @js_util_aborted(double, double) +declare double @js_util_transferable_abort_controller() +declare double @js_util_transferable_abort_signal(double) +declare double @js_util_parse_args(double) +declare double @js_boxed_number_new(double) +declare double @js_boxed_string_new(double, i32) +declare double @js_boxed_boolean_new(double) +declare double @js_util_types_is_arguments_object(double) +declare double @js_util_types_is_promise(double) +declare double @js_util_types_is_big_int_object(double) +declare double @js_util_types_is_symbol_object(double) +declare double @js_util_types_is_array_buffer(double) +declare double @js_util_types_is_shared_array_buffer(double) +declare double @js_util_types_is_any_array_buffer(double) +declare double @js_util_types_is_array_buffer_view(double) +declare double @js_util_types_is_data_view(double) +declare double @js_util_types_is_typed_array(double) +declare double @js_util_types_is_uint8_array(double) +declare double @js_util_types_is_int8_array(double) +declare double @js_util_types_is_int16_array(double) +declare double @js_util_types_is_uint16_array(double) +declare double @js_util_types_is_int32_array(double) +declare double @js_util_types_is_uint32_array(double) +declare double @js_util_types_is_float16_array(double) +declare double @js_util_types_is_float32_array(double) +declare double @js_util_types_is_float64_array(double) +declare double @js_util_types_is_uint8_clamped_array(double) +declare double @js_util_types_is_big_int64_array(double) +declare double @js_util_types_is_big_uint64_array(double) +declare double @js_util_types_is_map(double) +declare double @js_util_types_is_weak_map(double) +declare double @js_util_types_is_set(double) +declare double @js_util_types_is_weak_set(double) +declare double @js_util_types_is_date(double) +declare double @js_util_types_is_reg_exp(double) +declare double @js_util_types_is_async_function(double) +declare double @js_util_types_is_generator_function(double) +declare double @js_util_types_is_generator_object(double) +declare double @js_util_types_is_native_error(double) +declare double @js_util_types_is_number_object(double) +declare double @js_util_types_is_string_object(double) +declare double @js_util_types_is_boolean_object(double) +declare double @js_util_types_is_boxed_primitive(double) +declare double @js_util_types_is_external(double) +declare double @js_util_types_is_module_namespace_object(double) +declare double @js_util_types_is_key_object(double) +declare double @js_util_types_is_crypto_key(double) +declare double @js_util_types_is_proxy(double) +declare double @js_util_types_is_map_iterator(double) +declare double @js_util_types_is_set_iterator(double) +declare double @js_data_view_new(double, double, double) +declare double @js_data_view_get_direct(double, double, double, i32, i32) +declare double @js_data_view_set_direct(double, double, double, double, i32, i32) +declare i64 @js_getenv(i64) +declare double @js_getenv_value(i64) +declare void @js_setenv(i64, double) +declare void @js_removeenv(i64) +declare double @js_process_exit_code_get() +declare double @js_process_exit_code_set(double) +declare void @js_console_table(double) +declare void @js_console_table_with_properties(double, double) +declare void @js_console_trace(double) +declare void @js_console_trace_spread(i64) +declare i64 @js_process_cwd() +declare i64 @js_process_argv() +declare double @js_process_pid() +declare double @js_process_ppid() +declare double @js_process_uptime() +declare i64 @js_process_version() +declare double @js_process_versions() +declare double @js_process_memory_usage() +declare double @js_bigint_as_int_n_call(double, double) +declare double @js_bigint_as_uint_n_call(double, double) +declare double @js_v8_serialize(double) +declare double @js_v8_deserialize(double) +declare double @js_v8_get_heap_statistics() +declare double @js_v8_get_heap_code_statistics() +declare double @js_v8_get_heap_space_statistics() +declare double @js_v8_cached_data_version_tag() +declare double @js_v8_get_heap_snapshot(double) +declare double @js_v8_write_heap_snapshot(double, double) +declare double @js_v8_gc_profiler_new() +declare double @js_v8_gc_profiler_start(double) +declare double @js_v8_gc_profiler_stop(double) +declare double @js_v8_gc_profiler_report() +declare double @js_v8_serializer_new(double) +declare double @js_v8_deserializer_new(double) +declare double @js_v8_noop_undefined() +declare double @js_v8_is_building_snapshot() +declare double @js_v8_namespace(ptr, i64) +declare double @js_v8_throw_not_building_snapshot() +declare double @js_v8_promise_hook_register() +declare double @js_v8_promise_hooks_on_init(double) +declare double @js_v8_promise_hooks_on_before(double) +declare double @js_v8_promise_hooks_on_after(double) +declare double @js_v8_promise_hooks_on_settled(double) +declare double @js_v8_promise_hooks_create_hook(double) +declare double @js_process_thread_cpu_usage(double) +declare double @js_process_available_memory() +declare double @js_process_constrained_memory() +declare double @js_process_source_maps_enabled() +declare double @js_process_set_source_maps_enabled(double) +declare double @js_process_has_uncaught_exception_capture_callback() +declare double @js_process_set_uncaught_exception_capture_callback(double) +declare double @js_process_add_uncaught_exception_capture_callback(double) +declare double @js_process_getuid() +declare double @js_process_geteuid() +declare double @js_process_getgid() +declare double @js_process_getegid() +declare void @js_process_emit_warning(double, double, double) +declare double @js_process_cpu_usage(double) +declare double @js_process_resource_usage() +declare double @js_process_active_resources_info() +declare double @js_process_env() +declare double @js_process_hrtime_bigint() +declare double @js_process_hrtime(double) +declare double @js_process_title() +declare void @js_process_set_title(double) +declare void @js_process_chdir(i64) +declare void @js_process_chdir_jsv(double) +declare double @js_process_kill(double, double) +declare void @js_process_exit(double) +declare void @js_process_abort() +declare double @js_process_umask() +declare double @js_process_umask_set(double) +declare double @js_process_on(i64, i64) +declare double @js_process_add_listener(i64, i64) +declare double @js_process_once(i64, i64) +declare double @js_process_prepend_listener(i64, i64) +declare double @js_process_prepend_once_listener(i64, i64) +declare double @js_process_emit(i64, i64) +declare void @js_process_emit_before_exit(double) +declare void @js_process_run_finalization_exit() +declare void @js_trace_events_flush_output() +declare void @js_promise_report_unhandled_rejections() +declare i32 @js_process_pending_exit_code() +declare void @js_gc_release_current_thread_collection_side_allocations() +declare double @js_process_remove_listener(i64, i64) +declare double @js_process_off(i64, i64) +declare double @js_process_remove_all_listeners(i64) +declare double @js_process_listener_count(i64, i64) +declare i64 @js_process_listeners(i64) +declare i64 @js_process_raw_listeners(i64) +declare i64 @js_process_event_names() +declare double @js_process_set_max_listeners(double) +declare double @js_process_get_max_listeners() +declare double @js_process_get_builtin_module(double) +declare double @js_process_get_builtin_module_devirt(double) +declare double @js_process_execve(double, double, double) +declare double @js_module_is_builtin(double) +declare double @js_module_find_package_json(double, double) +declare double @js_module_register(double, double, double) +declare double @js_module_register_hooks(double) +declare void @js_process_next_tick(i64, i64) +declare double @js_process_stdin() +declare double @js_process_stdout() +declare double @js_process_stderr() +declare double @js_readline_set_raw_mode(double) +declare void @js_readline_stdin_on(i64, i64) +declare double @js_readline_stdin_remove_listener(i64, i64) +declare double @js_readline_stdin_pause() +declare double @js_readline_stdin_resume() +declare double @js_readline_stdin_unref() +declare double @js_readline_stdin_ref() +declare double @js_readline_stdin_destroy() +declare double @js_tty_isatty(double) +declare double @js_tty_read_stream_new(double) +declare double @js_tty_write_stream_new(double) +declare double @js_wasi_constructor_call(double) +declare double @js_process_stdin_isatty() +declare double @js_process_stdout_isatty() +declare double @js_process_stderr_isatty() +declare double @js_process_stdout_columns() +declare double @js_process_stdout_rows() +declare double @js_process_stdout_on(i64, i64) +declare i64 @js_os_platform() +declare i64 @js_os_arch() +declare i64 @js_os_type() +declare i64 @js_os_release() +declare i64 @js_os_hostname() +declare i64 @js_os_eol() +declare double @js_os_available_parallelism() +declare i64 @js_os_endianness() +declare i64 @js_os_dev_null() +declare i64 @js_os_machine() +declare i64 @js_os_loadavg() +declare i64 @js_os_version() +declare i64 @js_box_alloc_bits(i64) +declare i64 @js_box_get_bits(i64) +declare void @js_box_set_bits(i64, i64) +declare i64 @js_box_alloc(double) +declare double @js_box_get(i64) +declare void @js_box_set(i64, double) +declare i64 @js_i32_box_alloc(i32) +declare i32 @js_i32_box_get(i64) +declare void @js_i32_box_set(i64, i32) +declare i64 @js_bool_box_alloc(i32) +declare i32 @js_bool_box_get(i64) +declare void @js_bool_box_set(i64, i32) +declare i64 @js_arguments_object_alloc(double, double, i32) +declare void @js_arguments_object_map_index(i64, i32, i64) +declare i64 @js_array_like_to_array(double) +declare i32 @js_object_get_class_id(i64) +declare i64 @js_object_alloc_with_parent(i32, i32, i32) +declare i64 @js_object_alloc_class_with_keys(i32, i32, i32, ptr, i32) +declare i64 @js_object_alloc_class_dynamic_parent(i32, i32, ptr, i32) +declare i64 @js_object_alloc_class_inline_keys(i32, i32, i32, i64) +declare i64 @js_build_class_keys_array(i32, i32, ptr, i32) +declare ptr @js_inline_arena_state() +declare ptr @js_inline_arena_slow_alloc(ptr, i64, i64) +declare i32 @js_object_delete_field(i64, i64) +declare i32 @js_object_delete_field_value(double, i64) +declare i32 @js_object_delete_dynamic_value(double, double) +declare double @js_delete_result(i32, i32) +declare i64 @js_eq(i64, i64) +declare i64 @js_loose_eq(i64, i64) +declare i64 @js_number_to_fixed(double, double) +declare i64 @js_string_replace_regex(i64, i64, i64) +declare i64 @js_string_replace_all_regex(i64, i64, i64) +declare double @js_array_at(i64, double) +declare double @js_date_get_time(double) +declare double @js_date_get_full_year(double) +declare double @js_date_get_month(double) +declare double @js_date_get_date(double) +declare double @js_date_get_day(double) +declare double @js_date_get_hours(double) +declare double @js_date_get_minutes(double) +declare double @js_date_get_seconds(double) +declare double @js_date_get_milliseconds(double) +declare double @js_date_get_utc_day(double) +declare double @js_date_get_utc_full_year(double) +declare double @js_date_get_utc_month(double) +declare double @js_date_get_utc_date(double) +declare double @js_date_get_utc_hours(double) +declare double @js_date_get_utc_minutes(double) +declare double @js_date_get_utc_seconds(double) +declare double @js_date_get_utc_milliseconds(double) +declare double @js_date_value_of(double) +declare double @js_date_get_timezone_offset(double) +declare double @js_date_coerce_number(double) +declare double @js_rel_lt(double, double) +declare double @js_rel_le(double, double) +declare double @js_rel_gt(double, double) +declare double @js_rel_ge(double, double) +declare i64 @js_date_to_string(double) +declare i64 @js_date_to_iso_string(double) +declare i64 @js_date_to_iso_string_or_throw(double) +declare double @js_date_new_from_timestamp(double) +declare double @js_date_new_from_value(double) +declare i32 @js_array_indexOf_f64(i64, double) +declare i64 @js_array_indexOf_jsvalue(i64, double, double, i32) +declare i64 @js_array_last_index_of_jsvalue(i64, double, double, i32) +declare i32 @js_array_includes_f64(i64, double) +declare i32 @js_array_includes_jsvalue(i64, double, double, i32) +declare i32 @js_map_size(i64) +declare void @js_map_clear(i64) +declare void @js_set_clear(i64) +declare i64 @js_map_entries(i64) +declare i64 @js_map_keys(i64) +declare i64 @js_map_values(i64) +declare double @js_map_entry_key_at(i64, i32) +declare double @js_map_entry_value_at(i64, i32) +declare double @js_map_find_key_index(double, double) +declare double @js_set_find_value_index(double, double) +declare void @js_map_foreach(i64, double, double) +declare void @js_set_foreach(i64, double, double) +declare i64 @js_map_entries_iter_obj(i64) +declare i64 @js_map_keys_iter_obj(i64) +declare i64 @js_map_values_iter_obj(i64) +declare i64 @js_set_values_iter_obj(i64) +declare i64 @js_set_keys_iter_obj(i64) +declare i64 @js_set_entries_iter_obj(i64) +declare i64 @js_set_to_array(i64) +declare double @js_set_value_at(i64, i32) +declare i64 @js_array_splice(i64, i32, i32, ptr, i32, ptr) +declare i32 @js_array_splice_delete_count(double) +declare double @js_parse_int(i64, double) +declare double @js_parse_float(i64) +declare double @js_array_reduce(i64, i64, i32, double) +declare double @js_array_reduce_right(i64, i64, i32, double) +declare i64 @js_array_sort_default(i64) +declare i64 @js_array_reverse(i64) +declare double @js_array_reverse_value(double) +declare i64 @js_array_flat(i64) +declare i64 @js_array_flat_depth(i64, double) +declare i64 @js_array_flatMap(i64, i64) +declare i64 @js_array_sort_with_comparator(i64, i64) +declare i64 @js_validate_array_comparator(double) +declare i64 @js_validate_array_callback(double) +declare i64 @js_validate_array_map_callback(i64, double) +declare i64 @js_array_to_reversed(i64) +declare i64 @js_array_to_sorted_default(i64) +declare i64 @js_array_to_sorted_with_comparator(i64, i64) +declare i64 @js_array_to_spliced(i64, double, double, ptr, i32) +declare i64 @js_array_with(i64, double, double) +declare i64 @js_array_copy_within(i64, double, double, i32, double) +declare double @js_array_copy_within_value(double, double, double, i32, double) +declare i64 @js_regexp_new(i64, i64) +declare i64 @js_regexp_construct(double, double) +declare i64 @js_regexp_construct_call(double, double) +declare i32 @js_regexp_test(i64, i64) +declare double @js_regexp_escape(double) +declare i64 @js_get_string_pointer_unified(double) +declare i32 @js_switch_strict_equals(double, double) +declare i64 @js_value_to_str_ptr_for_ffi(double) +declare void @js_string_addref(i64) +declare void @js_string_addref_if_heap_string(double) +declare i64 @js_bigint_from_string(ptr, i32) +declare i64 @js_bigint_from_f64(double) +declare i64 @js_bigint_from_i128_parts(i64, i64) +declare i32 @js_bigint_cmp(i64, i64) +declare double @js_dynamic_add(double, double) +declare double @js_to_numeric(double) +declare double @js_numeric_step(double, i32) +declare double @js_dynamic_string_or_number_add(double, double) +declare double @js_dynamic_sub(double, double) +declare double @js_dynamic_mul(double, double) +declare double @js_dynamic_div(double, double) +declare double @js_dynamic_mod(double, double) +declare double @js_dynamic_bitand(double, double) +declare double @js_dynamic_bitor(double, double) +declare double @js_dynamic_bitxor(double, double) +declare double @js_dynamic_shl(double, double) +declare double @js_dynamic_shr(double, double) +declare double @js_dynamic_bitnot(double) +declare double @js_dynamic_pow(double, double) +declare double @js_dynamic_ushr(double, double) +declare double @js_instanceof(double, i32) +declare double @js_instanceof_dynamic(double, double) +declare double @js_instanceof_noncallable_rhs() +declare void @js_register_class_extends_error(i32) +declare void @js_register_class_extends_data_view(i32) +declare void @js_register_class_id(i32) +declare void @js_register_class_name(i32, ptr, i32) +declare void @js_register_anon_shape_class_id(i32) +declare double @js_get_global_this_builtin_value(ptr, i64) +declare double @js_promise_static_function_value(ptr, i64) +declare double @js_builtin_prototype_method_value(ptr, i64, ptr, i64) +declare void @js_register_class_parent(i32, i32) +declare void @js_register_class_parent_dynamic(i32, double) +declare double @js_get_dynamic_parent_value(i32) +declare void @js_class_register_capture_values(i32, ptr, i64) +declare void @js_class_object_refresh_capture_values(double, i64, double) +declare void @js_tdz_suppress_begin() +declare void @js_tdz_suppress_end() +declare double @js_class_capture_value(i32, i32) +declare double @js_class_capture_value_for_receiver(double, i32, i32) +declare double @js_class_capture_value_or(i32, i32, double) +declare double @js_param_or_class_capture_value(double, i32, i32) +declare void @js_super_construct_apply(i32, double, double) +declare double @js_super_method_call_dynamic(i32, ptr, i64, double, ptr, i64) +declare double @js_super_method_call_dynamic_apply(i32, ptr, i64, double, double) +declare i64 @js_array_push_spread_any(i64, double) +declare i32 @js_set_function_prototype(double, double) +declare void @js_register_prototype_method(i32, ptr, i64, double) +declare i32 @js_register_function_prototype_method(double, ptr, i64, double) +declare double @js_new_function_construct(double, ptr, i64) +declare double @js_function_ctor_from_strings(ptr, i64) +declare double @js_new_function_construct_apply(double, double) +declare double @js_throw_not_a_constructor() +declare double @js_new_target_value() +declare double @js_get_function_prototype_method(double, ptr, i64) +declare double @js_function_prototype_value_for_read(double) +declare i64 @js_typeerror_new(i64) +declare i64 @js_rangeerror_new(i64) +declare i64 @js_syntaxerror_new(i64) +declare i64 @js_referenceerror_new(i64) +declare double @js_throw_symbol_constructor_type_error() +declare double @js_throw_bigint_constructor_type_error() +declare double @js_throw_strict_eval_arguments_syntax_error() +declare double @js_throw_eval_syntax_error(double) +declare double @js_throw_restricted_function_property_assignment() +declare double @js_throw_math_constructor_type_error() +declare double @js_throw_json_constructor_type_error() +declare double @js_webcrypto_illegal_constructor() +declare double @js_throw_type_error_const_assignment(double) +declare double @js_throw_reference_error_unresolvable_assignment(double) +declare double @js_throw_reference_error_unresolved_get() +declare double @js_with_implicit_unset() +declare double @js_with_implicit_read(double, double) +declare double @js_iterator_result_validate(double) +declare double @js_global_get_or_throw_unresolved(double) +declare double @js_module_ambient_require() +declare double @js_module_ambient_require_apply(double) +declare double @js_module_dynamic_import_fallback(double) +declare double @js_module_dynamic_import_deferred(double, double) +declare double @js_module_create_require_devirt(double) +declare double @js_global_get_optional(double) +declare double @js_global_update(double, double, double) +declare double @js_global_assign_existing_or_throw(double, double) +declare double @js_throw_reference_error_this_before_super() +declare double @js_throw_reference_error_super_delete() +declare double @js_throw_reference_error_unresolved_assignment() +declare i64 @js_evalerror_new(i64) +declare i64 @js_urierror_new(i64) +declare i64 @js_weakmap_new() +declare i64 @js_weakset_new() +declare double @js_weakmap_init_iterable(double, double) +declare double @js_weakset_init_iterable(double, double) +declare double @js_weakmap_set(double, double, double) +declare double @js_weakmap_get(double, double) +declare double @js_weakmap_has(double, double) +declare double @js_weakmap_delete(double, double) +declare double @js_weakset_add(double, double) +declare double @js_weakset_has(double, double) +declare double @js_weakset_delete(double, double) +declare double @js_weak_throw_primitive() +declare i64 @js_buffer_from_string(i64, i32) +declare i32 @js_encoding_tag_from_value(double) +declare i64 @js_value_to_string_with_encoding(double, i32) +declare i64 @js_value_to_string_with_encoding_or_radix(double, i32, double) +declare i64 @js_object_values(i64) +declare i64 @js_object_values_value(double) +declare i64 @js_object_entries(i64) +declare i64 @js_object_entries_value(double) +declare i64 @js_path_join(i64, i64) +declare i64 @js_path_win32_join(i64, i64) +declare i64 @js_path_win32_dirname(i64) +declare i64 @js_path_win32_basename(i64) +declare i64 @js_path_win32_basename_ext(i64, i64) +declare i64 @js_path_win32_extname(i64) +declare i32 @js_path_win32_is_absolute(i64) +declare i64 @js_path_win32_normalize(i64) +declare i64 @js_path_win32_parse(i64) +declare i64 @js_path_win32_format(double) +declare i64 @js_path_win32_relative(i64, i64) +declare i64 @js_path_win32_relative_checked(double, double) +declare i64 @js_path_win32_resolve(i64) +declare i64 @js_path_win32_resolve_join(i64, i64) +declare i64 @js_path_win32_to_namespaced_path(i64) +declare double @js_path_win32_to_namespaced_path_value(double) +declare i32 @js_path_win32_matches_glob(i64, i64) +declare i64 @js_path_win32_sep_get() +declare i64 @js_path_win32_delimiter_get() +declare i64 @js_path_dirname(i64) +declare i64 @js_path_resolve(i64) +declare i64 @js_path_relative(i64, i64) +declare i64 @js_path_relative_checked(double, double) +declare i64 @js_path_to_namespaced_path(i64) +declare double @js_path_to_namespaced_path_value(double) +declare i32 @js_path_matches_glob(i64, i64) +declare i64 @js_path_resolve_join(i64, i64) +declare double @js_object_from_entries(double) +declare i64 @js_string_match(i64, i64) +declare i64 @js_string_match_all(i64, i64) +declare i64 @js_string_match_all_value(i64, double) +declare double @llvm.log.f64(double) +declare double @llvm.log2.f64(double) +declare double @llvm.log10.f64(double) +declare double @llvm.exp.f64(double) +declare double @llvm.sin.f64(double) +declare double @llvm.cos.f64(double) +declare i64 @js_path_basename(i64) +declare i64 @js_path_basename_ext(i64, i64) +declare i64 @js_path_extname(i64) +declare i64 @js_path_sep_get() +declare i64 @js_path_delimiter_get() +declare i64 @js_path_parse(i64) +declare i64 @js_json_parse(i64) +declare i64 @js_json_text_to_string(double) +declare double @js_json_raw_json(double) +declare double @js_json_is_raw_json(double) +declare i64 @js_json_parse_or_null(i64) +declare i64 @js_json_parse_typed_array(i64, i64, i32, i32) +declare i64 @js_date_to_date_string(double) +declare i64 @js_date_to_time_string(double) +declare i64 @js_date_to_utc_string(double) +declare i64 @js_date_to_locale_date_string(double) +declare i64 @js_date_to_locale_time_string(double) +declare i64 @js_date_to_json(double) +declare i64 @js_regexp_exec(i64, i64) +declare i64 @js_number_to_precision(double, double) +declare i64 @js_number_to_exponential(double, double) +declare double @js_date_new() +declare double @js_number_is_integer(double) +declare double @js_number_is_nan(double) +declare double @js_number_is_safe_integer(double) +declare double @js_date_parse(i64) +declare double @js_date_utc(ptr, i32) +declare double @js_date_new_local_components(double, double, double, double, double, double, double) +declare double @js_date_apply_setter(double, i32, i32, ptr, i32) +declare double @js_math_clz32(double) +declare double @js_math_cbrt(double) +declare double @js_math_fround(double) +declare double @js_math_f16round(double) +declare double @js_math_sinh(double) +declare double @js_math_cosh(double) +declare double @js_math_tanh(double) +declare double @js_math_asinh(double) +declare double @js_math_acosh(double) +declare double @js_math_atanh(double) +declare double @js_math_hypot(double, double) +declare double @js_object_is(double, double) +declare i64 @js_path_normalize(i64) +declare i64 @js_path_format(double) +declare i32 @js_path_is_absolute(i64) +declare i64 @js_encode_uri(double) +declare i64 @js_decode_uri(double) +declare i64 @js_encode_uri_component(double) +declare i64 @js_decode_uri_component(double) +declare i64 @js_text_encoder_new() +declare i64 @js_text_decoder_new(double, double, double) +declare i64 @js_text_encoder_encode_llvm(double) +declare i64 @js_text_decoder_decode_llvm(double, double) +declare i64 @js_text_decoder_encoding(double) +declare double @js_text_decoder_fatal(double) +declare double @js_text_decoder_ignore_bom(double) +declare void @js_queue_microtask(i64) +declare void @js_queue_next_tick(i64) +declare void @js_queue_next_tick_args(i64, ptr, i32) +declare void @js_drain_queued_microtasks() +declare i64 @js_uint8array_from_array(i64) +declare i64 @js_uint8array_alloc(i32) +declare i64 @js_uint8array_new(double) +declare i64 @js_uint8array_view(double, double, double) +declare i64 @js_typed_array_new_empty(i32, i32) +declare i64 @js_typed_array_new_from_array(i32, i64) +declare i64 @js_typed_array_new(i32, double) +declare i64 @js_typed_array_view(i32, double, double, double) +declare i32 @js_typed_array_length(i64) +declare double @js_typed_array_get(i64, i32) +declare i32 @js_typed_array_read_int32(i64, i32) +declare double @js_typed_array_read_f64(i64, i32) +declare double @js_typed_array_index_get_dynamic(i64, double) +declare double @js_typed_array_at(i64, double) +declare void @js_typed_array_set(i64, i32, double) +declare double @js_typed_array_index_set_dynamic(i64, double, double) +declare i32 @js_uint8array_get(i64, i32) +declare double @js_uint8array_index_get_value(i64, i32) +declare void @js_uint8array_set(i64, i32, i32) +declare i64 @js_native_arena_alloc(i64) +declare i64 @js_native_arena_view(i64, i32, i64, i64) +declare i64 @js_native_pod_view(i64, i64, i64, i64, i64, i64) +declare ptr @js_native_abi_check_pod_view_data_ptr(double, i64) +declare i64 @js_native_abi_check_pod_view_record_count(double, i64) +declare void @js_native_arena_dispose(i64) +declare void @js_native_memory_fill_u32(i64, double) +declare void @js_native_memory_copy(i64, i64) +declare i64 @js_typed_array_to_reversed(i64) +declare i64 @js_typed_array_to_sorted_default(i64) +declare i64 @js_typed_array_to_sorted_with_comparator(i64, i64) +declare i64 @js_typed_array_with(i64, double, double) +declare double @js_typed_array_find_last(i64, i64) +declare double @js_typed_array_find_last_index(i64, i64) +declare double @js_typed_array_set_from(i64, double, double) +declare i64 @js_typed_array_subarray(i64, i32, double, i32, double) +declare double @js_object_has_own(double, double) +declare double @js_object_property_is_enumerable(double, double) +declare double @js_object_define_getter(double, double, double) +declare double @js_object_define_setter(double, double, double) +declare double @js_object_lookup_getter(double, double) +declare double @js_object_lookup_setter(double, double) +declare double @js_object_get_own_field_or_undef(double, ptr, i64) +declare double @js_unresolved_namespace_stub() +declare double @js_node_submodule_export_as_function(ptr, i32, ptr, i32) +declare double @js_node_submodule_namespace_member(ptr, i32, ptr, i32) +declare double @js_node_submodule_namespace(ptr, i32) +declare void @js_node_submod_install_vm() +declare void @js_node_submod_install_timers() +declare void @js_node_submod_install_timers_promises() +declare void @js_node_submod_install_fs_promises() +declare void @js_node_submod_install_readline_promises() +declare void @js_node_submod_install_stream_promises() +declare void @js_node_submod_install_stream_consumers() +declare void @js_node_submod_install_stream_web() +declare void @js_node_submod_install_hono_jsx_server() +declare void @js_node_submod_install_hono_jsx_streaming() +declare void @js_node_submod_install_sys() +declare void @js_node_submod_install_diagnostics_channel() +declare void @js_node_submod_install_trace_events() +declare void @js_node_submod_install_test() +declare void @js_node_submod_install_test_reporters() +declare void @js_node_submod_install_all() +declare void @js_node_submod_enable_install_all() +declare double @js_unresolved_default_call() +declare double @js_get_global_this() +declare double @js_module_top_this() +declare double @js_global_or_console_property_by_name(i64) +declare void @js_class_register_static_symbol(i32, double, double) +declare void @js_register_class_computed_method(i64, double, i64, i64, i64, i64) +declare void @js_register_class_computed_accessor(i64, double, i64, i64, i64) +declare void @js_class_register_static_field(i32, ptr, i64, double) +declare double @js_object_define_property(double, double, double) +declare double @js_object_get_own_property_descriptor(double, double) +declare double @js_object_get_own_property_descriptors(double) +declare double @js_object_get_own_property_names(double) +declare double @js_symbol_new(double) +declare double @js_symbol_new_empty() +declare double @js_symbol_for(double) +declare double @js_symbol_computed_member(double, double) +declare double @js_symbol_key_for(double) +declare double @js_symbol_description(double) +declare i64 @js_symbol_to_string(double) +declare i32 @js_symbol_equals(double, double) +declare i32 @js_is_symbol(double) +declare i64 @js_object_get_own_property_symbols(double) +declare double @js_object_set_symbol_property(double, double, double) +declare double @js_to_property_key(double) +declare double @js_object_set_property_key(double, double, double) +declare double @js_object_get_property_key(double, double) +declare double @js_object_set_property_key_method(double, double, double) +declare double @js_object_super_get(double, double, double) +declare double @js_object_super_put_value_set(double, double, double, double, i32) +declare double @js_object_super_call(double, double, double, ptr, i64) +declare double @js_object_literal_infer_computed_function_name(double, double) +declare double @js_object_get_symbol_property(double, double) +declare double @js_object_create(double) +declare double @js_object_create_with_props(double, double) +declare double @js_object_freeze(double) +declare double @js_object_seal(double) +declare double @js_object_prevent_extensions(double) +declare void @js_object_copy_own_fields(i64, double) +declare double @js_object_assign_validate_target(double) +declare double @js_object_assign_one(double, double) +declare double @js_string_at(i64, i32) +declare double @js_string_code_point_at(i64, i32) +declare i64 @js_string_from_code_point(double) +declare i64 @js_string_raw(double, double) +declare i64 @js_string_from_char_code(double) +declare i64 @js_string_from_char_code_array(double) +declare double @js_string_char_code_at(i64, i32) +declare i32 @js_string_last_index_of(i64, i64) +declare i32 @js_string_last_index_of_from(i64, i64, double, i32) +declare double @js_string_locale_compare(i64, i64) +declare double @js_string_locale_compare_opts(i64, i64, double) +declare i64 @js_string_normalize(i64, double) +declare i64 @js_string_pad_start(i64, double, i64) +declare i64 @js_string_pad_end(i64, double, i64) +declare i64 @js_string_pad_fill(double) +declare double @js_string_is_well_formed(i64) +declare i64 @js_string_to_well_formed(i64) +declare i32 @js_string_search_regex(i64, i64) +declare i32 @js_string_search_value(i64, double) +declare i64 @js_string_match_value(i64, double) +declare double @js_regexp_exec_get_index() +declare i64 @js_regexp_exec_get_groups() +declare double @js_regexp_get_last_index(i64) +declare void @js_regexp_set_last_index(i64, double) +declare i64 @js_regexp_get_source(i64) +declare i64 @js_regexp_get_flags(i64) +declare i64 @js_string_replace_regex_named(i64, i64, i64) +declare i64 @js_string_replace_all_regex_named(i64, i64, i64) +declare i64 @js_string_replace_string_fn(i64, i64, double) +declare i64 @js_string_replace_string_dyn(i64, i64, double) +declare i64 @js_string_replace_all_string_dyn(i64, i64, double) +declare i64 @js_string_replace_regex_dyn(i64, i64, double) +declare i64 @js_string_replace_all_regex_dyn(i64, i64, double) +declare i64 @js_string_replace_search_dyn(i64, double, double) +declare i64 @js_string_replace_all_search_dyn(i64, double, double) +declare i64 @js_string_replace_all_string_fn(i64, i64, double) +declare i64 @js_string_replace_regex_fn(i64, i64, double) +declare i64 @js_string_replace_all_regex_fn(i64, i64, double) +declare double @js_structured_clone(double) +declare double @js_structured_clone_with_options(double, double) +declare double @js_generator_attach_prototype(double, i32) +declare double @js_generator_attach_closure_prototype(double, i64) +declare i64 @js_weakref_new(double) +declare double @js_weakref_deref(double) +declare i64 @js_finreg_new(double) +declare double @js_finreg_register(double, double, double, double) +declare double @js_finreg_unregister(double, double) +declare i64 @js_atob(double) +declare i64 @js_btoa(double) +declare double @js_object_is_frozen(double) +declare double @js_object_is_sealed(double) +declare double @js_object_is_extensible(double) +declare i64 @js_aggregateerror_new(i64, i64) +declare i64 @js_error_new_with_cause(i64, double) +declare i64 @js_aggregateerror_new_full(double, i64, double) +declare i64 @js_error_new_kind_with_options(i32, i64, double) +declare double @js_error_is_error(double) +declare i64 @js_error_get_errors(i64) +declare i64 @js_crypto_sha256(i64) +declare i64 @js_crypto_sha256_bytes(i64) +declare i64 @js_crypto_md5(i64) +declare i64 @js_crypto_hmac_sha256(i64, i64) +declare i64 @js_crypto_hmac_sha256_bytes(i64, i64) +declare void @js_runtime_validate_string_arg(double, ptr, i32) +declare void @js_set_call_location(ptr, i64, i32) +declare void @js_runtime_validate_crypto_key_arg(double, ptr, i32) +declare void @js_runtime_validate_integer_arg(double, ptr, i32, double, double) +declare i64 @js_crypto_pbkdf2_bytes(i64, i64, double, double, i64) +declare double @js_crypto_pbkdf2_async_alg(i64, i64, double, double, i64, double) +declare i64 @js_crypto_argon2_sync(i64, double) +declare double @js_crypto_argon2_async(i64, double, double) +declare i64 @js_crypto_encapsulate(double) +declare double @js_crypto_encapsulate_async(double, double) +declare i64 @js_crypto_decapsulate(double, double) +declare double @js_crypto_decapsulate_async(double, double, double) +declare i64 @js_crypto_hkdf_bytes_alg(i64, i64, i64, i64, double) +declare double @js_crypto_hkdf_async_alg(i64, i64, i64, i64, double, double) +declare i64 @js_crypto_scrypt_bytes(i64, i64, double, i64) +declare double @js_crypto_scrypt_async(i64, i64, double, double) +declare i64 @js_crypto_sign_rsa_sha256(i64, i64, double) +declare double @js_crypto_sign_async(i64, i64, double, double) +declare double @js_crypto_verify_rsa_sha256(i64, i64, double, i64) +declare double @js_crypto_verify_async(i64, i64, double, i64, double) +declare i64 @js_crypto_public_encrypt(i64, i64) +declare i64 @js_crypto_private_decrypt(i64, i64) +declare i64 @js_crypto_private_encrypt(i64, i64) +declare i64 @js_crypto_public_decrypt(i64, i64) +declare i64 @js_crypto_create_public_key(i64) +declare i64 @js_crypto_create_private_key_value(double) +declare i64 @js_crypto_create_public_key_value(double) +declare i64 @js_crypto_generate_key_pair_sync_rsa(double) +declare i64 @js_crypto_generate_key_pair_sync_ec_p256(double) +declare i64 @js_crypto_generate_key_pair_sync_ed25519(double) +declare i64 @js_crypto_generate_key_pair_sync_x25519(double) +declare double @js_crypto_generate_key_pair_async(i64, double, double) +declare i64 @js_crypto_diffie_hellman(double) +declare double @js_crypto_get_cipher_info(double, double) +declare i64 @js_crypto_get_curves() +declare i64 @js_crypto_secure_heap_used() +declare i64 @js_crypto_random_bytes_buffer(double) +declare double @js_crypto_random_bytes_async(double, double) +declare i64 @js_crypto_random_uuid(double) +declare i64 @js_crypto_random_uuidv7() +declare double @js_crypto_random_int(double, double) +declare double @js_crypto_random_int_async(double, double, double) +declare double @js_crypto_timing_safe_equal(double, double) +declare i64 @js_crypto_get_hashes() +declare i64 @js_crypto_get_ciphers() +declare double @js_crypto_generate_prime_sync(double, double) +declare double @js_crypto_generate_prime_async(double, double, double) +declare double @js_crypto_check_prime_sync(double, double) +declare double @js_crypto_check_prime_async(double, double, double) +declare i64 @js_crypto_create_secret_key(i64, i64) +declare i64 @js_crypto_generate_key_sync(i64, double) +declare double @js_crypto_generate_key_async(i64, double, double) +declare i64 @js_webcrypto_digest(double, double) +declare i64 @js_webcrypto_import_key(double, double, double, double, double) +declare i64 @js_webcrypto_export_key(double, double) +declare i64 @js_webcrypto_sign(double, double, double) +declare i64 @js_webcrypto_verify(double, double, double, double) +declare i64 @js_webcrypto_derive_bits(double, double, double) +declare i64 @js_webcrypto_derive_key(double, double, double, double, double) +declare i64 @js_webcrypto_encrypt(double, double, double) +declare i64 @js_webcrypto_decrypt(double, double, double) +declare i64 @js_webcrypto_generate_key(double, double, double) +declare i64 @js_webcrypto_wrap_key(double, double, double, double) +declare i64 @js_webcrypto_unwrap_key(double, double, double, double, double, double, double) +declare i64 @js_zlib_create_brotli_decompress(double) +declare double @js_crypto_random_fill_sync(double, double, double) +declare double @js_crypto_random_fill_async(double, double, double, double) +declare double @js_crypto_create_hash(i64) +declare double @js_crypto_create_hash_options(i64, double) +declare double @js_crypto_x509_new(i64) +declare double @js_crypto_certificate_verify_spkac(double) +declare double @js_crypto_certificate_export_public_key(double) +declare double @js_crypto_certificate_export_challenge(double) +declare double @js_crypto_create_sign(i64) +declare double @js_crypto_create_verify(i64) +declare double @js_crypto_create_ecdh(i64) +declare double @js_crypto_create_diffie_hellman(double, double, double) +declare double @js_crypto_get_diffie_hellman(double) +declare double @js_crypto_ecdh_convert_key(double, double, double, double, double) +declare double @js_crypto_create_hmac(i64, i64) +declare i64 @js_buffer_alloc(i32, i32) +declare i64 @js_buffer_alloc_fill_value(i32, double, i32) +declare i64 @js_array_buffer_new(i32) +declare i64 @js_shared_array_buffer_new(i32) +declare i64 @js_array_buffer_new_value(double) +declare i64 @js_shared_array_buffer_new_value(double) +declare i64 @js_json_stringify_full(double, double, double) +declare i64 @js_json_parse_with_reviver(i64, i64) +declare double @js_array_find(i64, i64) +declare i32 @js_array_findIndex(i64, i64) +declare double @js_array_find_last(i64, i64) +declare i32 @js_array_find_last_index(i64, i64) +declare double @js_array_some(i64, i64) +declare double @js_array_every(i64, i64) +declare i32 @js_promise_state(i64) +declare double @js_promise_value(i64) +declare double @js_promise_reason(i64) +declare i32 @js_value_is_promise(double) +declare double @js_assimilate_thenable(double) +declare i32 @js_promise_run_microtasks() +declare i32 @js_promise_run_microtasks_event_loop() +declare i32 @js_promise_run_microtasks_await_loop() +declare i32 @js_await_loop_tick_timers() +declare void @js_mark_entry_module_esm() +declare i32 @js_promise_run_promise_jobs() +declare void @js_run_stdlib_pump() +declare void @js_sleep_ms(double) +declare void @js_wait_for_event() +declare i32 @js_event_loop_host_driven() +declare void @js_unsettled_top_level_await_exit() +declare void @js_throw(double) +declare ptr @js_try_push() +declare i32 @_setjmp(ptr) #0 +declare void @js_try_end() +declare double @js_get_exception() +declare void @js_clear_exception() +declare i32 @js_has_exception() +declare void @js_enter_finally() +declare void @js_leave_finally() +declare double @js_await_any_promise(double) +declare i64 @js_promise_new() +declare i64 @js_promise_new_with_executor(i64) +declare i32 @js_timer_tick() +declare i32 @js_timer_tick_if_refed() +declare i32 @js_callback_timer_tick() +declare i32 @js_interval_timer_tick() +declare i32 @js_timer_has_pending() +declare i32 @js_callback_timer_has_pending() +declare i32 @js_interval_timer_has_pending() +declare i32 @js_stdlib_has_active_handles() +declare i32 @js_microtasks_pending() +declare i64 @js_timer_validate_callback(double, i32) +declare i64 @js_set_timeout_callback(i64, double) +declare i64 @js_set_timeout_callback_args(i64, double, ptr, i32) +declare i64 @js_set_immediate_callback(i64) +declare i64 @js_set_immediate_callback_args(i64, ptr, i32) +declare i64 @setInterval(i64, double) +declare i64 @js_set_interval_callback_args(i64, double, ptr, i32) +declare void @clearTimeout(i64) +declare void @clearInterval(i64) +declare void @clearImmediate(i64) +declare void @js_clear_timeout_value(double) +declare void @js_clear_interval_value(double) +declare void @js_clear_immediate_value(double) +declare i64 @js_buffer_from_array(i64) +declare i64 @js_buffer_from_arraybuffer_slice(i64, i32, i32) +declare i32 @js_buffer_length(i64) +declare i32 @js_buffer_get(i64, i32) +declare double @js_buffer_index_get_value(i64, i32) +declare ptr @js_native_buffer_data_ptr(double) +declare i64 @js_native_buffer_byte_len(double) +declare void @js_console_time(i64) +declare void @js_console_time_end(i64) +declare void @js_console_time_log(i64) +declare void @js_console_time_value(double) +declare void @js_console_time_end_value(double) +declare void @js_console_time_log_value(double) +declare void @js_console_time_log_spread(double, i64) +declare void @js_console_count(i64) +declare void @js_console_count_reset(i64) +declare void @js_console_count_value(double) +declare void @js_console_count_reset_value(double) +declare double @js_console_new(double) +declare double @js_console_new2(double, double) +declare void @js_console_group_begin() +declare void @js_console_group_end() +declare void @js_console_clear() +declare void @js_console_noop() +declare double @js_native_call_method(double, ptr, i64, ptr, i64) +declare double @js_native_call_method_by_id(double, i64, ptr, i64) +declare double @js_native_call_method_apply(double, ptr, i64, i64) +declare double @js_native_call_method_apply_by_id(double, i64, i64) +declare double @js_native_call_method_str_key(double, i64, ptr, i64) +declare double @js_native_call_method_value(double, double, ptr, i64) +declare double @js_native_call_method_value_apply(double, double, i64) +declare void @js_promise_resolve(i64, double) +declare void @js_promise_reject(i64, double) +declare void @js_promise_mark_internally_handled(i64) +declare i64 @js_promise_resolved(double) +declare i64 @js_async_fn_result(double) +declare i64 @js_promise_rejected(double) +declare double @js_create_namespace(i32, ptr, ptr, ptr) +declare i64 @js_promise_then(i64, i64, i64) +declare i64 @js_promise_resolved_then(double, i64, i64) +declare i64 @js_promise_finally(i64, i64) +declare double @js_promise_then_checked(double, double, double) +declare double @js_promise_catch_checked(double, double) +declare double @js_promise_finally_checked(double, double) +declare i64 @js_promise_closure_arg(double) +declare i64 @js_promise_all(i64) +declare i64 @js_promise_race(i64) +declare i64 @js_promise_any(i64) +declare i64 @js_promise_all_settled(i64) +declare i64 @js_promise_all_iterable(double) +declare i64 @js_promise_race_iterable(double) +declare i64 @js_promise_any_iterable(double) +declare i64 @js_promise_all_settled_iterable(double) +declare i64 @js_promise_with_resolvers() +declare i64 @js_promise_try(double, i64) +declare i64 @js_array_unshift_f64(i64, double) +declare i64 @js_array_unshift_variadic(i64, ptr, i32) +declare i64 @js_array_entries(i64) +declare i64 @js_array_keys(i64) +declare i64 @js_array_values(i64) +declare i64 @js_array_entries_iter_obj(i64) +declare i64 @js_array_keys_iter_obj(i64) +declare i64 @js_array_values_iter_obj(i64) +declare double @js_response_new(i64, double, i64, double) +declare i64 @js_response_body_init_ptr(double) +declare double @js_headers_new() +declare double @js_headers_set(double, i64, i64) +declare double @js_headers_append(double, i64, i64) +declare i64 @js_headers_get(double, i64) +declare double @js_headers_get_set_cookie(double) +declare double @js_headers_has(double, i64) +declare double @js_headers_delete(double, i64) +declare double @js_headers_for_each(double, double) +declare double @js_headers_keys(double) +declare double @js_headers_values(double) +declare double @js_headers_entries(double) +declare double @js_headers_init_from_value(double, double) +declare double @js_headers_method_value(double, i64, i64) +declare double @js_request_new(i64, i64, i64, double, i64, i64, i64, i64, i64, i64, i64, double, i64, double) +declare double @js_request_new_from_init(i64, double) +declare i64 @js_request_get_url(double) +declare i64 @js_request_input_to_url(double) +declare i64 @js_request_get_method(double) +declare double @js_request_get_body(double) +declare double @js_request_body_used(double) +declare i64 @js_request_get_destination(double) +declare i64 @js_request_get_referrer(double) +declare i64 @js_request_get_referrer_policy(double) +declare i64 @js_request_get_mode(double) +declare i64 @js_request_get_credentials(double) +declare i64 @js_request_get_cache(double) +declare i64 @js_request_get_redirect(double) +declare i64 @js_request_get_integrity(double) +declare double @js_request_get_keepalive(double) +declare i64 @js_request_get_duplex(double) +declare double @js_request_get_signal(double) +declare double @js_request_get_headers(double) +declare i64 @js_request_text(double) +declare i64 @js_request_json(double) +declare i64 @js_request_array_buffer(double) +declare i64 @js_request_blob(double) +declare i64 @js_request_bytes(double) +declare i64 @js_request_form_data(double) +declare double @js_request_clone(double) +declare double @js_fetch_response_status(double) +declare i64 @js_fetch_response_status_text(double) +declare double @js_fetch_response_ok(double) +declare i64 @js_fetch_response_type(double) +declare i64 @js_fetch_response_url(double) +declare double @js_fetch_response_redirected(double) +declare double @js_response_body_used(double) +declare i64 @js_fetch_response_text(double) +declare i64 @js_fetch_response_json(double) +declare double @js_response_get_headers(double) +declare double @js_response_clone(double) +declare i64 @js_response_array_buffer(double) +declare i64 @js_response_blob(double) +declare i64 @js_response_bytes(double) +declare i64 @js_response_form_data(double) +declare double @js_form_data_new() +declare double @js_form_data_append(double, double, double) +declare double @js_form_data_set(double, double, double) +declare double @js_form_data_delete(double, i64) +declare double @js_form_data_get(double, i64) +declare double @js_form_data_get_all(double, i64) +declare double @js_form_data_has(double, i64) +declare double @js_form_data_entries(double) +declare double @js_form_data_keys(double) +declare double @js_form_data_values(double) +declare double @js_form_data_for_each(double, double) +declare double @js_blob_size(double) +declare i64 @js_blob_type(double) +declare i64 @js_blob_array_buffer(double) +declare i64 @js_blob_bytes(double) +declare i64 @js_blob_text(double) +declare double @js_blob_slice(double, double, double, i64) +declare double @js_blob_new(double, double) +declare double @js_file_new(double, double, double, double) +declare i64 @js_file_name(double) +declare double @js_file_last_modified(double) +declare i64 @js_url_create_object_url(double) +declare void @js_url_revoke_object_url(double) +declare double @js_buffer_resolve_object_url(double) +declare double @js_response_static_json(double, double, i64, double) +declare double @js_response_static_redirect(i64, double) +declare double @js_response_static_error() +declare double @js_blob_stream(double) +declare double @js_response_body(double) +declare double @js_readable_stream_new(double, double, double, double) +declare double @js_readable_stream_new_with_source_type(double, double, double, double, double) +declare double @js_readable_stream_new_with_strategy_and_source_type(double, double, double, double, double) +declare double @js_readable_stream_new_from_source_object(double, double) +declare double @js_readable_stream_get_reader(double) +declare double @js_readable_stream_get_reader_with_options(double, double) +declare double @js_readable_stream_get_byob_reader(double) +declare double @js_readable_stream_controller_byob_request(double) +declare double @js_readable_stream_from_iterable(double) +declare double @js_readable_stream_locked(double) +declare i64 @js_readable_stream_cancel(double, double) +declare double @js_readable_stream_tee(double) +declare i64 @js_readable_stream_pipe_to(double, double, double) +declare double @js_readable_stream_pipe_through(double, double, double) +declare double @js_readable_stream_pipe_through_validate(double, double, double, double) +declare double @js_readable_stream_controller_enqueue(double, double) +declare double @js_readable_stream_controller_close(double) +declare double @js_readable_stream_controller_error(double, double) +declare double @js_readable_stream_controller_desired_size(double) +declare i64 @js_reader_read(double) +declare i64 @js_reader_read_with_view(double, double) +declare double @js_reader_release_lock(double) +declare i64 @js_reader_closed(double) +declare i64 @js_reader_cancel(double, double) +declare double @js_writable_stream_new(double, double, double, double, double) +declare double @js_writable_stream_new_with_sink_type(double, double, double, double, double, double) +declare double @js_writable_stream_new_from_sink_object(double, double) +declare double @js_writable_stream_throw_invalid_sink() +declare double @js_writable_stream_get_writer(double) +declare double @js_writable_stream_locked(double) +declare i64 @js_writable_stream_close(double) +declare i64 @js_writable_stream_abort(double, double) +declare i64 @js_writer_write(double, double) +declare i64 @js_writer_close(double) +declare i64 @js_writer_abort(double, double) +declare double @js_writer_release_lock(double) +declare i64 @js_writer_closed(double) +declare i64 @js_writer_ready(double) +declare double @js_writer_desired_size(double) +declare double @js_transform_stream_new(double, double, double, double, double) +declare double @js_transform_stream_new_from_transformer_object(double, double, double) +declare double @js_transform_stream_readable(double) +declare double @js_transform_stream_writable(double) +declare double @js_text_encoding_stream_new() +declare double @js_text_encoder_stream_new() +declare double @js_text_decoder_stream_new() +declare double @js_stream_web_text_encoder_stream_new() +declare double @js_stream_web_text_decoder_stream_new(double, double) +declare double @js_stream_web_compression_stream_new(double) +declare double @js_stream_web_decompression_stream_new(double) +declare double @js_streams_strategy_high_water_mark(double) +declare double @js_count_queuing_strategy_new(double) +declare double @js_byte_length_queuing_strategy_new(double) +declare double @js_stream_unwrap_handle(double) +declare double @js_readable_stream_subclass_init(double, double, double, double, double) +declare double @js_writable_stream_subclass_init(double, double, double, double, double) +declare double @js_transform_stream_subclass_init(double, double, double, double) +declare double @js_request_subclass_init(double, double, double) +declare double @js_response_subclass_init(double, double, double) +declare double @js_fetch_or_value_super(double, double, ptr, i64) +declare i64 @js_abort_controller_new() +declare i64 @js_abort_controller_signal(i64) +declare void @js_abort_controller_abort(i64) +declare void @js_abort_controller_abort_reason(i64, double) +declare void @js_abort_signal_add_listener(i64, double, double) +declare i64 @js_abort_signal_timeout(double) +declare i64 @js_abort_signal_abort(double) +declare i64 @js_abort_signal_any(i64) +declare double @js_abort_signal_throw_if_aborted(i64) +declare i64 @js_event_target_new() +declare i64 @js_event_new(double, double, i32) +declare double @js_event_subclass_init(double, double, double, i32, i32) +declare i64 @js_custom_event_new(double, double, i32) +declare i64 @js_dom_exception_new(double, double) +declare double @js_dom_exception_subclass_init(double, double, double) +declare void @js_event_target_add_event_listener(i64, i64, i64) +declare void @js_event_target_add_event_listener_with_options(i64, i64, i64, double) +declare void @js_event_target_remove_event_listener(i64, i64, i64) +declare void @js_event_target_remove_event_listener_with_options(i64, i64, i64, double) +declare double @js_event_target_dispatch_event(i64, double) +declare i32 @js_event_target_is_event_target(i64) +declare i64 @js_event_target_get_event_listeners(i64, i64) +declare double @js_event_target_get_max_listeners(i64) +declare i32 @js_event_target_set_max_listeners(i64, double) +declare double @js_message_channel_new() +declare double @js_message_port_constructor_error() +declare double @js_broadcast_channel_new(double) +declare i64 @js_array_alloc(i32) +declare i64 @js_tagged_template_register_raw(i64, i64) +declare i64 @js_tagged_template_get_or_init(i64, i64, i64) +declare i64 @js_template_raw(i64) +declare i64 @js_array_create() +declare i64 @js_array_constructor_single(double) +declare i64 @js_array_alloc_literal(i32) +declare i64 @js_array_from_values(ptr, i32) +declare i64 @js_array_push_f64(i64, double) +declare void @js_array_push_guard(i64) +declare i64 @js_array_push_hole(i64) +declare i64 @js_array_numeric_push_f64_unboxed(i64, double) +declare i64 @js_array_push_spread_f64(i64, i64) +declare double @js_array_get_f64(i64, i32) +declare double @js_array_get_index_or_string(i64, double) +declare double @js_array_numeric_get_f64_unboxed(i64, i32) +declare void @js_array_set_f64(i64, i32, double) +declare i32 @js_array_numeric_set_f64_unboxed(i64, i32, double) +declare i64 @js_array_set_f64_extend(i64, i32, double) +declare i64 @js_array_set_f64_extend_strict(i64, i32, double) +declare i64 @js_array_fill_f64_const_extend(i64, i32, double) +declare i64 @js_array_fill_f64_iota_extend(i64, i32) +declare i64 @js_array_fill_f64_const_len_extend(i64, double) +declare i64 @js_array_fill_f64_iota_len_extend(i64) +declare i64 @js_array_numeric_range_add(double, double, double, double) +declare i64 @js_array_numeric_range_add_len(double, double, double) +declare i64 @js_array_set_string_key(i64, i64, double) +declare i64 @js_array_set_index_or_string(i64, double, double) +declare i64 @js_array_mark_arguments_object(i64) +declare i32 @js_array_mark_numeric_f64_layout(i64) +declare i32 @js_array_is_numeric_f64_layout(i64) +declare void @js_array_clear_numeric_layout(i64) +declare double @js_array_numeric_value_to_raw_f64(double) #4 +declare double @js_array_refresh_local_head(double) +declare void @js_array_note_numeric_write(i64, i64) +declare i32 @js_array_length(i64) +declare double @js_array_is_array(double) +declare double @js_value_length_f64(double) +declare nonnull ptr @js_shadow_frame_enter(i32) +declare i64 @js_shadow_frame_push(i32) +declare void @js_shadow_frame_pop(i64) +declare void @js_shadow_slot_set(i32, i64) +declare void @js_shadow_slot_bind(i32, ptr) +declare void @js_gc_write_barriers_emitted(i32) +declare i32 @js_gc_temp_root_push(i64) +declare i64 @js_gc_temp_root_get(i32) +declare void @js_gc_temp_root_set(i32, i64) +declare void @js_gc_temp_root_truncate(i32) +declare void @js_array_push_f64_temp_rooted(i32, double) +declare void @js_gc_loop_safepoint() +declare void @js_write_barrier(i64, i64) +declare void @js_write_barrier_slot(i64, i64, i64) +declare void @js_write_barrier_root_nanbox(i64) +declare void @js_write_barrier_root_heap_word(i64) +declare void @js_gc_note_slot_layout(i64, i32, i64) +declare void @js_gc_note_slot_layout_aware(i64, i32, i64, i64) +declare void @js_gc_init_typed_shape_layout(i64, i32, ptr, i32, ptr, i32) +declare void @js_gc_init_unboxed_object_layout(i64, i32, i64, i64) +declare double @js_array_pop_f64(i64) +declare i64 @js_array_join(i64, i64) +declare i64 @js_array_join_value(i64, double) +declare void @js_array_forEach(i64, i64) +declare i64 @js_array_fill(i64, double) +declare i64 @js_array_fill_range(i64, double, double, double) +declare double @js_array_fill_generic(double, double, i32, double, i32, double) +declare i32 @js_array_delete(i64, i32) +declare void @js_array_set_length(i64, double) +declare void @js_array_set_length_strict(i64, double) +declare i64 @js_array_clone(i64) +declare i64 @js_array_from_value(double) +declare i64 @js_array_from_arraylike_holey_value(double) +declare double @js_iterator_from(double) +declare i64 @js_array_from_mapped(double, double, double) +declare i64 @js_array_concat_variadic(i64, ptr, i32) +declare double @js_arraylike_forEach(double, double, double) +declare double @js_arraylike_map(double, double, double) +declare double @js_arraylike_filter(double, double, double) +declare double @js_arraylike_some(double, double, double) +declare double @js_arraylike_every(double, double, double) +declare double @js_arraylike_find(double, double, double) +declare double @js_arraylike_findIndex(double, double, double) +declare double @js_arraylike_findLast(double, double, double) +declare double @js_arraylike_findLastIndex(double, double, double) +declare double @js_arraylike_reduce(double, double, i32, double) +declare double @js_arraylike_reduceRight(double, double, i32, double) +declare double @js_arraylike_indexOf(double, double, double, i32) +declare double @js_arraylike_lastIndexOf(double, double, double, i32) +declare double @js_arraylike_includes(double, double, double, i32) +declare double @js_arraylike_at(double, double) +declare double @js_arraylike_join(double, double) +declare double @js_arraylike_slice(double, double, i32, double, i32) +declare double @js_arraylike_sort(double, double) +declare double @js_arraylike_splice(double, ptr, i32) +declare double @js_arraylike_concat(double, ptr, i32) +declare double @js_arraylike_pop(double) +declare double @js_arraylike_shift(double) +declare double @js_arraylike_push(double, ptr, i32) +declare double @js_arraylike_unshift(double, ptr, i32) +declare i64 @js_array_clone_for_spread(double) +declare i64 @js_array_spread_append(i64, double) +declare i64 @js_iterator_to_array(double) +declare double @js_iterator_next_result(double) +declare double @js_iterator_close_if_not_done(double, double) +declare double @js_iterator_rest_to_array(double, double) +declare double @js_get_iterator(double) +declare double @js_get_async_iterator(double) +declare double @js_for_of_to_array(double) +declare i64 @js_object_alloc(i32, i32) +declare double @js_object_coerce(double) +declare void @js_object_mark_class(i64) +declare void @js_class_object_pin_parent(i64, i32) +declare i64 @js_object_alloc_with_shape(i32, i32, ptr, i32) +declare void @js_object_set_field(i64, i32, i64) +declare void @js_object_set_unboxed_f64_field(i64, i32, double) +declare double @js_object_get_unboxed_f64_field(i64, i32) +declare void @js_object_set_field_by_name(i64, i64, double) +declare void @js_object_set_field_by_property_id(i64, i64, double) +declare void @js_object_set_field_by_name_nonenum(i64, i64, double) +declare void @js_error_subclass_default_init(double, double, i64) +declare void @js_object_set_field_by_name_nonconfigurable(i64, i64, double) +declare void @js_error_apply_cause_to_object(i64, double) +declare i32 @js_with_has_binding(double, i64) +declare double @js_with_get_binding(double, i64) +declare double @js_with_set_binding(double, i64, double, i32) +declare i32 @js_with_delete_binding(double, i64) +declare i32 @js_pod_scalar_write_compatible(double, i32) +declare void @js_typed_feedback_register_site(i64, i32, ptr, i64, ptr, i64, ptr, i64, ptr, i64, ptr, i64, ptr, i64) +declare void @js_typed_feedback_record_guard_pass(i64) +declare void @js_typed_feedback_record_guard_fail(i64) +declare void @js_typed_feedback_record_fallback_call(i64) +declare void @js_typed_feedback_observe_property_get(i64, i64, i64) +declare void @js_typed_feedback_observe_property_set(i64, i64, i64) +declare double @js_typed_feedback_object_get_field_by_name_f64(i64, i64, i64) +declare void @js_typed_feedback_object_set_field_by_name(i64, i64, i64, double) +declare void @js_typed_feedback_object_set_field_by_name_fast(i64, i64, i64, double) +declare i32 @js_typed_feedback_class_field_set_guard(i64, double, i32, i64, i64, i32, double, i32) +declare void @js_class_field_set_fallback(i64, i64, i64, double) +declare void @js_class_field_set_ic(i64, double, i32, i64, i64, i32, double, i32) +declare i32 @js_typed_feedback_class_field_get_guard(i64, double, i32, i64, i64, i32, i32) +declare double @js_class_field_get_ic(i64, double, i32, i64, i64, i32, i32) +declare double @js_typed_feedback_native_call_method(i64, double, ptr, i64, ptr, i64) +declare double @js_typed_feedback_native_call_method_by_id(i64, double, i64, ptr, i64) +declare double @js_typed_feedback_native_call_method_apply(i64, double, ptr, i64, i64) +declare double @js_typed_feedback_native_call_method_apply_by_id(i64, double, i64, i64) +declare i32 @js_typed_feedback_method_direct_call_guard(i64, double, i32, i64, ptr, i64, ptr) +declare i32 @js_method_direct_shape_guard(double, i32, i64) +declare i32 @js_typed_feedback_closure_direct_call_guard(i64, double, ptr, i32, i32) +declare void @js_typed_feedback_object_set_unboxed_f64_field(i64, i64, i32, i64, double) +declare double @js_typed_feedback_observe_helper_return(i64, double) +declare void @js_object_set_index_polymorphic(i64, double, double) +declare double @js_object_get_index_polymorphic(i64, double) +declare double @js_object_get_field_by_name_f64(i64, i64) +declare double @js_object_get_field_by_name_boxed(double, i64) +declare double @js_object_get_field_by_property_id_f64(i64, i64) +declare double @js_native_module_property_by_name(ptr, i64, ptr, i64) +declare double @js_create_native_module_namespace(ptr, i64) +declare void @js_nm_install_assert() +declare void @js_nm_install_async_hooks() +declare void @js_nm_install_bigint() +declare void @js_nm_install_buffer() +declare void @js_nm_install_bun() +declare void @js_nm_install_bun_ffi() +declare void @js_nm_install_child_process() +declare void @js_nm_install_cluster() +declare void @js_nm_install_console() +declare void @js_nm_install_crypto() +declare void @js_nm_install_dgram() +declare void @js_nm_install_dns() +declare void @js_nm_install_domain() +declare void @js_nm_install_events() +declare void @js_nm_install_fs() +declare void @js_nm_install_http() +declare void @js_nm_install_inspector() +declare void @js_nm_install_module() +declare void @js_nm_install_net() +declare void @js_nm_install_node_pty() +declare void @js_nm_install_os() +declare void @js_nm_install_path() +declare void @js_nm_install_perf() +declare void @js_nm_install_process() +declare void @js_nm_install_punycode() +declare void @js_nm_install_querystring() +declare void @js_nm_install_readline() +declare void @js_nm_install_repl() +declare void @js_nm_install_sea() +declare void @js_nm_install_sqlite() +declare void @js_nm_install_stream() +declare void @js_nm_install_timers() +declare void @js_nm_install_tls() +declare void @js_nm_install_tty() +declare void @js_nm_install_url() +declare void @js_nm_install_util() +declare void @js_nm_install_v8() +declare void @js_nm_install_vm() +declare void @js_nm_install_wasi() +declare void @js_nm_install_zlib() +declare void @js_nm_install_all() +declare double @js_object_get_field_ic_miss(i64, i64, ptr) +declare double @js_object_get_field_ic(i64, i64, i64, ptr) +declare i64 @js_object_rest(i64, i64) +declare double @js_require_object_coercible(double) +declare double @js_require_json_disk(double) +declare double @js_require_resolve_node_modules(double, double) +declare void @js_globalthis_seed_async_local_storage() +declare void @js_register_path_module(double, double) +declare double @js_require_path_module(double) +declare void @js_register_path_init(ptr, i64, i64) +declare i64 @js_array_alloc_with_length(i32) +declare void @js_array_set_f64_unchecked(i64, i32, double) +declare double @js_typed_feedback_array_get_f64(i64, i64, i32) +declare i32 @js_typed_feedback_plain_array_index_get_guard(i64, double, i32, i32) #4 +declare i32 @js_typed_feedback_numeric_array_index_get_guard(i64, double, i32, i32) #4 +declare i32 @js_typed_feedback_packed_f64_array_loop_guard(i64, double) +declare i32 @js_typed_feedback_packed_f64_range_loop_guard(i64, double, i32, i32) +declare i32 @js_typed_feedback_packed_f64_range_loop_guard_dense(i64, double, i32, i32) +declare i32 @js_typed_feedback_packed_f64_range_loop_guard_dense_i32(i64, double, i32, i32) +declare i32 @js_typed_feedback_masked_window_ta_kind(i64, double, i32, i32) +declare i64 @js_typed_array_masked_window_data_ptr(double) +declare i32 @js_typed_feedback_packed_u32_array_loop_guard(i64, double) +declare double @js_typed_feedback_array_index_get_fallback_boxed(i64, double, double) +declare void @js_typed_feedback_array_set_f64(i64, i64, i32, double) +declare i64 @js_typed_feedback_array_set_f64_extend(i64, i64, i32, double) +declare i32 @js_typed_feedback_plain_array_index_set_guard(i64, double, i32, double, i32) #4 +declare i32 @js_typed_feedback_numeric_array_index_set_guard(i64, double, i32, double, i32) #4 +declare i32 @js_typed_feedback_numeric_array_push_guard(i64, double, double) #4 +declare double @js_typed_feedback_array_index_set_fallback_boxed(i64, double, double, double) +declare void @js_typed_feedback_observe_array_element(i64, i64, i32) +declare i64 @js_typed_feedback_array_set_string_key(i64, i64, i64, double) +declare i64 @js_typed_feedback_array_set_index_or_string(i64, i64, double, double) +declare void @js_typed_feedback_object_set_index_polymorphic(i64, i64, double, double) +declare double @js_proxy_new(double, double) +declare double @js_proxy_revocable(double, double) +declare void @js_proxy_revoke(double) +declare i32 @js_proxy_is_revoked(double) +declare i32 @js_proxy_is_proxy(double) +declare double @js_proxy_target(double) +declare double @js_proxy_get(double, double) +declare double @js_proxy_set(double, double, double) +declare double @js_proxy_has(double, double) +declare double @js_proxy_delete(double, double) +declare double @js_proxy_apply(double, double, double) +declare double @js_proxy_construct(double, double, double) +declare double @js_reflect_construct(double, double, double) +declare double @js_reflect_get(double, double, double) +declare double @js_reflect_set(double, double, double, double) +declare double @js_put_value_set(double, double, double, double, i32) +declare double @js_put_value_set_dyn_ic(ptr, double, double, double, i32) +declare double @js_put_value_set_ic_miss(double, i64, double, i32, ptr) +declare i64 @js_object_array_numeric_write_guard(double, double, double, double, double, i32, i32) +declare double @js_super_put_value_set(i32, double, double, double, i32) +declare double @js_super_accessor_get(i32, double, double) +declare double @js_reflect_has(double, double) +declare double @js_reflect_delete(double, double) +declare double @js_reflect_own_keys(double) +declare double @js_reflect_apply(double, double, double) +declare double @js_reflect_define_property(double, double, double) +declare double @js_reflect_get_own_property_descriptor(double, double) +declare double @js_reflect_get_prototype_of(double) +declare double @js_reflect_set_prototype_of(double, double) +declare double @js_reflect_is_extensible(double) +declare double @js_reflect_prevent_extensions(double) +declare double @js_reflect_define_metadata(double, double, double, double) +declare double @js_reflect_get_metadata(double, double, double) +declare double @js_reflect_get_own_metadata(double, double, double) +declare double @js_reflect_has_metadata(double, double, double) +declare double @js_reflect_has_own_metadata(double, double, double) +declare double @js_reflect_get_metadata_keys(double, double) +declare double @js_reflect_get_own_metadata_keys(double, double) +declare double @js_reflect_delete_metadata(double, double, double) +declare double @js_http_server_construct_with_this(double, double, double) +declare double @js_https_server_construct_with_this(double, double, double) +declare i64 @js_net_socket_set_encoding(i64, i64) +declare double @js_vm_create_context(double) +declare double @js_vm_module_call() +declare double @js_vm_module_constructor_error() +declare double @js_repl_start(double) +declare double @js_repl_repl_server_new(double) +declare double @js_repl_recoverable_new(double) +declare double @js_worker_threads_worker_new(i64, double) +declare double @js_worker_threads_worker_post_message(i64, double) +declare double @js_worker_threads_worker_on(i64, double, i64) +declare double @js_worker_threads_worker_once(i64, double, i64) +declare double @js_worker_threads_worker_off(i64, double, i64) +declare double @js_worker_threads_worker_add_event_listener(i64, double, i64) +declare double @js_worker_threads_worker_remove_event_listener(i64, double, i64) +declare double @js_worker_threads_worker_terminate(i64) +declare double @js_worker_threads_worker_ref(i64) +declare double @js_worker_threads_worker_unref(i64) +declare double @js_worker_threads_worker_get_heap_statistics(i64) +declare double @js_worker_threads_worker_cpu_usage(i64, double) +declare double @js_worker_threads_worker_get_heap_snapshot(i64, double) +declare double @js_worker_threads_worker_start_cpu_profile(i64) +declare double @js_worker_threads_worker_start_heap_profile(i64) +declare i64 @js_http_client_request_end(i64, double) +declare i64 @js_http_client_request_write(i64, double) +declare i64 @js_http_client_request_end_full(i64, double, i64, i64) +declare double @js_http_client_request_write_full(i64, double, i64, i64) +declare i64 @js_http_set_timeout_full(i64, double, i64) +declare i64 @js_http_client_request_method(i64) +declare i64 @js_http_client_request_protocol(i64) +declare i64 @js_http_client_request_host(i64) +declare i64 @js_http_client_request_path(i64) +declare double @js_http_client_request_listener_count(i64, i64) +declare double @js_http_client_request_get_header(i64, i64) +declare double @js_http_client_request_has_header(i64, i64) +declare double @js_http_client_request_remove_header(i64, i64) +declare double @js_http_client_request_get_header_names(i64) +declare double @js_http_client_request_get_headers(i64) +declare double @js_http_client_request_get_raw_header_names(i64) +declare double @js_http_client_request_abort(i64) +declare i64 @js_http_client_request_destroy(i64, double) +declare double @js_http_client_request_noop_undefined(i64, double, double) +declare double @js_http_client_request_aborted(i64) +declare double @js_http_client_request_destroyed(i64) +declare double @js_http_client_request_finished(i64) +declare double @js_http_client_request_reused_socket(i64) +declare double @js_http_client_request_max_headers_count(i64) +declare double @js_http_client_request_writable_ended(i64) +declare double @js_http_client_request_writable_finished(i64) +declare double @js_http_client_request_socket(i64) +declare i64 @js_http_get(double, i64) +declare i64 @js_http_get_overload(i64) +declare i64 @js_http_request_overload(i64) +declare i64 @js_https_get_overload(i64) +declare i64 @js_https_request_overload(i64) +declare i64 @js_http_on(i64, i64, i64) +declare i64 @js_http_request(double, i64) +declare i64 @js_http_request_body(i64) +declare double @js_http_request_body_length(i64) +declare i64 @js_http_request_content_type(i64) +declare double @js_http_request_has_header(i64, i64) +declare i64 @js_http_request_header(i64, i64) +declare i64 @js_http_request_headers_all(i64) +declare double @js_http_request_id(i64) +declare double @js_http_request_is_method(i64, i64) +declare i64 @js_http_request_method(i64) +declare i64 @js_http_request_path(i64) +declare i64 @js_http_request_query(i64) +declare i64 @js_http_request_query_all(i64) +declare i64 @js_http_request_query_param(i64, i64) +declare double @js_http_respond_error(i64, double, i64) +declare double @js_http_respond_html(i64, double, i64) +declare double @js_http_respond_json(i64, double, i64) +declare double @js_http_respond_not_found(i64) +declare double @js_http_respond_redirect(i64, i64, double) +declare i64 @js_http_respond_status_text(double) +declare double @js_http_respond_text(i64, double, i64) +declare double @js_http_respond_with_headers(i64, double, i64, i64) +declare double @js_http_response_headers(i64) +declare double @js_http_response_trailers(i64) +declare i64 @js_http_incoming_message_set_encoding(i64, i64) +declare i64 @js_http_server_accept_v2(i64) +declare double @js_http_server_close(i64) +declare i64 @js_http_server_create(double) +declare i64 @js_http_set_header(i64, i64, i64) +declare i64 @js_http_set_timeout(i64, double) +declare double @js_http_status_code(i64) +declare i64 @js_http_status_message(i64) +declare i64 @js_http_agent_new(double) +declare i64 @js_https_agent_new(double) +declare i64 @js_http_agent_get_name(i64, double) +declare i64 @js_http_agent_noop_self(i64) +declare double @js_http_agent_max_sockets(i64) +declare double @js_http_agent_max_free_sockets(i64) +declare double @js_http_agent_max_total_sockets(i64) +declare double @js_http_agent_keep_alive_msecs(i64) +declare double @js_http_agent_keep_alive(i64) +declare i64 @js_http_agent_protocol(i64) +declare double @js_http_agent_default_port(i64) +declare void @js_http_agent_set_protocol(i64, i64) +declare i64 @js_http_agent_destroy(i64) +declare double @js_http_agent_destroyed(i64) +declare double @js_http_agent_sockets(i64) +declare double @js_http_agent_free_sockets(i64) +declare double @js_http_agent_requests(i64) +declare void @js_http_agent_set_max_sockets(i64, double) +declare void @js_http_agent_set_max_free_sockets(i64, double) +declare void @js_http_agent_set_max_total_sockets(i64, double) +declare void @js_http_agent_set_keep_alive(i64, double) +declare void @js_http_agent_set_keep_alive_msecs(i64, double) +declare void @js_http_agent_set_create_connection(i64, i64) +declare void @js_http_agent_set_create_socket(i64, i64) +declare i64 @js_http_agent_create_connection(i64) +declare i64 @js_http_agent_create_socket(i64) +declare i64 @js_https_get(double, i64) +declare i64 @js_https_request(double, i64) +declare i64 @js_node_http_create_server(i64) +declare i64 @js_node_http_server_listen(i64, i64) +declare void @js_node_http_server_close(i64, i64) +declare void @js_node_http_server_close_all_connections(i64) +declare void @js_node_http_server_close_idle_connections(i64) +declare i64 @js_node_http_server_address_json(i64) +declare i32 @js_node_http_server_listening(i64) +declare double @js_node_http_server_listening_value(i64) +declare double @js_node_http_server_on(i64, i64, i64) +declare i64 @js_node_http_im_method(i64) +declare i64 @js_node_http_im_url(i64) +declare i64 @js_node_http_im_http_version(i64) +declare i64 @js_node_http_im_headers_json(i64) +declare i64 @js_node_http_im_raw_headers_json(i64) +declare i64 @js_node_http_im_headers_distinct_json(i64) +declare i64 @js_node_http_im_trailers_json(i64) +declare i64 @js_node_http_im_raw_trailers_json(i64) +declare i64 @js_node_http_im_trailers_distinct_json(i64) +declare i32 @js_node_http_im_complete(i64) +declare i32 @js_node_http_im_aborted(i64) +declare i32 @js_node_http_im_destroyed(i64) +declare i64 @js_node_http_im_remote_address(i64) +declare double @js_node_http_im_remote_port(i64) +declare void @js_node_http_im_pause(i64) +declare void @js_node_http_im_resume(i64) +declare void @js_node_http_im_destroy(i64) +declare double @js_node_http_im_on(i64, i64, i64) +declare double @js_node_http_im_read(i64) +declare i64 @js_node_http_im_set_timeout(i64, double, i64) +declare void @js_node_http_res_set_status(i64, double) +declare double @js_node_http_res_get_status(i64) +declare void @js_node_http_res_set_status_message(i64, i64) +declare void @js_node_http_res_set_header(i64, i64, double) +declare i64 @js_node_http_res_set_header_self(i64, i64, double) +declare double @js_node_http_res_get_header(i64, i64) +declare void @js_node_http_res_remove_header(i64, i64) +declare i32 @js_node_http_res_has_header(i64, i64) +declare double @js_node_http_res_has_header_value(i64, i64) +declare i64 @js_node_http_res_get_headers_json(i64) +declare i64 @js_node_http_res_get_header_names_json(i64) +declare i64 @js_node_http_res_append_header(i64, i64, i64) +declare i64 @js_node_http_res_set_headers(i64, double) +declare double @js_node_http_res_get_status_message(i64) +declare i32 @js_node_http_res_headers_sent(i64) +declare i32 @js_node_http_res_writable_ended(i64) +declare i32 @js_node_http_res_writable_finished(i64) +declare i32 @js_node_http_res_finished(i64) +declare i32 @js_node_http_res_send_date(i64) +declare void @js_node_http_res_set_send_date(i64, double) +declare i32 @js_node_http_res_strict_content_length(i64) +declare void @js_node_http_res_set_strict_content_length(i64, double) +declare i64 @js_node_http_res_req_handle(i64) +declare void @js_node_http_res_write_head(i64, double, i64, i64) +declare i32 @js_node_http_res_write(i64, double) +declare double @js_node_http_res_write_full(i64, double, i64, i64) +declare void @js_node_http_res_add_trailers(i64, double) +declare void @js_node_http_res_end(i64, double) +declare void @js_node_http_res_end_full(i64, double, i64, i64) +declare void @js_node_http_res_flush_headers(i64) +declare void @js_node_http_res_cork(i64) +declare void @js_node_http_res_uncork(i64) +declare i64 @js_node_http_res_set_timeout(i64, double, i64) +declare void @js_node_http_res_write_early_hints(i64, double, i64) +declare void @js_node_http_res_write_continue(i64) +declare void @js_node_http_res_write_processing(i64) +declare double @js_node_http_res_on(i64, i64, i64) +declare i64 @js_node_https_create_server(double, i64) +declare i64 @js_node_https_server_listen(i64, i64) +declare void @js_node_https_server_close(i64, i64) +declare void @js_node_https_server_close_all_connections(i64) +declare void @js_node_https_server_close_idle_connections(i64) +declare i64 @js_node_https_server_address_json(i64) +declare double @js_node_https_server_on(i64, i64, i64) +declare double @js_node_https_server_listening_value(i64) +declare double @js_node_https_server_headers_timeout(i64) +declare double @js_node_https_server_set_headers_timeout(i64, double) +declare double @js_node_https_server_keep_alive_timeout(i64) +declare double @js_node_https_server_set_keep_alive_timeout(i64, double) +declare double @js_node_https_server_keep_alive_timeout_buffer(i64) +declare double @js_node_https_server_set_keep_alive_timeout_buffer(i64, double) +declare double @js_node_https_server_request_timeout(i64) +declare double @js_node_https_server_set_request_timeout(i64, double) +declare double @js_node_https_server_idle_timeout(i64) +declare double @js_node_https_server_set_idle_timeout(i64, double) +declare double @js_node_https_server_max_headers_count(i64) +declare double @js_node_https_server_set_max_headers_count(i64, double) +declare double @js_node_https_server_max_requests_per_socket(i64) +declare double @js_node_https_server_set_max_requests_per_socket(i64, double) +declare i64 @js_node_https_server_set_timeout_method(i64, double, i64) +declare i64 @js_node_http2_create_server(double, double) +declare i64 @js_node_http2_create_secure_server(double, i64) +declare i64 @js_node_http2_connect(double, double, i64) +declare i64 @js_node_http2_server_listen(i64, i64) +declare void @js_node_http2_server_close(i64, i64) +declare i64 @js_node_http2_server_address_json(i64) +declare double @js_node_http2_server_on(i64, i64, i64) +declare i64 @js_node_http2_get_default_settings() +declare i64 @js_node_http2_get_packed_settings(i64) +declare i64 @js_node_http2_get_unpacked_settings(i64) +declare i64 @js_pg_client_connect(i64) +declare i64 @js_pg_client_end(i64) +declare i64 @js_pg_client_new(i64) +declare i64 @js_pg_client_query(i64, i64) +declare i64 @js_pg_client_query_params(i64, i64, i64) +declare i64 @js_pg_connect(i64) +declare i64 @js_pg_create_pool(i64) +declare i64 @js_pg_pool_end(i64) +declare i64 @js_pg_pool_new(i64) +declare i64 @js_pg_pool_query(i64, i64) +declare i64 @js_ioredis_connect(i64) +declare i64 @js_ioredis_decr(i64, i64) +declare i64 @js_ioredis_del(i64, i64) +declare void @js_ioredis_disconnect(i64) +declare i64 @js_ioredis_exists(i64, i64) +declare i64 @js_ioredis_expire(i64, i64, double) +declare i64 @js_ioredis_get(i64, i64) +declare i64 @js_ioredis_hdel(i64, i64, i64) +declare i64 @js_ioredis_hget(i64, i64, i64) +declare i64 @js_ioredis_hgetall(i64, i64) +declare i64 @js_ioredis_hlen(i64, i64) +declare i64 @js_ioredis_hset(i64, i64, i64, i64) +declare i64 @js_ioredis_incr(i64, i64) +declare i64 @js_ioredis_new(i64) +declare i64 @js_ioredis_ping(i64) +declare i64 @js_ioredis_quit(i64) +declare i64 @js_ioredis_set(i64, i64, i64) +declare i64 @js_ioredis_setex(i64, i64, double, i64) +declare i64 @js_mongodb_client_close(i64) +declare i64 @js_mongodb_client_connect(i64) +declare i64 @js_mongodb_client_db(i64, i64) +declare i64 @js_mongodb_client_list_databases(i64) +declare i64 @js_mongodb_client_new(i64) +declare i64 @js_mongodb_collection_count_value(i64, double) +declare i64 @js_mongodb_collection_delete_many_value(i64, double) +declare i64 @js_mongodb_collection_delete_one_value(i64, double) +declare i64 @js_mongodb_collection_find_one_value(i64, double) +declare i64 @js_mongodb_collection_find_value(i64, double) +declare i64 @js_mongodb_collection_insert_many_value(i64, double) +declare i64 @js_mongodb_collection_insert_one_value(i64, double) +declare i64 @js_mongodb_collection_update_many_value(i64, double, double) +declare i64 @js_mongodb_collection_update_one_value(i64, double, double) +declare i64 @js_mongodb_collection_count(i64, i64) +declare i64 @js_mongodb_collection_delete_many(i64, i64) +declare i64 @js_mongodb_collection_delete_one(i64, i64) +declare i64 @js_mongodb_collection_find(i64, i64) +declare i64 @js_mongodb_collection_find_one(i64, i64) +declare i64 @js_mongodb_collection_insert_many(i64, i64) +declare i64 @js_mongodb_collection_insert_one(i64, i64) +declare i64 @js_mongodb_collection_update_many(i64, i64, i64) +declare i64 @js_mongodb_collection_update_one(i64, i64, i64) +declare i64 @js_mongodb_connect(i64) +declare i64 @js_mongodb_db_collection(i64, i64) +declare i64 @js_mongodb_db_list_collections(i64) +declare void @js_sqlite_close(i64) +declare void @js_sqlite_exec(i64, i64) +declare i64 @js_sqlite_open(i64) +declare i64 @js_sqlite_pragma(i64, i64, i64) +declare i64 @js_sqlite_prepare(i64, i64) +declare i64 @js_sqlite_stmt_all(i64, i64) +declare i64 @js_sqlite_stmt_columns(i64) +declare i64 @js_sqlite_stmt_get(i64, i64) +declare i64 @js_sqlite_stmt_run(i64, i64) +declare i64 @js_sqlite_transaction(i64, i64) +declare void @js_sqlite_transaction_commit(i64) +declare void @js_sqlite_transaction_rollback(i64) +declare i64 @js_node_sqlite_backup(double, double, double) +declare i64 @js_node_sqlite_database_sync_call(double, double) +declare i64 @js_node_sqlite_database_sync_new(double, double) +declare i32 @js_node_sqlite_database_sync_open(i64) +declare i32 @js_node_sqlite_database_sync_close(i64) +declare i32 @js_node_sqlite_database_sync_dispose(i64) +declare i32 @js_node_sqlite_database_sync_exec(i64, double) +declare i64 @js_node_sqlite_database_sync_prepare(i64, double, double) +declare i32 @js_node_sqlite_database_sync_function(i64, double, double, double) +declare i32 @js_node_sqlite_database_sync_aggregate(i64, double, double) +declare i32 @js_node_sqlite_database_sync_enable_defensive(i64, double) +declare i32 @js_node_sqlite_database_sync_set_authorizer(i64, double) +declare i64 @js_node_sqlite_database_sync_create_tag_store(i64, double) +declare i64 @js_node_sqlite_database_sync_create_session(i64, double) +declare double @js_node_sqlite_database_sync_apply_changeset(i64, double, double) +declare i32 @js_node_sqlite_database_sync_enable_load_extension(i64, double) +declare i32 @js_node_sqlite_database_sync_load_extension(i64, double) +declare double @js_node_sqlite_database_sync_location(i64, double) +declare double @js_node_sqlite_database_sync_is_open(i64) +declare double @js_node_sqlite_database_sync_is_transaction(i64) +declare i64 @js_node_sqlite_database_sync_limits(i64) +declare i64 @js_node_sqlite_statement_sync_call(double, double) +declare i64 @js_node_sqlite_statement_sync_new(double, double) +declare i64 @js_node_sqlite_statement_sync_run(i64, i64) +declare double @js_node_sqlite_statement_sync_get(i64, i64) +declare i64 @js_node_sqlite_statement_sync_all(i64, i64) +declare double @js_node_sqlite_statement_sync_iterate(i64, i64) +declare i64 @js_node_sqlite_statement_sync_columns(i64) +declare i32 @js_node_sqlite_statement_sync_set_read_bigints(i64, double) +declare i32 @js_node_sqlite_statement_sync_set_return_arrays(i64, double) +declare i32 @js_node_sqlite_statement_sync_set_allow_bare_named_parameters(i64, double) +declare i32 @js_node_sqlite_statement_sync_set_allow_unknown_named_parameters(i64, double) +declare i64 @js_node_sqlite_statement_sync_source_sql(i64) +declare i64 @js_node_sqlite_statement_sync_expanded_sql(i64) +declare i64 @js_node_sqlite_sql_tag_store_run(i64, i64) +declare double @js_node_sqlite_sql_tag_store_get(i64, i64) +declare i64 @js_node_sqlite_sql_tag_store_all(i64, i64) +declare double @js_node_sqlite_sql_tag_store_iterate(i64, i64) +declare i32 @js_node_sqlite_sql_tag_store_clear(i64) +declare double @js_node_sqlite_sql_tag_store_size(i64) +declare double @js_node_sqlite_sql_tag_store_capacity(i64) +declare i64 @js_node_sqlite_sql_tag_store_db(i64) +declare i64 @js_node_sqlite_session_call(double, double) +declare i64 @js_node_sqlite_session_new(double, double) +declare i64 @js_node_sqlite_session_changeset(i64) +declare i64 @js_node_sqlite_session_patchset(i64) +declare i32 @js_node_sqlite_session_close(i64) +declare i32 @js_node_sqlite_session_dispose(i64) +declare i64 @js_os_cpus() +declare double @js_os_freemem() +declare i64 @js_os_homedir() +declare i64 @js_os_network_interfaces() +declare i64 @js_os_tmpdir() +declare double @js_os_totalmem() +declare double @js_os_uptime() +declare i64 @js_os_user_info() +declare i64 @js_os_user_info_buffer() +declare i64 @js_os_user_info_options(i64) +declare i64 @js_crypto_aes256_decrypt(i64, i64, i64) +declare i64 @js_crypto_aes256_encrypt(i64, i64, i64) +declare i64 @js_crypto_aes256_gcm_decrypt(i64, i64, i64) +declare i64 @js_crypto_aes256_gcm_encrypt(i64, i64, i64) +declare double @js_crypto_create_cipheriv(i64, i64, i64, double) +declare double @js_crypto_create_decipheriv(i64, i64, i64, double) +declare i64 @js_crypto_hkdf_sha256(i64, i64, i64, double) +declare i64 @js_crypto_hkdf_sync(i64, i64, i64, i64, double) +declare i64 @js_crypto_pbkdf2(i64, i64, double, double) +declare i64 @js_crypto_random_bytes_hex(double) +declare i64 @js_crypto_random_nonce() +declare i64 @js_crypto_scrypt(i64, i64, double) +declare double @js_crypto_generate_key_pair_sync(i64, i64) +declare i64 @js_crypto_scrypt_custom(i64, i64, double, double, double, double) +declare i64 @js_crypto_x25519_keypair() +declare i64 @js_crypto_x25519_shared_secret(i64, i64) +declare i64 @js_keccak256_native(i64) +declare i64 @js_keccak256_native_bytes(i64) +declare i64 @js_nanoid(double) +declare i64 @js_nanoid_custom(i64, double) +declare i64 @js_argon2_hash(i64) +declare i64 @js_argon2_hash_options(i64, i64) +declare i64 @js_argon2_verify(i64, i64) +declare i64 @js_bcrypt_compare(i64, i64) +declare double @js_bcrypt_compare_sync(i64, i64) +declare i64 @js_bcrypt_gen_salt(double) +declare i64 @js_bcrypt_hash(i64, double) +declare i64 @js_bcrypt_hash_sync(i64, double) +declare i64 @js_ads_interstitial_load(i64) +declare i64 @js_ads_interstitial_show() +declare i64 @js_ads_rewarded_load(i64) +declare i64 @js_ads_rewarded_show() +declare double @js_ads_banner_create(i64, i64) +declare void @js_ads_banner_destroy(double) +declare i64 @js_ads_request_consent() +declare i64 @js_perry_read_embedded(double) +declare i64 @js_perry_embedded_files() +declare double @js_thread_parallel_map(double, double) +declare double @js_thread_parallel_filter(double, double) +declare double @js_thread_spawn(double) +declare i64 @js_jwt_decode(i64) +declare i64 @js_jwt_sign(i64, i64, double, i64) +declare i64 @js_jwt_sign_es256(i64, i64, double, i64) +declare i64 @js_jwt_sign_rs256(i64, i64, double, i64) +declare i64 @js_jwt_verify(i64, i64) +declare i64 @js_jwt_verify_es256(i64, i64) +declare i64 @js_jwt_verify_rs256(i64, i64) +declare i64 @js_jwt_sign_dyn(i64, i64, i64, double, i64) +declare i64 @js_jwt_verify_dyn(i64, i64, i64) +declare i64 @js_jwt_sign_dyn_opts(i64, i64, double) +declare i64 @js_jwt_verify_dyn_opts(i64, i64, double) +declare double @js_axios_create(i64) +declare i64 @js_axios_delete(i64) +declare i64 @js_axios_get(i64) +declare i64 @js_axios_head(i64) +declare i64 @js_axios_options(i64) +declare i64 @js_axios_post(i64, double) +declare i64 @js_axios_put(i64, double) +declare i64 @js_axios_patch(i64, double) +declare i64 @js_axios_request(i64) +declare double @js_axios_response_status(i64) +declare i64 @js_axios_response_status_text(i64) +declare i64 @js_axios_response_data(i64) +declare double @js_axios_response_data_parsed(i64) +declare i64 @js_sharp_auto_orient(i64) +declare i64 @js_sharp_avif(i64, double) +declare i64 @js_sharp_blur(i64, double) +declare i64 @js_sharp_composite(i64, double) +declare i64 @js_sharp_extend(i64, double) +declare i64 @js_sharp_extract(i64, double) +declare i64 @js_sharp_flip(i64) +declare i64 @js_sharp_flop(i64) +declare i64 @js_sharp_from_buffer(i64, double) +declare i64 @js_sharp_from_file(i64) +declare i64 @js_sharp_from_input(i64) +declare i64 @js_sharp_grayscale(i64) +declare i64 @js_sharp_metadata(i64) +declare i64 @js_sharp_sharpen(i64) +declare i64 @js_sharp_trim(i64) +declare i64 @js_sharp_negate(i64) +declare i64 @js_sharp_quality(i64, double) +declare i64 @js_sharp_resize(i64, double, double) +declare i64 @js_sharp_rotate(i64, double) +declare i64 @js_sharp_to_buffer(i64) +declare i64 @js_sharp_to_file(i64, i64) +declare i64 @js_sharp_to_format(i64, i64) +declare void @js_cron_clear_interval(i64) +declare void @js_cron_clear_timeout(i64) +declare i64 @js_cron_describe(i64) +declare double @js_cron_job_is_running(i64) +declare i64 @js_cron_job_new(i64, i64, double) +declare void @js_cron_job_start(i64) +declare void @js_cron_job_stop(i64) +declare i64 @js_cron_next_date(i64) +declare i64 @js_cron_next_dates(i64, double) +declare i64 @js_cron_schedule(i64, i64) +declare i64 @js_cron_set_interval(double, double) +declare i64 @js_cron_set_timeout(double, double) +declare i32 @js_cron_timer_has_pending() +declare i32 @js_cron_timer_tick() +declare double @js_cron_validate(i64) +declare i64 @js_async_hooks_create_hook(double) +declare double @js_async_hooks_execution_async_id() +declare double @js_async_hooks_trigger_async_id() +declare double @js_async_hooks_execution_async_resource() +declare i64 @js_async_hook_enable(i64) +declare i64 @js_async_hook_disable(i64) +declare i64 @js_async_resource_new(double, double) +declare double @js_async_resource_async_id(i64) +declare double @js_async_resource_trigger_async_id(i64) +declare i64 @js_async_resource_emit_destroy(i64) +declare double @js_async_resource_run_in_async_scope(i64, double, double, i64) +declare i64 @js_async_resource_bind(i64, double, double) +declare i64 @js_async_resource_static_bind(i64, double) +declare void @js_async_local_storage_disable(i64) +declare void @js_async_local_storage_enter_with(i64, double) +declare double @js_async_local_storage_exit(i64, double, i64) +declare double @js_async_local_storage_get_store(i64) +declare i64 @js_async_local_storage_new() +declare double @js_async_local_storage_run(i64, double, double, i64) +declare i64 @js_disposable_stack_new() +declare i64 @js_async_disposable_stack_new() +declare double @js_suppressed_error_new(double, double, double) +declare i64 @js_zlib_deflate_sync(i64, double) +declare void @js_zlib_deflate(double, double) +declare i64 @js_zlib_gunzip_sync(i64) +declare void @js_zlib_gunzip(double, double) +declare i64 @js_zlib_gzip_sync(i64, double) +declare void @js_zlib_gzip(double, double) +declare i64 @js_zlib_inflate_sync(i64) +declare void @js_zlib_inflate(double, double) +declare i64 @js_zlib_deflate_raw_sync(double, double) +declare void @js_zlib_deflate_raw(double, double) +declare i64 @js_zlib_inflate_raw_sync(double) +declare void @js_zlib_inflate_raw(double, double) +declare i64 @js_zlib_unzip_sync(double) +declare void @js_zlib_unzip(double, double) +declare double @js_zlib_crc32(double, double) +declare i64 @js_zlib_brotli_compress_sync(i64) +declare i64 @js_zlib_brotli_decompress_sync(i64) +declare void @js_zlib_brotli_compress(double, double) +declare void @js_zlib_brotli_decompress(double, double) +declare i64 @js_zlib_zstd_compress_sync(double, double) +declare i64 @js_zlib_zstd_decompress_sync(double, double) +declare void @js_zlib_zstd_compress(double, double) +declare void @js_zlib_zstd_decompress(double, double) +declare i64 @js_zlib_create_gzip(double) +declare i64 @js_zlib_create_gunzip(double) +declare i64 @js_zlib_create_deflate(double) +declare i64 @js_zlib_create_inflate(double) +declare i64 @js_zlib_create_deflate_raw(double) +declare i64 @js_zlib_create_inflate_raw(double) +declare i64 @js_zlib_create_unzip(double) +declare i64 @js_zlib_create_brotli_compress(double) +declare i64 @js_zlib_create_zstd_compress(double) +declare i64 @js_zlib_create_zstd_decompress(double) +declare i64 @js_buffer_alloc_unsafe(i32) +declare i32 @js_buffer_byte_length(i64) +declare i32 @js_buffer_byte_length_value(double, double) +declare i64 @js_buffer_concat(i64) +declare i64 @js_buffer_concat_with_length(i64, double) +declare i32 @js_buffer_validate_size(double) +declare i64 @js_buffer_validate_concat_list(double) +declare i32 @js_buffer_copy(i64, i64, i32, i32, i32) +declare i32 @js_buffer_equals(i64, i64) +declare i64 @js_buffer_fill(i64, i32) +declare i64 @js_buffer_from_value(i64, i32) +declare double @js_buffer_is_ascii(double) +declare i32 @js_buffer_is_buffer(i64) +declare i32 @js_buffer_is_encoding(double) +declare double @js_buffer_is_utf8(double) +declare void @js_buffer_print(i64) +declare void @js_buffer_set(i64, i32, i32) +declare void @js_buffer_set_from(i64, i64, i32) +declare i64 @js_buffer_slice(i64, i32, i32) +declare i64 @js_buffer_to_string(i64, i32) +declare i64 @js_buffer_transcode(double, double, double) +declare i32 @js_buffer_write(i64, i64, i32, i32) +declare double @js_child_process_exec_sync(i64, i64) +declare double @js_child_process_exec(i64, double, double) +declare i64 @js_child_process_get_process_status(double) +declare i32 @js_child_process_kill_process(double) +declare i64 @js_child_process_spawn_background(double, i64, double, double) +declare i64 @js_child_process_spawn_sync(i64, i64, i64) +declare double @js_child_process_spawn_streams(i64, i64, i64) +declare double @js_pty_spawn(i64, i64, i64) +declare double @js_child_process_fork(i64, i64, i64) +declare double @js_child_process_exec_file(i64, double, double, double) +declare double @js_child_process_exec_file_sync(i64, double, double) +declare double @js_child_process_validate_command(double, ptr, i32) +declare double @js_child_process_validate_args(double) +declare double @js_child_process_validate_options(double, i32, i32) +declare double @js_child_process_validate_fork_module(double) +declare double @js_child_process_validate_spawn_args(double, i32, i32) +declare double @js_child_process_new() +declare i64 @js_cheerio_load(i64) +declare i64 @js_cheerio_load_fragment(i64) +declare i64 @js_cheerio_select(i64, i64) +declare i64 @js_cheerio_selection_attr(i64, i64) +declare i64 @js_cheerio_selection_attrs(i64, i64) +declare i64 @js_cheerio_selection_children(i64, i64) +declare i64 @js_cheerio_selection_eq(i64, double) +declare i64 @js_cheerio_selection_find(i64, i64) +declare i64 @js_cheerio_selection_first(i64) +declare double @js_cheerio_selection_has_class(i64, i64) +declare i64 @js_cheerio_selection_html(i64) +declare double @js_cheerio_selection_is(i64, i64) +declare i64 @js_cheerio_selection_last(i64) +declare double @js_cheerio_selection_length(i64) +declare i64 @js_cheerio_selection_parent(i64) +declare i64 @js_cheerio_selection_text(i64) +declare i64 @js_cheerio_selection_texts(i64) +declare i64 @js_cheerio_selection_to_array(i64) +declare double @js_url_file_url_to_path(double, double) +declare double @js_url_file_url_to_path_buffer(double, double) +declare double @js_url_get_hash(i64) +declare double @js_url_get_host(i64) +declare double @js_url_get_hostname(i64) +declare double @js_url_get_href(i64) +declare double @js_url_get_origin(i64) +declare double @js_url_get_pathname(i64) +declare double @js_url_get_port(i64) +declare double @js_url_get_protocol(i64) +declare double @js_url_get_search(i64) +declare double @js_url_get_search_params(i64) +declare i64 @js_url_new(i64) +declare i64 @js_url_new_with_base(i64, i64) +declare i64 @js_url_pattern_new(double, double) +declare double @js_url_pattern_constructor_call(double, double) +declare i32 @js_url_can_parse(i64) +declare i32 @js_url_can_parse_with_base(i64, i64) +declare i64 @js_url_parse(i64) +declare i64 @js_url_parse_with_base(i64, i64) +declare void @js_url_set_pathname(i64, double) +declare void @js_url_set_search(i64, double) +declare void @js_url_set_hash(i64, double) +declare void @js_url_set_protocol(i64, double) +declare void @js_url_set_hostname(i64, double) +declare void @js_url_set_port(i64, double) +declare void @js_url_set_username(i64, double) +declare void @js_url_set_password(i64, double) +declare void @js_url_set_href(i64, double) +declare double @js_url_search_params_has2(i64, double, double) +declare void @js_url_search_params_delete2(i64, double, double) +declare double @js_url_search_params_throw_missing_args(i32) +declare void @js_url_search_params_append(i64, double, double) +declare void @js_url_search_params_delete(i64, double) +declare i64 @js_url_search_params_get(i64, double) +declare double @js_url_search_params_get_all(i64, double) +declare double @js_url_search_params_has(i64, double) +declare i64 @js_url_search_params_new(i64) +declare i64 @js_url_search_params_new_any(double) +declare i64 @js_url_search_params_new_empty() +declare double @js_url_search_params_subclass_init(double, double) +declare void @js_url_search_params_set(i64, double, double) +declare i64 @js_url_search_params_to_string(i64) +declare i32 @js_url_search_params_size(i64) +declare double @js_url_search_params_entries_arr(i64) +declare double @js_url_search_params_keys_arr(i64) +declare double @js_url_search_params_values_arr(i64) +declare void @js_url_search_params_sort(i64) +declare void @js_url_search_params_for_each(i64, double, double) +declare i64 @js_url_coerce_string(double) +declare double @js_url_path_to_file_url(double, double) +declare double @js_url_domain_to_ascii(double) +declare double @js_url_domain_to_unicode(double) +declare double @js_url_to_http_options(double) +declare double @js_url_legacy_url_new() +declare double @js_url_format(double, double) +declare double @js_url_legacy_parse(double, double, double) +declare double @js_url_legacy_resolve(double, double) +declare double @js_url_legacy_resolve_object(double, double) +declare void @js_ws_close(i64) +declare i64 @js_ws_connect(i64) +declare double @js_ws_connect_start(double) +declare i64 @js_ws_handle_to_i64(double) +declare double @js_ws_is_open(i64) +declare double @js_ws_message_count(i64) +declare double @js_ws_ready_state(i64) +declare i64 @js_ws_on(i64, i64, i64) +declare i64 @js_ws_receive(i64) +declare void @js_ws_send(i64, i64) +declare void @js_ws_send_to_client(double, i64) +declare void @js_ws_close_client(double) +declare void @js_ws_send_client_i64(i64, i64) +declare void @js_ws_close_client_i64(i64) +declare i64 @js_ws_on_client_i64(i64, i64, i64) +declare void @js_ws_server_close(i64) +declare i64 @js_ws_server_new(double) +declare i64 @js_ws_handle_upgrade(i64, double, double, double, i64) +declare i64 @js_ws_wait_for_message(i64, double) +declare i64 @js_pdf_create_pdf(double) +declare void @js_pdf_add_text(i64, i64, double, double, double) +declare void @js_pdf_add_line(i64, double, double, double, double) +declare void @js_pdf_new_page(i64) +declare void @js_pdf_save(i64) +declare i64 @js_commander_action(i64, i64) +declare i64 @js_commander_command(i64, i64) +declare i64 @js_commander_description(i64, i64) +declare i64 @js_commander_get_option(i64, i64) +declare double @js_commander_get_option_bool(i64, i64) +declare double @js_commander_get_option_number(i64, i64) +declare i64 @js_commander_name(i64, i64) +declare i64 @js_commander_new() +declare i64 @js_commander_option(i64, i64, i64, i64) +declare i64 @js_commander_opts(i64) +declare i64 @js_commander_parse(i64, double) +declare i64 @js_commander_required_option(i64, i64, i64, i64) +declare i64 @js_commander_version(i64, i64) +declare double @js_dotenv_config() +declare double @js_dotenv_config_path(i64) +declare i64 @js_dotenv_parse(i64) +declare double @js_datefns_add_days(double, double) +declare double @js_datefns_add_months(double, double) +declare double @js_datefns_add_years(double, double) +declare double @js_datefns_difference_in_days(double, double) +declare double @js_datefns_difference_in_hours(double, double) +declare double @js_datefns_difference_in_minutes(double, double) +declare double @js_datefns_end_of_day(double) +declare i64 @js_datefns_format(double, i64) +declare double @js_datefns_is_after(double, double) +declare double @js_datefns_is_before(double, double) +declare double @js_datefns_parse_iso(i64) +declare double @js_datefns_start_of_day(double) +declare double @js_dayjs_add(i64, double, i64) +declare double @js_dayjs_date(i64) +declare double @js_dayjs_day(i64) +declare double @js_dayjs_diff(i64, i64, i64) +declare double @js_dayjs_end_of(i64, i64) +declare double @js_dayjs_factory(i64) +declare i64 @js_dayjs_format(i64, i64) +declare double @js_dayjs_from_timestamp(double) +declare double @js_dayjs_hour(i64) +declare double @js_dayjs_is_after(i64, i64) +declare double @js_dayjs_is_before(i64, i64) +declare double @js_dayjs_is_same(i64, i64) +declare double @js_dayjs_is_valid(i64) +declare double @js_dayjs_millisecond(i64) +declare double @js_dayjs_minute(i64) +declare double @js_dayjs_month(i64) +declare double @js_dayjs_now() +declare double @js_dayjs_parse(i64) +declare double @js_dayjs_second(i64) +declare double @js_dayjs_start_of(i64, i64) +declare double @js_dayjs_subtract(i64, double, i64) +declare i64 @js_dayjs_to_iso_string(i64) +declare double @js_dayjs_unix(i64) +declare double @js_dayjs_value_of(i64) +declare double @js_dayjs_year(i64) +declare double @js_moment_add(i64, double, i64) +declare double @js_moment_clone(i64) +declare double @js_moment_date(i64) +declare double @js_moment_day(i64) +declare double @js_moment_diff(i64, i64, i64) +declare double @js_moment_end_of(i64, i64) +declare double @js_moment_factory(i64) +declare i64 @js_moment_format(i64, i64) +declare i64 @js_moment_from_now(i64) +declare double @js_moment_from_timestamp(double) +declare double @js_moment_hour(i64) +declare double @js_moment_is_after(i64, i64) +declare double @js_moment_is_before(i64, i64) +declare double @js_moment_is_between(i64, i64, i64) +declare double @js_moment_is_same(i64, i64, i64) +declare double @js_moment_is_valid(i64) +declare double @js_moment_millisecond(i64) +declare double @js_moment_minute(i64) +declare double @js_moment_month(i64) +declare double @js_moment_now() +declare double @js_moment_parse(i64) +declare double @js_moment_second(i64) +declare double @js_moment_start_of(i64, i64) +declare double @js_moment_subtract(i64, double, i64) +declare double @js_moment_to_date(i64) +declare i64 @js_moment_to_iso_string(i64) +declare double @js_moment_unix(i64) +declare double @js_moment_value_of(i64) +declare double @js_moment_year(i64) +declare i64 @js_decimal_abs(i64) +declare i64 @js_decimal_ceil(i64) +declare double @js_decimal_cmp(i64, i64) +declare double @js_decimal_cmp_value(i64, double) +declare i64 @js_decimal_coerce_to_handle(double) +declare i64 @js_decimal_div(i64, i64) +declare i64 @js_decimal_div_number(i64, double) +declare i64 @js_decimal_div_value(i64, double) +declare double @js_decimal_eq(i64, i64) +declare double @js_decimal_eq_value(i64, double) +declare i64 @js_decimal_floor(i64) +declare i64 @js_decimal_from_number(double) +declare i64 @js_decimal_from_string(i64) +declare double @js_decimal_gt(i64, i64) +declare double @js_decimal_gt_value(i64, double) +declare double @js_decimal_gte(i64, i64) +declare double @js_decimal_gte_value(i64, double) +declare double @js_decimal_is_negative(i64) +declare double @js_decimal_is_positive(i64) +declare double @js_decimal_is_zero(i64) +declare double @js_decimal_lt(i64, i64) +declare double @js_decimal_lt_value(i64, double) +declare double @js_decimal_lte(i64, i64) +declare double @js_decimal_lte_value(i64, double) +declare i64 @js_decimal_minus(i64, i64) +declare i64 @js_decimal_minus_number(i64, double) +declare i64 @js_decimal_minus_value(i64, double) +declare i64 @js_decimal_mod(i64, i64) +declare i64 @js_decimal_mod_value(i64, double) +declare i64 @js_decimal_neg(i64) +declare i64 @js_decimal_plus(i64, i64) +declare i64 @js_decimal_plus_number(i64, double) +declare i64 @js_decimal_plus_value(i64, double) +declare i64 @js_decimal_pow(i64, double) +declare i64 @js_decimal_round(i64) +declare i64 @js_decimal_sqrt(i64) +declare i64 @js_decimal_times(i64, i64) +declare i64 @js_decimal_times_number(i64, double) +declare i64 @js_decimal_times_value(i64, double) +declare i64 @js_decimal_to_fixed(i64, double) +declare double @js_decimal_to_number(i64) +declare i64 @js_decimal_to_string(i64) +declare i64 @js_ethers_format_ether(i64) +declare i64 @js_ethers_format_units(i64, double) +declare i64 @js_ethers_get_address(i64) +declare i64 @js_ethers_parse_ether(i64) +declare i64 @js_ethers_parse_units(i64, double) +declare i64 @js_lodash_camel_case(i64) +declare i64 @js_lodash_capitalize(i64) +declare i64 @js_lodash_chunk(i64, double) +declare double @js_lodash_clamp(double, double, double) +declare i64 @js_lodash_compact(i64) +declare i64 @js_lodash_concat(i64, i64) +declare i64 @js_lodash_difference(i64, i64) +declare i64 @js_lodash_drop(i64, double) +declare i64 @js_lodash_drop_right(i64, double) +declare double @js_lodash_ends_with(i64, i64) +declare i64 @js_lodash_escape(i64) +declare double @js_lodash_first(i64) +declare i64 @js_lodash_flatten(i64) +declare double @js_lodash_in_range(double, double, double) +declare double @js_lodash_includes(i64, i64) +declare i64 @js_lodash_initial(i64) +declare i64 @js_lodash_kebab_case(i64) +declare double @js_lodash_last(i64) +declare i64 @js_lodash_lower_case(i64) +declare i64 @js_lodash_lower_first(i64) +declare double @js_lodash_max(i64) +declare double @js_lodash_max_by(i64, double) +declare double @js_lodash_mean(i64) +declare double @js_lodash_mean_by(i64, double) +declare double @js_lodash_min(i64) +declare double @js_lodash_min_by(i64, double) +declare i64 @js_lodash_pad(i64, double) +declare i64 @js_lodash_pad_end(i64, double) +declare i64 @js_lodash_pad_start(i64, double) +declare double @js_lodash_random(double, double) +declare i64 @js_lodash_repeat(i64, double) +declare i64 @js_lodash_replace(i64, i64, i64) +declare i64 @js_lodash_reverse(i64) +declare double @js_lodash_size(i64) +declare i64 @js_lodash_snake_case(i64) +declare i64 @js_lodash_split(i64, i64) +declare i64 @js_lodash_start_case(i64) +declare double @js_lodash_starts_with(i64, i64) +declare double @js_lodash_sum(i64) +declare double @js_lodash_sum_by(i64, double) +declare i64 @js_lodash_tail(i64) +declare i64 @js_lodash_take(i64, double) +declare i64 @js_lodash_take_right(i64, double) +declare i64 @js_lodash_trim(i64) +declare i64 @js_lodash_trim_end(i64) +declare i64 @js_lodash_trim_start(i64) +declare i64 @js_lodash_truncate(i64, double) +declare i64 @js_lodash_unescape(i64) +declare i64 @js_lodash_uniq(i64) +declare i64 @js_lodash_upper_case(i64) +declare i64 @js_lodash_upper_first(i64) +declare void @js_lru_cache_clear(i64) +declare double @js_lru_cache_delete(i64, double) +declare double @js_lru_cache_get(i64, double) +declare double @js_lru_cache_has(i64, double) +declare i64 @js_lru_cache_new(double) +declare double @js_lru_cache_peek(i64, double) +declare i64 @js_lru_cache_set(i64, double, double) +declare double @js_lru_cache_size(i64) +declare double @js_event_emitter_subclass_init(double) +declare double @js_array_subclass_init(double, double) +declare double @js_map_set_subclass_init(double, i32, double) +declare double @js_promise_subclass_init(double, double) +declare double @js_node_stream_readable_new(double) +declare double @js_node_stream_readable_subclass_init(double, double) +declare double @js_node_stream_writable_new(double) +declare double @js_node_stream_writable_subclass_init(double, double) +declare double @js_node_stream_duplex_new(double) +declare double @js_node_stream_duplex_subclass_init(double, double) +declare double @js_node_stream_transform_new(double) +declare double @js_node_stream_transform_subclass_init(double, double) +declare double @js_node_stream_passthrough_new(double) +declare double @js_node_stream_readable_from(double) +declare double @js_node_stream_readable_from_options(double, double) +declare double @js_node_stream_duplex_from_options(double, double) +declare double @js_node_stream_is_disturbed(double) +declare double @js_node_stream_is_errored(double) +declare double @js_node_stream_is_readable(double) +declare double @js_node_stream_is_writable(double) +declare double @js_node_stream_is_array_buffer_view(double) +declare double @js_node_stream_is_uint8_array(double) +declare double @js_node_stream_is_destroyed(double) +declare double @js_node_stream_uint8_array_to_buffer(double) +declare double @js_node_stream_get_default_hwm(double) +declare double @js_node_stream_set_default_hwm(double, double) +declare double @js_node_stream_add_abort_signal(double, double) +declare double @js_node_stream_compose(i64) +declare double @js_node_stream_pipeline(i64) +declare double @js_node_stream_finished(i64) +declare double @js_node_stream_duplex_pair(double) +declare double @js_node_stream_readable_to_web(double) +declare double @js_node_stream_writable_to_web(double) +declare double @js_node_stream_duplex_to_web(double) +declare double @js_node_stream_readable_from_web(double, double) +declare double @js_node_stream_writable_from_web(double, double) +declare double @js_node_stream_duplex_from_web(double, double) +declare double @js_node_stream_to_web(double) +declare double @js_node_stream_from_web(double) +declare double @js_node_stream_method_readable_aborted(i64) +declare double @js_node_stream_method_closed(i64) +declare double @js_node_stream_method_errored(i64) +declare double @js_node_stream_method_readable_did_read(i64) +declare double @js_node_stream_method_destroyed(i64) +declare double @js_node_stream_method_destroy(i64, double) +declare double @js_node_stream_method_pause(i64) +declare double @js_node_stream_method_readable(i64) +declare double @js_node_stream_method_readable_length(i64) +declare double @js_node_stream_method_readable_flowing(i64) +declare double @js_node_stream_method_readable_ended(i64) +declare double @js_node_stream_method_readable_object_mode(i64) +declare double @js_node_stream_method_pipe(i64, double, double) +declare double @js_node_stream_method_unpipe(i64, double) +declare double @js_node_stream_method_is_paused(i64) +declare double @js_node_stream_method_resume(i64) +declare double @js_node_stream_method_readable_encoding(i64) +declare double @js_node_stream_method_cork(i64) +declare double @js_node_stream_method_uncork(i64) +declare double @js_node_stream_method_writable_corked(i64) +declare double @js_node_stream_method_writable_length(i64) +declare double @js_node_stream_method_writable_need_drain(i64) +declare double @js_node_stream_method_writable(i64) +declare double @js_node_stream_method_writable_ended(i64) +declare double @js_node_stream_method_writable_finished(i64) +declare double @js_node_stream_method_allow_half_open(i64) +declare double @js_node_stream_method_set_encoding(i64, double) +declare double @js_node_stream_method_writable_object_mode(i64) +declare double @js_event_emitter_emit(i64, i64, i64) +declare double @js_event_emitter_emit0(i64, i64) +declare double @js_event_emitter_listener_count(i64, i64, i64) +declare i64 @js_event_emitter_new() +declare i64 @js_event_emitter_new_with_options(double) +declare i64 @js_event_emitter_on(i64, i64, i64) +declare i64 @js_event_emitter_once(i64, i64, i64) +declare i64 @js_event_emitter_prepend_listener(i64, i64, i64) +declare i64 @js_event_emitter_prepend_once_listener(i64, i64, i64) +declare i64 @js_event_emitter_remove_all_listeners(i64, i64) +declare i64 @js_event_emitter_remove_listener(i64, i64, i64) +declare i64 @js_event_emitter_set_max_listeners(i64, double) +declare double @js_event_emitter_get_max_listeners(i64) +declare i64 @js_event_emitter_event_names(i64) +declare i64 @js_event_emitter_listeners(i64, i64) +declare i64 @js_event_emitter_raw_listeners(i64, i64) +declare double @js_event_emitter_domain_value(i64) +declare i64 @js_event_emitter_async_resource_new(double) +declare double @js_event_emitter_async_resource_call(double) +declare double @js_event_emitter_async_resource_async_id(i64) +declare double @js_event_emitter_async_resource_trigger_async_id(i64) +declare double @js_event_emitter_async_resource_async_resource(i64) +declare double @js_event_emitter_async_resource_emit_destroy(i64) +declare i64 @js_events_once(double, i64, double) +declare i64 @js_events_on(double, i64, double) +declare i64 @js_events_add_abort_listener(double, double) +declare i64 @js_events_get_event_listeners(double, i64) +declare double @js_events_listener_count(double, i64) +declare double @js_events_get_max_listeners(double) +declare double @js_events_set_max_listeners(double, i64) +declare double @js_events_init() +declare i64 @js_domain_create() +declare i64 @js_domain_on(i64, i64, i64) +declare double @js_domain_emit(i64, i64, i64) +declare double @js_domain_run(i64, double, i64) +declare double @js_domain_bind(i64, double) +declare double @js_domain_intercept(i64, double) +declare i64 @js_domain_add(i64, double) +declare i64 @js_domain_remove(i64, double) +declare double @js_domain_enter(i64) +declare double @js_domain_exit(i64) +declare i64 @js_string_decoder_new(i64) +declare double @js_string_decoder_write(i64, double) +declare double @js_string_decoder_end(i64, double) +declare double @js_querystring_escape(double) +declare double @js_querystring_unescape(double) +declare i64 @js_querystring_unescape_buffer(double, double) +declare i64 @js_querystring_parse(double, double, double, double) +declare double @js_querystring_stringify(double, double, double, double) +declare i32 @js_fastify_add_hook(i64, i64, i64) +declare i32 @js_fastify_all(i64, i64, i64) +declare i64 @js_fastify_create() +declare i64 @js_fastify_create_with_opts(double) +declare double @js_fastify_ctx_html(i64, i64, double) +declare double @js_fastify_ctx_json(i64, double, double) +declare double @js_fastify_ctx_redirect(i64, i64, double) +declare double @js_fastify_ctx_text(i64, i64, double) +declare i32 @js_fastify_delete(i64, i64, i64) +declare i32 @js_fastify_get(i64, i64, i64) +declare i32 @js_fastify_head(i64, i64, i64) +declare void @js_fastify_listen(i64, double, i64) +declare void @js_fastify_app_close(i64) +declare i64 @js_fastify_app_server(i64) +declare void @js_fastify_app_on(i64, i64, i64) +declare i32 @js_fastify_options(i64, i64, i64) +declare i32 @js_fastify_patch(i64, i64, i64) +declare i32 @js_fastify_post(i64, i64, i64) +declare i32 @js_fastify_put(i64, i64, i64) +declare i32 @js_fastify_register(i64, i64, double) +declare i64 @js_fastify_reply_header(i64, i64, i64) +declare i32 @js_fastify_reply_send(i64, double) +declare i64 @js_fastify_reply_status(i64, double) +declare i64 @js_fastify_reply_type(i64, i64) +declare i64 @js_fastify_req_body(i64) +declare double @js_fastify_req_get_user_data(i64) +declare i64 @js_fastify_req_header(i64, i64) +declare i64 @js_fastify_req_headers(i64) +declare double @js_fastify_req_json(i64) +declare i64 @js_fastify_req_method(i64) +declare i64 @js_fastify_req_param(i64, i64) +declare i64 @js_fastify_req_params(i64) +declare i64 @js_fastify_req_query(i64) +declare double @js_fastify_req_query_object(i64) +declare void @js_fastify_req_set_user_data(i64, double) +declare i64 @js_fastify_req_url(i64) +declare i32 @js_fastify_route(i64, i64, i64, i64) +declare i32 @js_fastify_set_error_handler(i64, i64) +declare double @js_nodemailer_create_transport(i64) +declare i64 @js_nodemailer_send_mail(i64, i64) +declare i64 @js_nodemailer_verify(i64) +declare i64 @js_ratelimit_block(i64, i64, double) +declare i64 @js_ratelimit_consume(i64, i64, double) +declare i64 @js_ratelimit_create(i64) +declare i64 @js_ratelimit_delete(i64, i64) +declare i64 @js_ratelimit_get(i64, i64) +declare i64 @js_ratelimit_new_from_options(i64) +declare i64 @js_ratelimit_penalty(i64, i64, double) +declare i64 @js_ratelimit_reward(i64, i64, double) +declare double @js_validator_contains(i64, i64) +declare double @js_validator_equals(i64, i64) +declare double @js_validator_is_alpha(i64) +declare double @js_validator_is_alphanumeric(i64) +declare double @js_validator_is_email(i64) +declare double @js_validator_is_empty(i64) +declare double @js_validator_is_float(i64) +declare double @js_validator_is_hexadecimal(i64) +declare double @js_validator_is_int(i64) +declare double @js_validator_is_json(i64) +declare double @js_validator_is_length(i64, double, double) +declare double @js_validator_is_lowercase(i64) +declare double @js_validator_is_numeric(i64) +declare double @js_validator_is_uppercase(i64) +declare double @js_validator_is_url(i64) +declare double @js_validator_is_uuid(i64) +declare i64 @js_date_to_locale_string(double) +declare i64 @js_number_to_locale_string(double) +declare double @js_value_to_locale_string(double) +declare i64 @js_string_split_regex(i64, i64) +declare i32 @js_object_delete_dynamic(i64, double) +declare double @js_object_get_prototype_of(double) +declare double @js_object_set_prototype_of(double, double) +declare double @js_object_define_properties(double, double) +declare double @js_math_acos(double) +declare double @js_math_asin(double) +declare double @js_math_atan(double) +declare double @js_math_atan2(double, double) +declare double @js_math_cos(double) +declare double @js_math_expm1(double) +declare double @js_math_log(double) +declare double @js_math_log10(double) +declare double @js_math_log1p(double) +declare double @js_math_log2(double) +declare double @js_math_sin(double) +declare double @js_math_tan(double) +declare double @js_atomics_load(ptr, double, double) +declare double @js_atomics_is_lock_free(ptr, double) +declare double @js_atomics_store(ptr, double, double, double) +declare double @js_atomics_add(ptr, double, double, double) +declare double @js_atomics_sub(ptr, double, double, double) +declare double @js_atomics_and(ptr, double, double, double) +declare double @js_atomics_or(ptr, double, double, double) +declare double @js_atomics_xor(ptr, double, double, double) +declare double @js_atomics_exchange(ptr, double, double, double) +declare double @js_atomics_compare_exchange(ptr, double, double, double, double) +declare double @js_atomics_notify(ptr, double, double, double) +declare double @js_atomics_wait(ptr, double, double, double, double) +declare double @js_atomics_wait_async(ptr, double, double, double, double) +declare double @js_number_is_finite(double) +declare double @js_json_get_bool(i64, i64) +declare double @js_json_get_number(i64, i64) +declare i64 @js_json_get_string(i64, i64) +declare double @js_json_is_valid(i64) +declare i64 @js_json_stringify_bool(double) +declare i64 @js_json_stringify_null() +declare i64 @js_json_stringify_number(double) +declare i64 @js_json_stringify_string(i64) +declare void @js_set_property(double, i64, i64, double) +declare i64 @js_error_get_message(i64) +declare double @js_await_js_promise(double) +declare i64 @js_text_decoder_decode(i64) +declare i64 @js_text_encoder_encode(double) +declare double @js_call_function(i64, i64, i64, i64, i64) +declare double @js_call_method(double, i64, i64, i64, i64) +declare double @js_call_value(double, i64, i64) +declare double @js_closure_call_array(i64, ptr, i64) +declare double @js_closure_call_apply_with_spread(double, ptr, i64, i64) +declare double @js_create_callback(i64, i64, i64) +declare double @js_dynamic_neg(double) +declare i32 @js_dynamic_string_equals(double, double) +declare double @js_is_nan(double) +declare i32 @js_jsvalue_compare(double, double) +declare i32 @js_jsvalue_loose_equals(double, double) +declare void @js_gc_collect() +declare void @js_console_assert(double, i64) +declare void @js_console_assert_spread(double, i64) +declare void @js_console_group(i64) +declare double @js_console_context(double) +declare double @js_console_create_task(double) +declare i64 @js_fetch_get(i64) +declare i64 @js_fetch_get_with_auth(i64, i64) +declare i64 @js_fetch_post(i64, i64, i64) +declare i64 @js_fetch_post_with_auth(i64, i64, i64) +declare double @js_fetch_stream_close(double) +declare i64 @js_fetch_stream_poll(double) +declare double @js_fetch_stream_start(i64, i64, i64, i64) +declare double @js_fetch_stream_status(double) +declare i64 @js_fetch_text(i64) +declare i64 @js_fetch_with_options(i64, i64, i64, i64) +declare void @js_fetch_set_pending_signal(double) +declare i64 @js_fetch_headers_to_json(double) +declare double @js_net_create_connection(i32, i64, i64) +declare i64 @js_net_create_server(i64, i64) +declare double @js_net_normalize_args(double) +declare double @js_net_create_server_handle_stub(double, double, double, double, double) +declare void @js_net_validate_create_server_options(double) +declare i64 @js_net_socket_set_timeout(i64, double, i64) +declare void @js_net_server_listen(i64, double, double, double) +declare void @js_net_server_close(i64, i64) +declare i64 @js_net_server_address(i64) +declare void @js_net_server_on(i64, i64, i64) +declare double @js_net_server_get_listening(i64) +declare double @js_net_server_get_connections(i64) +declare double @js_net_server_get_max_connections(i64) +declare double @js_net_server_set_max_connections(i64, double) +declare double @js_net_server_get_drop_max_connection(i64) +declare double @js_net_server_set_drop_max_connection(i64, double) +declare i64 @js_net_block_list_new() +declare double @js_net_block_list_is_block_list(double) +declare double @js_net_block_list_add_address(i64, i64, i64) +declare double @js_net_block_list_add_range(i64, i64, i64, i64) +declare double @js_net_block_list_add_subnet(i64, i64, double, i64) +declare double @js_net_block_list_check(i64, i64, i64) +declare double @js_net_block_list_to_json(i64) +declare i64 @js_net_block_list_rules(i64) +declare double @js_net_block_list_from_json(i64, double) +declare i64 @js_net_socket_address_new(double) +declare double @js_net_socket_address_parse(i64) +declare i64 @js_net_socket_address_get_address(i64) +declare i64 @js_net_socket_address_get_family(i64) +declare double @js_net_socket_address_get_port(i64) +declare double @js_net_socket_address_get_flowlabel(i64) +declare double @js_net_socket_get_type_of_service(i64) +declare i64 @js_net_socket_set_type_of_service(i64, double) +declare i64 @js_net_socket_address(i64) +declare i64 @js_net_socket_once(i64, i64, i64) +declare i64 @js_net_socket_remove_listener(i64, i64, i64) +declare i64 @js_net_socket_remove_all_listeners(i64, i64) +declare double @js_net_socket_listener_count(i64, i64) +declare i64 @js_net_socket_event_names(i64) +declare i64 @js_net_socket_reset_and_destroy(i64) +declare i64 @js_net_server_once(i64, i64, i64) +declare i64 @js_net_server_remove_listener(i64, i64, i64) +declare i64 @js_net_server_remove_all_listeners(i64, i64) +declare double @js_net_server_listener_count(i64, i64) +declare i64 @js_net_server_event_names(i64) +declare double @js_performance_now() +declare double @js_perf_mark(double, double) +declare double @js_perf_measure(double, double, double) +declare double @js_perf_get_entries() +declare double @js_perf_get_entries_by_type(double) +declare double @js_perf_get_entries_by_name(double, double) +declare double @js_perf_clear_marks(double) +declare double @js_perf_clear_measures(double) +declare double @js_perf_event_loop_utilization(double, double) +declare double @js_perf_to_json() +declare double @js_perf_clear_resource_timings() +declare double @js_perf_set_resource_timing_buffer_size(double) +declare double @js_perf_mark_resource_timing(double, double, double, double, double, double, double, double) +declare double @js_perf_timerify(double, double) +declare double @js_perf_observer_new(double) +declare double @js_perf_observer_observe(double, double) +declare double @js_perf_observer_disconnect(double) +declare double @js_perf_observer_take_records(double) +declare double @js_perf_monitor_event_loop_delay(double) +declare double @js_perf_create_histogram(double) +declare double @js_perf_histogram_noop() +declare double @js_perf_histogram_percentile(double) +declare double @js_iter_result_set(double, i32) +declare double @js_iter_result_set_f64(double, i32) +declare double @js_iter_result_set_i32(i32, i32) +declare double @js_iter_result_set_i1(i32, i32) +declare double @js_iter_result_get_value() +declare double @js_iter_result_get_value_f64() +declare i32 @js_iter_result_get_value_i32() +declare i32 @js_iter_result_get_value_i1() +declare double @js_iter_result_get_done() +declare i64 @js_async_step_chain(double, i64) +declare i64 @js_async_step_done(double, i64) +declare i64 @js_get_current_step_closure() +declare double @js_async_first_call(double) +declare double @js_async_generator_resume(double, double, double) +declare i64 @js_slugify(i64) +declare i64 @js_slugify_strict(i64) +declare void @js_register_class_getter(i64, i64, i64, i64) +declare void @js_register_class_setter(i64, i64, i64, i64) +declare void @js_register_class_method_bind_length(i64, i64, i64, i64) +declare void @js_register_class_static_method_bind_length(i64, i64, i64, i64) +declare void @js_register_class_static_getter(i64, i64, i64, i64) +declare void @js_register_class_static_setter(i64, i64, i64, i64) +declare void @js_register_class_method(i64, i64, i64, i64, i64, i64, i64) +declare void @js_register_class_constructor(i64, i64, i64, i64) +declare void @js_register_class_constructor_flags(i64, i64, i64) +declare void @js_register_class_static_method(i64, i64, i64, i64, i64, i64) +declare double @js_class_static_method_call(double, i64, i64, ptr, i64) +declare double @js_class_method_bind(double, i64, i64) +declare double @js_class_method_bind_by_id(double, i64) +declare double @js_class_prototype_method_value(double, double) +declare double @js_implicit_this_get() +declare double @js_implicit_this_get_sloppy() +declare double @js_implicit_this_set(double) +declare double @js_static_this_resolve(double) +declare void @js_static_this_arm_classref(i32) +declare void @js_static_this_arm_value(double) +declare double @js_ctor_return_override(double, double, i32) +declare double @js_new_target_get() +declare double @js_new_target_set(double) +declare double @js_get_export(i64, i64, i64) +declare double @js_get_property(double, i64, i64) +declare i64 @js_load_module(i64, i64) +declare double @js_module_dynamic_import_apply_hooks(double) +declare double @js_native_call_method_nullsafe(double, i64, i64, i64, i64) +declare double @js_native_call_value(double, i64, i64) +declare double @js_new_from_handle(double, i64, i64) +declare double @js_new_instance(i64, i64, i64, i64, i64) +declare void @js_runtime_init() +declare double @js_object_set_symbol_method(double, double, double) +declare double @js_object_set_method_by_name(double, double, double) +declare double @js_object_define_accessor(double, double, double, double) +declare double @js_object_literal_set_computed(double, double, double) +declare double @js_object_literal_to_property_key(double) +declare double @js_object_literal_set_prototype(double, double) +declare double @js_to_primitive(double, i32) +declare void @js_register_class_has_instance(i32, i64) +declare void @js_register_class_to_string_tag(i32, i64) +declare double @js_object_to_string(double) +declare double @js_object_group_by(double, double) +declare double @js_map_group_by(double, double) +declare double @js_array_from_async(double, double, double) +declare double @js_jsx(double, double) +declare double @js_jsxs(double, double) +declare i64 @js_node_http_server_ref(i64) +declare i64 @js_node_http_server_unref(i64) +declare i64 @js_node_https_server_ref(i64) +declare i64 @js_node_https_server_unref(i64) +declare double @js_http_client_request_flush_headers(i64, double, double) +declare double @js_node_http_im_http_version_major(i64) +declare double @js_node_http_im_http_version_minor(i64) +declare i64 @js_node_http_im_pause_self(i64) +declare i64 @js_node_http_im_resume_self(i64) +declare i64 @js_commander_args_array(i64) +declare i64 @js_commander_argument(i64, i64) +declare double @__ic_decl_2() +declare double @__ic_decl_5() +declare double @__ic_decl_8() +declare double @__ic_decl_10() +declare double @__ic_decl_12() +declare double @__ic_decl_14() +declare double @__ic_decl_16() +declare double @__ic_decl_18() +declare double @__ic_decl_20() +declare double @__ic_decl_22() +declare double @__ic_decl_24() +declare double @__ic_decl_26() +declare double @__ic_decl_28() +declare double @__ic_decl_31() +declare double @__ic_decl_34() +declare double @__ic_decl_39() +declare double @__ic_decl_71() +declare double @__ic_decl_74() +declare double @__ic_decl_77() + +define double @perry_fn_batch_ts__buildRows(double %arg14, double %arg44) alwaysinline { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 2) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r9 = alloca i32 + store i32 0, ptr %r9 + %r10 = alloca i1 + %r11 = alloca i32 + %r35 = alloca double + store double 0x7FFC000000000001, ptr %r35 + %r68 = alloca i64 + %r69 = load i64, ptr @perry_class_keys_batch_ts__Row + store i64 %r69, ptr %r68 + %r7 = alloca double + store double %arg14, ptr %r7 + %r8 = alloca double + store double %arg44, ptr %r8 + call void @js_shadow_slot_bind(i32 0, ptr %r8) + store i32 0, ptr %r9 + store i1 false, ptr %r10 + store i32 0, ptr %r11 + %r12 = load double, ptr %r7 + %r13 = bitcast double %r12 to i64 + %r14 = and i64 %r13, -281474976710656 + %r15 = icmp ult i64 %r14, 9221401712017801216 + %r16 = icmp ugt i64 %r14, 9223090561878065152 + %r17 = or i1 %r15, %r16 + br i1 %r17, label %for.bound_i32.number.1, label %for.bound_i32.merge.3 + +for.bound_i32.number.1: + %r18 = fcmp oge double %r12, -2147483648.0 + %r19 = fcmp ole double %r12, 2147483647.0 + %r20 = and i1 %r18, %r19 + br i1 %r20, label %for.bound_i32.convert.2, label %for.bound_i32.merge.3 + +for.bound_i32.convert.2: + %r21 = fptosi double %r12 to i32 + %r22 = sitofp i32 %r21 to double + %r23 = fcmp oeq double %r22, %r12 + store i32 %r21, ptr %r11 + store i1 %r23, ptr %r10 + br label %for.bound_i32.merge.3 + +for.bound_i32.merge.3: + br label %for.cond.4 + +for.cond.4: + %r24 = load i1, ptr %r10 + br i1 %r24, label %for.cond.fast.8, label %for.cond.slow.9 + +for.body.5: + %r36 = call i32 @js_gc_temp_root_push(i64 0) + %r37 = load i32, ptr %r9 + %r38 = sitofp i32 %r37 to double + %r39 = load double, ptr @perry_global_batch_ts__1 + %r40 = load i32, ptr %r9 + %r41 = sitofp i32 %r40 to double + %r42 = fptosi double %r41 to i64 + %r43 = fptosi double 4.0 to i64 + %r44 = srem i64 %r42, %r43 + %r45 = sitofp i64 %r44 to double + %r46 = icmp eq i64 %r44, 0 + %r47 = fcmp olt double %r41, 0.0 + %r48 = and i1 %r46, %r47 + %r49 = fneg double %r45 + %r50 = select i1 %r48, double %r49, double %r45 + %r51 = bitcast double %r39 to i64 + %r52 = and i64 %r51, 281474976710655 + %r53 = call double @js_array_get_index_or_string(i64 %r52, double %r50) + %r54 = bitcast double %r53 to i64 + %r55 = call i32 @js_gc_temp_root_push(i64 %r54) + %r56 = load i32, ptr %r9 + %r57 = sitofp i32 %r56 to double + %r58 = fptosi double %r57 to i64 + %r59 = fptosi double 97.0 to i64 + %r60 = srem i64 %r58, %r59 + %r61 = sitofp i64 %r60 to double + %r62 = icmp eq i64 %r60, 0 + %r63 = fcmp olt double %r57, 0.0 + %r64 = and i1 %r62, %r63 + %r65 = fneg double %r61 + %r66 = select i1 %r64, double %r65, double %r61 + %r67 = fmul double %r66, 0.5 + %r70 = load i64, ptr %r68 + %r71 = call i64 @js_object_alloc_class_inline_keys(i32 1, i32 0, i32 4, i64 %r70) + %r72 = call i32 @js_gc_temp_root_push(i64 %r71) + %r73 = or i64 %r71, 9222527611924643840 + %r74 = bitcast i64 %r73 to double + %r75 = call i64 @js_gc_temp_root_get(i32 %r55) + %r76 = bitcast i64 %r75 to double + %r77 = call double @batch_ts__Row_constructor(double %r74, double %r38, double %r76, double %r67) + %r78 = call i64 @js_gc_temp_root_get(i32 %r72) + %r79 = or i64 %r78, 9222527611924643840 + %r80 = bitcast i64 %r79 to double + call void @js_gc_init_typed_shape_layout(i64 %r78, i32 4, ptr @perry_typed_shape_raw_f64_mask_batch_ts__Row, i32 1, ptr @perry_typed_shape_mask_batch_ts__Row, i32 1) + %r81 = call double @js_ctor_return_override(double %r80, double %r77, i32 0) + call void @js_gc_temp_root_truncate(i32 %r36) + store double %r81, ptr %r35 + %r82 = load ptr, ptr %r2 + %r83 = icmp eq ptr %r82, null + br i1 %r83, label %ss.slow.10, label %ss.chk_top.11 + +for.update.6: + %r164 = load i32, ptr %r9 + %r165 = add i32 %r164, 1 + store i32 %r165, ptr %r9 + %r166 = sitofp i32 %r164 to double + %r167 = sitofp i32 %r165 to double + br label %for.cond.4 + +for.exit.7: + %r168 = load ptr, ptr %r2 + %r169 = icmp eq ptr %r168, null + br i1 %r169, label %ss.slow.26, label %ss.chk_top.27 + +for.cond.fast.8: + %r25 = load i32, ptr %r9 + %r26 = load i32, ptr %r11 + %r27 = icmp slt i32 %r25, %r26 + br i1 %r27, label %for.body.5, label %for.exit.7 + +for.cond.slow.9: + %r28 = load i32, ptr %r9 + %r29 = sitofp i32 %r28 to double + %r30 = load double, ptr %r7 + %r31 = fcmp olt double %r29, %r30 + %r32 = select i1 %r31, i64 9222246136947933188, i64 9222246136947933187 + %r33 = bitcast i64 %r32 to double + %r34 = icmp eq i64 %r32, 9222246136947933188 + br i1 %r34, label %for.body.5, label %for.exit.7 + +ss.slow.10: + call void @js_shadow_slot_bind(i32 1, ptr %r35) + br label %ss.done.14 + +ss.chk_top.11: + %r84 = getelementptr inbounds i8, ptr %r82, i64 24 + %r85 = load i64, ptr %r84 + %r86 = icmp eq i64 %r85, -1 + br i1 %r86, label %ss.done.14, label %ss.chk_len.12 + +ss.chk_len.12: + %r87 = add i64 %r85, 1 + %r88 = getelementptr inbounds i8, ptr %r82, i64 8 + %r89 = load i64, ptr %r88 + %r90 = icmp ult i64 %r87, %r89 + br i1 %r90, label %ss.store.13, label %ss.done.14 + +ss.store.13: + %r91 = load ptr, ptr %r82 + %r92 = shl i64 %r87, 4 + %r93 = getelementptr inbounds i8, ptr %r91, i64 %r92 + %r94 = getelementptr inbounds i8, ptr %r93, i64 8 + %r95 = load i64, ptr %r35 + %r96 = ptrtoint ptr %r35 to i64 + %r97 = and i64 %r96, 1 + %r98 = icmp eq i64 %r97, 0 + %r99 = select i1 %r98, i64 %r96, i64 0 + %r100 = or i64 %r99, 1 + store i64 %r95, ptr %r93 + store i64 %r100, ptr %r94 + %r101 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r102 = icmp ne i32 %r101, 0 + br i1 %r102, label %ss.barrier.15, label %ss.done.14 + +ss.done.14: + %r103 = load double, ptr %r35 + %r104 = bitcast double %r103 to i64 + %r105 = load double, ptr %r8 + %r106 = bitcast double %r105 to i64 + %r107 = and i64 %r106, 281474976710655 + %r108 = sub i64 %r107, 7 + %r109 = inttoptr i64 %r108 to ptr + %r110 = load i8, ptr %r109 + %r111 = and i8 %r110, 128 + %r112 = icmp ne i8 %r111, 0 + br i1 %r112, label %apush.fwd.16, label %apush.nofwd.17 + +ss.barrier.15: + call void @js_write_barrier_root_nanbox(i64 %r95) + br label %ss.done.14 + +apush.fwd.16: + %r113 = call i64 @js_array_push_f64(i64 %r107, double %r103) + %r114 = or i64 %r113, 9222527611924643840 + %r115 = bitcast i64 %r114 to double + store double %r115, ptr %r8 + br label %apush.merge.20 + +apush.nofwd.17: + %r116 = sub i64 %r107, 6 + %r117 = inttoptr i64 %r116 to ptr + %r118 = load i16, ptr %r117 + %r119 = and i16 %r118, 1031 + %r120 = icmp eq i16 %r119, 0 + %r121 = icmp ult i64 %r107, 4096 + %r122 = inttoptr i64 %r107 to ptr + %r123 = select i1 %r121, ptr @perry_null_guard_zero, ptr %r122 + %r124 = load i32, ptr %r123 + %r125 = add i64 %r107, 4 + %r126 = inttoptr i64 %r125 to ptr + %r127 = load i32, ptr %r126 + %r128 = icmp ult i32 %r124, %r127 + %r129 = and i1 %r128, %r120 + br i1 %r129, label %apush.inbounds.18, label %apush.realloc.19 + +apush.inbounds.18: + %r130 = icmp ult i64 %r107, 4096 + %r131 = inttoptr i64 %r107 to ptr + %r132 = select i1 %r130, ptr @perry_null_guard_zero, ptr %r131 + %r133 = load i32, ptr %r132 + %r134 = zext i32 %r133 to i64 + %r135 = shl i64 %r134, 3 + %r136 = add i64 %r135, 8 + %r137 = add i64 %r107, %r136 + %r138 = inttoptr i64 %r137 to ptr + store double %r103, ptr %r138 + call void @js_string_addref_if_heap_string(double %r103) + call void @js_gc_note_slot_layout(i64 %r107, i32 %r133, i64 %r104) + call void @js_write_barrier_slot(i64 %r107, i64 %r137, i64 %r104) + call void @js_array_note_numeric_write(i64 %r107, i64 %r104) + %r139 = add i32 %r133, 1 + %r140 = inttoptr i64 %r107 to ptr + store i32 %r139, ptr %r140 + br label %apush.merge.20 + +apush.realloc.19: + %r141 = call i64 @js_array_push_f64(i64 %r107, double %r103) + %r142 = or i64 %r141, 9222527611924643840 + %r143 = bitcast i64 %r142 to double + store double %r143, ptr %r8 + br label %apush.merge.20 + +apush.merge.20: + %r144 = load double, ptr %r8 + %r145 = bitcast double %r144 to i64 + %r146 = and i64 %r145, 281474976710655 + %r147 = call i32 @js_array_length(i64 %r146) + %r148 = sitofp i32 %r147 to double + %r149 = load ptr, ptr %r2 + %r150 = icmp eq ptr %r149, null + br i1 %r150, label %ss.slow.21, label %ss.chk_top.22 + +ss.slow.21: + call void @js_shadow_slot_set(i32 1, i64 0) + br label %ss.done.25 + +ss.chk_top.22: + %r151 = getelementptr inbounds i8, ptr %r149, i64 24 + %r152 = load i64, ptr %r151 + %r153 = icmp eq i64 %r152, -1 + br i1 %r153, label %ss.done.25, label %ss.chk_len.23 + +ss.chk_len.23: + %r154 = add i64 %r152, 1 + %r155 = getelementptr inbounds i8, ptr %r149, i64 8 + %r156 = load i64, ptr %r155 + %r157 = icmp ult i64 %r154, %r156 + br i1 %r157, label %ss.store.24, label %ss.done.25 + +ss.store.24: + %r158 = load ptr, ptr %r149 + %r159 = shl i64 %r154, 4 + %r160 = getelementptr inbounds i8, ptr %r158, i64 %r159 + %r161 = getelementptr inbounds i8, ptr %r160, i64 8 + %r162 = load i64, ptr %r161 + %r163 = and i64 %r162, -2 + store i64 0, ptr %r160 + store i64 %r163, ptr %r161 + br label %ss.done.25 + +ss.done.25: + br label %for.update.6 + +ss.slow.26: + call void @js_shadow_slot_set(i32 0, i64 0) + br label %ss.done.30 + +ss.chk_top.27: + %r170 = getelementptr inbounds i8, ptr %r168, i64 24 + %r171 = load i64, ptr %r170 + %r172 = icmp eq i64 %r171, -1 + br i1 %r172, label %ss.done.30, label %ss.chk_len.28 + +ss.chk_len.28: + %r173 = add i64 %r171, 0 + %r174 = getelementptr inbounds i8, ptr %r168, i64 8 + %r175 = load i64, ptr %r174 + %r176 = icmp ult i64 %r173, %r175 + br i1 %r176, label %ss.store.29, label %ss.done.30 + +ss.store.29: + %r177 = load ptr, ptr %r168 + %r178 = shl i64 %r173, 4 + %r179 = getelementptr inbounds i8, ptr %r177, i64 %r178 + %r180 = getelementptr inbounds i8, ptr %r179, i64 8 + %r181 = load i64, ptr %r180 + %r182 = and i64 %r181, -2 + store i64 0, ptr %r179 + store i64 %r182, ptr %r180 + br label %ss.done.30 + +ss.done.30: + %r183 = load ptr, ptr %r2 + %r184 = icmp eq ptr %r183, null + br i1 %r184, label %ss.slow.31, label %ss.chk_top.32 + +ss.slow.31: + call void @js_shadow_slot_set(i32 1, i64 0) + br label %ss.done.35 + +ss.chk_top.32: + %r185 = getelementptr inbounds i8, ptr %r183, i64 24 + %r186 = load i64, ptr %r185 + %r187 = icmp eq i64 %r186, -1 + br i1 %r187, label %ss.done.35, label %ss.chk_len.33 + +ss.chk_len.33: + %r188 = add i64 %r186, 1 + %r189 = getelementptr inbounds i8, ptr %r183, i64 8 + %r190 = load i64, ptr %r189 + %r191 = icmp ult i64 %r188, %r190 + br i1 %r191, label %ss.store.34, label %ss.done.35 + +ss.store.34: + %r192 = load ptr, ptr %r183 + %r193 = shl i64 %r188, 4 + %r194 = getelementptr inbounds i8, ptr %r192, i64 %r193 + %r195 = getelementptr inbounds i8, ptr %r194, i64 8 + %r196 = load i64, ptr %r195 + %r197 = and i64 %r196, -2 + store i64 0, ptr %r194 + store i64 %r197, ptr %r195 + br label %ss.done.35 + +ss.done.35: + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double 0x7FFC000000000001 +} + +define double @perry_fn_batch_ts__shape(double %arg18) alwaysinline { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 1) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %arg18, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = load double, ptr %r7 + %r9 = call i64 @js_closure_alloc_singleton(ptr @perry_closure_batch_ts__7) + %r10 = or i64 %r9, 9222527611924643840 + %r11 = bitcast i64 %r10 to double + %r12 = bitcast double %r8 to i64 + %r13 = and i64 %r12, 281474976710655 + %r14 = call i64 @js_validate_array_map_callback(i64 %r13, double %r11) + %r15 = call i64 @js_array_map(i64 %r13, i64 %r14) + %r16 = or i64 %r15, 9222527611924643840 + %r17 = bitcast i64 %r16 to double + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r17 +} + +define double @perry_fn_batch_ts__ranked(double %arg23) alwaysinline { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 2) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r8 = alloca double + store double 0x7FFC000000000001, ptr %r8 + %r7 = alloca double + store double %arg23, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r9 = load double, ptr %r7 + %r10 = bitcast double %r9 to i64 + %r11 = and i64 %r10, 281474976710655 + %r12 = call i64 @js_array_slice_values(i64 %r11, double 0.0, double 0x7FFC000000000001) + %r13 = or i64 %r12, 9222527611924643840 + %r14 = bitcast i64 %r13 to double + store double %r14, ptr %r8 + %r15 = load ptr, ptr %r2 + %r16 = icmp eq ptr %r15, null + br i1 %r16, label %ss.slow.1, label %ss.chk_top.2 + +ss.slow.1: + call void @js_shadow_slot_bind(i32 1, ptr %r8) + br label %ss.done.5 + +ss.chk_top.2: + %r17 = getelementptr inbounds i8, ptr %r15, i64 24 + %r18 = load i64, ptr %r17 + %r19 = icmp eq i64 %r18, -1 + br i1 %r19, label %ss.done.5, label %ss.chk_len.3 + +ss.chk_len.3: + %r20 = add i64 %r18, 1 + %r21 = getelementptr inbounds i8, ptr %r15, i64 8 + %r22 = load i64, ptr %r21 + %r23 = icmp ult i64 %r20, %r22 + br i1 %r23, label %ss.store.4, label %ss.done.5 + +ss.store.4: + %r24 = load ptr, ptr %r15 + %r25 = shl i64 %r20, 4 + %r26 = getelementptr inbounds i8, ptr %r24, i64 %r25 + %r27 = getelementptr inbounds i8, ptr %r26, i64 8 + %r28 = load i64, ptr %r8 + %r29 = ptrtoint ptr %r8 to i64 + %r30 = and i64 %r29, 1 + %r31 = icmp eq i64 %r30, 0 + %r32 = select i1 %r31, i64 %r29, i64 0 + %r33 = or i64 %r32, 1 + store i64 %r28, ptr %r26 + store i64 %r33, ptr %r27 + %r34 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r35 = icmp ne i32 %r34, 0 + br i1 %r35, label %ss.barrier.6, label %ss.done.5 + +ss.done.5: + %r36 = load ptr, ptr %r2 + %r37 = icmp eq ptr %r36, null + br i1 %r37, label %ss.slow.7, label %ss.chk_top.8 + +ss.barrier.6: + call void @js_write_barrier_root_nanbox(i64 %r28) + br label %ss.done.5 + +ss.slow.7: + call void @js_shadow_slot_set(i32 0, i64 0) + br label %ss.done.11 + +ss.chk_top.8: + %r38 = getelementptr inbounds i8, ptr %r36, i64 24 + %r39 = load i64, ptr %r38 + %r40 = icmp eq i64 %r39, -1 + br i1 %r40, label %ss.done.11, label %ss.chk_len.9 + +ss.chk_len.9: + %r41 = add i64 %r39, 0 + %r42 = getelementptr inbounds i8, ptr %r36, i64 8 + %r43 = load i64, ptr %r42 + %r44 = icmp ult i64 %r41, %r43 + br i1 %r44, label %ss.store.10, label %ss.done.11 + +ss.store.10: + %r45 = load ptr, ptr %r36 + %r46 = shl i64 %r41, 4 + %r47 = getelementptr inbounds i8, ptr %r45, i64 %r46 + %r48 = getelementptr inbounds i8, ptr %r47, i64 8 + %r49 = load i64, ptr %r48 + %r50 = and i64 %r49, -2 + store i64 0, ptr %r47 + store i64 %r50, ptr %r48 + br label %ss.done.11 + +ss.done.11: + %r51 = load double, ptr %r8 + %r52 = call i64 @js_closure_alloc_singleton(ptr @perry_closure_batch_ts__9) + %r53 = or i64 %r52, 9222527611924643840 + %r54 = bitcast i64 %r53 to double + %r55 = bitcast double %r51 to i64 + %r56 = and i64 %r55, 281474976710655 + %r57 = call i64 @js_validate_array_comparator(double %r54) + %r58 = call i64 @js_array_sort_with_comparator(i64 %r56, i64 %r57) + %r59 = or i64 %r58, 9222527611924643840 + %r60 = bitcast i64 %r59 to double + %r61 = load double, ptr %r8 + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r61 +} + +define double @perry_fn_batch_ts__summarize(double %arg27) alwaysinline { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 3) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r8 = alloca double + store double 0x7FFC000000000001, ptr %r8 + %r33 = alloca i32 + store i32 0, ptr %r33 + %r67 = alloca double + store double 0x7FFC000000000001, ptr %r67 + %r130 = alloca i64 + %r131 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + store i64 %r131, ptr %r130 + %r7 = alloca double + store double %arg27, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r9 = call i64 @js_array_alloc(i32 0) + %r10 = or i64 %r9, 9222527611924643840 + %r11 = bitcast i64 %r10 to double + store double %r11, ptr %r8 + %r12 = load ptr, ptr %r2 + %r13 = icmp eq ptr %r12, null + br i1 %r13, label %ss.slow.1, label %ss.chk_top.2 + +ss.slow.1: + call void @js_shadow_slot_bind(i32 1, ptr %r8) + br label %ss.done.5 + +ss.chk_top.2: + %r14 = getelementptr inbounds i8, ptr %r12, i64 24 + %r15 = load i64, ptr %r14 + %r16 = icmp eq i64 %r15, -1 + br i1 %r16, label %ss.done.5, label %ss.chk_len.3 + +ss.chk_len.3: + %r17 = add i64 %r15, 1 + %r18 = getelementptr inbounds i8, ptr %r12, i64 8 + %r19 = load i64, ptr %r18 + %r20 = icmp ult i64 %r17, %r19 + br i1 %r20, label %ss.store.4, label %ss.done.5 + +ss.store.4: + %r21 = load ptr, ptr %r12 + %r22 = shl i64 %r17, 4 + %r23 = getelementptr inbounds i8, ptr %r21, i64 %r22 + %r24 = getelementptr inbounds i8, ptr %r23, i64 8 + %r25 = load i64, ptr %r8 + %r26 = ptrtoint ptr %r8 to i64 + %r27 = and i64 %r26, 1 + %r28 = icmp eq i64 %r27, 0 + %r29 = select i1 %r28, i64 %r26, i64 0 + %r30 = or i64 %r29, 1 + store i64 %r25, ptr %r23 + store i64 %r30, ptr %r24 + %r31 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r32 = icmp ne i32 %r31, 0 + br i1 %r32, label %ss.barrier.6, label %ss.done.5 + +ss.done.5: + store i32 0, ptr %r33 + br label %for.cond.7 + +ss.barrier.6: + call void @js_write_barrier_root_nanbox(i64 %r25) + br label %ss.done.5 + +for.cond.7: + %r34 = load i32, ptr %r33 + %r35 = sitofp i32 %r34 to double + %r36 = load double, ptr @perry_global_batch_ts__1 + %r37 = bitcast double %r36 to i64 + %r38 = and i64 %r37, 281474976710655 + %r39 = lshr i64 %r37, 48 + %r40 = and i64 %r39, 65533 + %r41 = icmp eq i64 %r40, 32765 + %r42 = icmp ugt i64 %r38, 1048575 + %r43 = and i1 %r41, %r42 + br i1 %r43, label %plen.check_gc.11, label %plen.slow.13 + +for.body.8: + %r68 = call i32 @js_gc_temp_root_push(i64 0) + %r69 = load double, ptr @perry_global_batch_ts__1 + %r70 = load i32, ptr %r33 + %r71 = bitcast double %r69 to i64 + %r72 = and i64 %r71, 281474976710655 + %r73 = lshr i64 %r71, 48 + %r74 = icmp eq i64 %r73, 32765 + %r75 = icmp ugt i64 %r72, 1048575 + %r76 = and i1 %r74, %r75 + br i1 %r76, label %arr.guard.deref.18, label %arr.fallback.16 + +for.update.9: + %r226 = load i32, ptr %r33 + %r227 = add i32 %r226, 1 + store i32 %r227, ptr %r33 + %r228 = sitofp i32 %r226 to double + %r229 = sitofp i32 %r227 to double + br label %for.cond.7 + +for.exit.10: + %r230 = load ptr, ptr %r2 + %r231 = icmp eq ptr %r230, null + br i1 %r231, label %ss.slow.35, label %ss.chk_top.36 + +plen.check_gc.11: + %r44 = sub i64 %r38, 8 + %r45 = inttoptr i64 %r44 to ptr + %r46 = load i8, ptr %r45 + %r47 = icmp eq i8 %r46, 1 + %r48 = icmp eq i8 %r46, 3 + %r49 = or i1 %r47, %r48 + %r50 = sub i64 %r38, 7 + %r51 = inttoptr i64 %r50 to ptr + %r52 = load i8, ptr %r51 + %r53 = and i8 %r52, 128 + %r54 = icmp eq i8 %r53, 0 + %r55 = and i1 %r49, %r54 + br i1 %r55, label %plen.fast.12, label %plen.slow.13 + +plen.fast.12: + %r56 = icmp ult i64 %r38, 4096 + %r57 = inttoptr i64 %r38 to ptr + %r58 = select i1 %r56, ptr @perry_null_guard_zero, ptr %r57 + %r59 = load i32, ptr %r58 + %r60 = uitofp i32 %r59 to double + br label %plen.merge.14 + +plen.slow.13: + %r61 = call double @js_value_length_f64(double %r36) + br label %plen.merge.14 + +plen.merge.14: + %r62 = phi double [ %r60, %plen.fast.12 ], [ %r61, %plen.slow.13 ] + %r63 = fcmp olt double %r35, %r62 + %r64 = select i1 %r63, i64 9222246136947933188, i64 9222246136947933187 + %r65 = bitcast i64 %r64 to double + %r66 = icmp eq i64 %r64, 9222246136947933188 + br i1 %r66, label %for.body.8, label %for.exit.10 + +arr.fast.15: + %r115 = bitcast double %r69 to i64 + %r116 = and i64 %r115, 281474976710655 + %r117 = zext i32 %r70 to i64 + %r118 = shl i64 %r117, 3 + %r119 = add i64 %r118, 8 + %r120 = add i64 %r116, %r119 + %r121 = inttoptr i64 %r120 to ptr + %r122 = load double, ptr %r121 + %r123 = bitcast double %r122 to i64 + %r124 = icmp eq i64 %r123, 9222246136947933200 + %r125 = bitcast i64 9222246136947933185 to double + %r126 = select i1 %r124, double %r125, double %r122 + br label %arr.merge.17 + +arr.fallback.16: + %r113 = sitofp i32 %r70 to double + %r114 = call double @js_typed_feedback_array_index_get_fallback_boxed(i64 8450987250308612096, double %r69, double %r113) + br label %arr.merge.17 + +arr.merge.17: + %r127 = phi double [ %r126, %arr.fast.15 ], [ %r114, %arr.fallback.16 ] + %r128 = bitcast double %r127 to i64 + %r129 = call i32 @js_gc_temp_root_push(i64 %r128) + %r132 = load i64, ptr %r130 + %r133 = call i64 @js_object_alloc_class_inline_keys(i32 3, i32 0, i32 4, i64 %r132) + %r134 = call i32 @js_gc_temp_root_push(i64 %r133) + %r135 = or i64 %r133, 9222527611924643840 + %r136 = bitcast i64 %r135 to double + %r137 = call i64 @js_gc_temp_root_get(i32 %r129) + %r138 = bitcast i64 %r137 to double + %r139 = call double @batch_ts____AnonShape_c33c4204c28b9430_constructor(double %r136, double %r138, double 0.0, double 0.0, double 0.0) + %r140 = call i64 @js_gc_temp_root_get(i32 %r134) + %r141 = or i64 %r140, 9222527611924643840 + %r142 = bitcast i64 %r141 to double + call void @js_gc_init_typed_shape_layout(i64 %r140, i32 4, ptr @perry_typed_shape_raw_f64_mask_batch_ts____AnonShape_c33c4204c28b9430, i32 1, ptr @perry_typed_shape_mask_batch_ts____AnonShape_c33c4204c28b9430, i32 1) + %r143 = call double @js_ctor_return_override(double %r142, double %r139, i32 0) + call void @js_gc_temp_root_truncate(i32 %r68) + store double %r143, ptr %r67 + %r144 = load ptr, ptr %r2 + %r145 = icmp eq ptr %r144, null + br i1 %r145, label %ss.slow.19, label %ss.chk_top.20 + +arr.guard.deref.18: + %r77 = bitcast double %r69 to i64 + %r78 = and i64 %r77, 281474976710655 + %r79 = sub i64 %r78, 8 + %r80 = inttoptr i64 %r79 to ptr + %r81 = load i8, ptr %r80 + %r82 = icmp eq i8 %r81, 1 + %r83 = sub i64 %r78, 7 + %r84 = inttoptr i64 %r83 to ptr + %r85 = load i8, ptr %r84 + %r86 = and i8 %r85, 128 + %r87 = icmp eq i8 %r86, 0 + %r88 = sub i64 %r78, 6 + %r89 = inttoptr i64 %r88 to ptr + %r90 = load i16, ptr %r89 + %r91 = and i16 %r90, 1024 + %r92 = icmp eq i16 %r91, 0 + %r93 = load volatile i8, ptr @PERRY_ARRAY_INDEX_FAST_PATH_INVALIDATED + %r94 = icmp eq i8 %r93, 0 + %r95 = inttoptr i64 %r78 to ptr + %r96 = load i32, ptr %r95 + %r97 = getelementptr i8, ptr %r95, i64 4 + %r98 = load i32, ptr %r97 + %r99 = icmp slt i32 %r70, 0 + %r100 = icmp eq i1 %r99, false + %r101 = icmp ult i32 %r70, %r96 + %r102 = icmp ule i32 %r96, 16000000 + %r103 = icmp ule i32 %r98, 16000000 + %r104 = icmp ule i32 %r96, %r98 + %r105 = and i1 %r82, %r87 + %r106 = and i1 %r105, %r92 + %r107 = and i1 %r106, %r94 + %r108 = and i1 %r107, %r100 + %r109 = and i1 %r108, %r101 + %r110 = and i1 %r109, %r102 + %r111 = and i1 %r110, %r103 + %r112 = and i1 %r111, %r104 + br i1 %r112, label %arr.fast.15, label %arr.fallback.16 + +ss.slow.19: + call void @js_shadow_slot_bind(i32 2, ptr %r67) + br label %ss.done.23 + +ss.chk_top.20: + %r146 = getelementptr inbounds i8, ptr %r144, i64 24 + %r147 = load i64, ptr %r146 + %r148 = icmp eq i64 %r147, -1 + br i1 %r148, label %ss.done.23, label %ss.chk_len.21 + +ss.chk_len.21: + %r149 = add i64 %r147, 2 + %r150 = getelementptr inbounds i8, ptr %r144, i64 8 + %r151 = load i64, ptr %r150 + %r152 = icmp ult i64 %r149, %r151 + br i1 %r152, label %ss.store.22, label %ss.done.23 + +ss.store.22: + %r153 = load ptr, ptr %r144 + %r154 = shl i64 %r149, 4 + %r155 = getelementptr inbounds i8, ptr %r153, i64 %r154 + %r156 = getelementptr inbounds i8, ptr %r155, i64 8 + %r157 = load i64, ptr %r67 + %r158 = ptrtoint ptr %r67 to i64 + %r159 = and i64 %r158, 1 + %r160 = icmp eq i64 %r159, 0 + %r161 = select i1 %r160, i64 %r158, i64 0 + %r162 = or i64 %r161, 1 + store i64 %r157, ptr %r155 + store i64 %r162, ptr %r156 + %r163 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r164 = icmp ne i32 %r163, 0 + br i1 %r164, label %ss.barrier.24, label %ss.done.23 + +ss.done.23: + %r165 = load double, ptr %r67 + %r166 = bitcast double %r165 to i64 + %r167 = load double, ptr %r8 + %r168 = bitcast double %r167 to i64 + %r169 = and i64 %r168, 281474976710655 + %r170 = sub i64 %r169, 7 + %r171 = inttoptr i64 %r170 to ptr + %r172 = load i8, ptr %r171 + %r173 = and i8 %r172, 128 + %r174 = icmp ne i8 %r173, 0 + br i1 %r174, label %apush.fwd.25, label %apush.nofwd.26 + +ss.barrier.24: + call void @js_write_barrier_root_nanbox(i64 %r157) + br label %ss.done.23 + +apush.fwd.25: + %r175 = call i64 @js_array_push_f64(i64 %r169, double %r165) + %r176 = or i64 %r175, 9222527611924643840 + %r177 = bitcast i64 %r176 to double + store double %r177, ptr %r8 + br label %apush.merge.29 + +apush.nofwd.26: + %r178 = sub i64 %r169, 6 + %r179 = inttoptr i64 %r178 to ptr + %r180 = load i16, ptr %r179 + %r181 = and i16 %r180, 1031 + %r182 = icmp eq i16 %r181, 0 + %r183 = icmp ult i64 %r169, 4096 + %r184 = inttoptr i64 %r169 to ptr + %r185 = select i1 %r183, ptr @perry_null_guard_zero, ptr %r184 + %r186 = load i32, ptr %r185 + %r187 = add i64 %r169, 4 + %r188 = inttoptr i64 %r187 to ptr + %r189 = load i32, ptr %r188 + %r190 = icmp ult i32 %r186, %r189 + %r191 = and i1 %r190, %r182 + br i1 %r191, label %apush.inbounds.27, label %apush.realloc.28 + +apush.inbounds.27: + %r192 = icmp ult i64 %r169, 4096 + %r193 = inttoptr i64 %r169 to ptr + %r194 = select i1 %r192, ptr @perry_null_guard_zero, ptr %r193 + %r195 = load i32, ptr %r194 + %r196 = zext i32 %r195 to i64 + %r197 = shl i64 %r196, 3 + %r198 = add i64 %r197, 8 + %r199 = add i64 %r169, %r198 + %r200 = inttoptr i64 %r199 to ptr + store double %r165, ptr %r200 + call void @js_string_addref_if_heap_string(double %r165) + call void @js_gc_note_slot_layout(i64 %r169, i32 %r195, i64 %r166) + call void @js_write_barrier_slot(i64 %r169, i64 %r199, i64 %r166) + call void @js_array_note_numeric_write(i64 %r169, i64 %r166) + %r201 = add i32 %r195, 1 + %r202 = inttoptr i64 %r169 to ptr + store i32 %r201, ptr %r202 + br label %apush.merge.29 + +apush.realloc.28: + %r203 = call i64 @js_array_push_f64(i64 %r169, double %r165) + %r204 = or i64 %r203, 9222527611924643840 + %r205 = bitcast i64 %r204 to double + store double %r205, ptr %r8 + br label %apush.merge.29 + +apush.merge.29: + %r206 = load double, ptr %r8 + %r207 = bitcast double %r206 to i64 + %r208 = and i64 %r207, 281474976710655 + %r209 = call i32 @js_array_length(i64 %r208) + %r210 = sitofp i32 %r209 to double + %r211 = load ptr, ptr %r2 + %r212 = icmp eq ptr %r211, null + br i1 %r212, label %ss.slow.30, label %ss.chk_top.31 + +ss.slow.30: + call void @js_shadow_slot_set(i32 2, i64 0) + br label %ss.done.34 + +ss.chk_top.31: + %r213 = getelementptr inbounds i8, ptr %r211, i64 24 + %r214 = load i64, ptr %r213 + %r215 = icmp eq i64 %r214, -1 + br i1 %r215, label %ss.done.34, label %ss.chk_len.32 + +ss.chk_len.32: + %r216 = add i64 %r214, 2 + %r217 = getelementptr inbounds i8, ptr %r211, i64 8 + %r218 = load i64, ptr %r217 + %r219 = icmp ult i64 %r216, %r218 + br i1 %r219, label %ss.store.33, label %ss.done.34 + +ss.store.33: + %r220 = load ptr, ptr %r211 + %r221 = shl i64 %r216, 4 + %r222 = getelementptr inbounds i8, ptr %r220, i64 %r221 + %r223 = getelementptr inbounds i8, ptr %r222, i64 8 + %r224 = load i64, ptr %r223 + %r225 = and i64 %r224, -2 + store i64 0, ptr %r222 + store i64 %r225, ptr %r223 + br label %ss.done.34 + +ss.done.34: + br label %for.update.9 + +ss.slow.35: + call void @js_shadow_slot_set(i32 2, i64 0) + br label %ss.done.39 + +ss.chk_top.36: + %r232 = getelementptr inbounds i8, ptr %r230, i64 24 + %r233 = load i64, ptr %r232 + %r234 = icmp eq i64 %r233, -1 + br i1 %r234, label %ss.done.39, label %ss.chk_len.37 + +ss.chk_len.37: + %r235 = add i64 %r233, 2 + %r236 = getelementptr inbounds i8, ptr %r230, i64 8 + %r237 = load i64, ptr %r236 + %r238 = icmp ult i64 %r235, %r237 + br i1 %r238, label %ss.store.38, label %ss.done.39 + +ss.store.38: + %r239 = load ptr, ptr %r230 + %r240 = shl i64 %r235, 4 + %r241 = getelementptr inbounds i8, ptr %r239, i64 %r240 + %r242 = getelementptr inbounds i8, ptr %r241, i64 8 + %r243 = load i64, ptr %r242 + %r244 = and i64 %r243, -2 + store i64 0, ptr %r241 + store i64 %r244, ptr %r242 + br label %ss.done.39 + +ss.done.39: + %r245 = load double, ptr %r7 + %r246 = call i64 @js_closure_alloc_singleton(ptr @perry_closure_batch_ts__11) + %r247 = or i64 %r246, 9222527611924643840 + %r248 = bitcast i64 %r247 to double + %r249 = load double, ptr %r8 + %r250 = bitcast double %r245 to i64 + %r251 = and i64 %r250, 281474976710655 + %r252 = call i64 @js_validate_array_callback(double %r248) + %r253 = call double @js_array_reduce(i64 %r251, i64 %r252, i32 1, double %r249) + %r254 = load ptr, ptr %r2 + %r255 = icmp eq ptr %r254, null + br i1 %r255, label %ss.slow.40, label %ss.chk_top.41 + +ss.slow.40: + call void @js_shadow_slot_set(i32 0, i64 0) + br label %ss.done.44 + +ss.chk_top.41: + %r256 = getelementptr inbounds i8, ptr %r254, i64 24 + %r257 = load i64, ptr %r256 + %r258 = icmp eq i64 %r257, -1 + br i1 %r258, label %ss.done.44, label %ss.chk_len.42 + +ss.chk_len.42: + %r259 = add i64 %r257, 0 + %r260 = getelementptr inbounds i8, ptr %r254, i64 8 + %r261 = load i64, ptr %r260 + %r262 = icmp ult i64 %r259, %r261 + br i1 %r262, label %ss.store.43, label %ss.done.44 + +ss.store.43: + %r263 = load ptr, ptr %r254 + %r264 = shl i64 %r259, 4 + %r265 = getelementptr inbounds i8, ptr %r263, i64 %r264 + %r266 = getelementptr inbounds i8, ptr %r265, i64 8 + %r267 = load i64, ptr %r266 + %r268 = and i64 %r267, -2 + store i64 0, ptr %r265 + store i64 %r268, ptr %r266 + br label %ss.done.44 + +ss.done.44: + %r269 = load double, ptr %r8 + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r269 +} + +define double @perry_fn_batch_ts__totalsRow(double %arg39) alwaysinline { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 2) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r8 = alloca double + store double 0x7FFC000000000001, ptr %r8 + %r11 = alloca i64 + %r12 = load i64, ptr @perry_class_keys_batch_ts__Row + store i64 %r12, ptr %r11 + %r45 = alloca i32 + store i32 0, ptr %r45 + %r73 = alloca double + %r76 = alloca i32 + %r7 = alloca double + store double %arg39, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r9 = call i32 @js_gc_temp_root_push(i64 0) + %r10 = load double, ptr @batch_ts_.str.0.handle + %r13 = load i64, ptr %r11 + %r14 = call i64 @js_object_alloc_class_inline_keys(i32 1, i32 0, i32 4, i64 %r13) + %r15 = call i32 @js_gc_temp_root_push(i64 %r14) + %r16 = or i64 %r14, 9222527611924643840 + %r17 = bitcast i64 %r16 to double + %r18 = load double, ptr @batch_ts_.str.0.handle + %r19 = call double @batch_ts__Row_constructor(double %r17, double 0.0, double %r18, double 0.0) + %r20 = call i64 @js_gc_temp_root_get(i32 %r15) + %r21 = or i64 %r20, 9222527611924643840 + %r22 = bitcast i64 %r21 to double + call void @js_gc_init_typed_shape_layout(i64 %r20, i32 4, ptr @perry_typed_shape_raw_f64_mask_batch_ts__Row, i32 1, ptr @perry_typed_shape_mask_batch_ts__Row, i32 1) + %r23 = call double @js_ctor_return_override(double %r22, double %r19, i32 0) + call void @js_gc_temp_root_truncate(i32 %r9) + store double %r23, ptr %r8 + %r24 = load ptr, ptr %r2 + %r25 = icmp eq ptr %r24, null + br i1 %r25, label %ss.slow.1, label %ss.chk_top.2 + +ss.slow.1: + call void @js_shadow_slot_bind(i32 1, ptr %r8) + br label %ss.done.5 + +ss.chk_top.2: + %r26 = getelementptr inbounds i8, ptr %r24, i64 24 + %r27 = load i64, ptr %r26 + %r28 = icmp eq i64 %r27, -1 + br i1 %r28, label %ss.done.5, label %ss.chk_len.3 + +ss.chk_len.3: + %r29 = add i64 %r27, 1 + %r30 = getelementptr inbounds i8, ptr %r24, i64 8 + %r31 = load i64, ptr %r30 + %r32 = icmp ult i64 %r29, %r31 + br i1 %r32, label %ss.store.4, label %ss.done.5 + +ss.store.4: + %r33 = load ptr, ptr %r24 + %r34 = shl i64 %r29, 4 + %r35 = getelementptr inbounds i8, ptr %r33, i64 %r34 + %r36 = getelementptr inbounds i8, ptr %r35, i64 8 + %r37 = load i64, ptr %r8 + %r38 = ptrtoint ptr %r8 to i64 + %r39 = and i64 %r38, 1 + %r40 = icmp eq i64 %r39, 0 + %r41 = select i1 %r40, i64 %r38, i64 0 + %r42 = or i64 %r41, 1 + store i64 %r37, ptr %r35 + store i64 %r42, ptr %r36 + %r43 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r44 = icmp ne i32 %r43, 0 + br i1 %r44, label %ss.barrier.6, label %ss.done.5 + +ss.done.5: + store i32 0, ptr %r45 + %r46 = load double, ptr %r7 + %r47 = bitcast double %r46 to i64 + %r48 = and i64 %r47, 281474976710655 + %r49 = lshr i64 %r47, 48 + %r50 = and i64 %r49, 65533 + %r51 = icmp eq i64 %r50, 32765 + %r52 = icmp ugt i64 %r48, 1048575 + %r53 = and i1 %r51, %r52 + br i1 %r53, label %plen.check_gc.7, label %plen.slow.9 + +ss.barrier.6: + call void @js_write_barrier_root_nanbox(i64 %r37) + br label %ss.done.5 + +plen.check_gc.7: + %r54 = sub i64 %r48, 8 + %r55 = inttoptr i64 %r54 to ptr + %r56 = load i8, ptr %r55 + %r57 = icmp eq i8 %r56, 1 + %r58 = icmp eq i8 %r56, 3 + %r59 = or i1 %r57, %r58 + %r60 = sub i64 %r48, 7 + %r61 = inttoptr i64 %r60 to ptr + %r62 = load i8, ptr %r61 + %r63 = and i8 %r62, 128 + %r64 = icmp eq i8 %r63, 0 + %r65 = and i1 %r59, %r64 + br i1 %r65, label %plen.fast.8, label %plen.slow.9 + +plen.fast.8: + %r66 = icmp ult i64 %r48, 4096 + %r67 = inttoptr i64 %r48 to ptr + %r68 = select i1 %r66, ptr @perry_null_guard_zero, ptr %r67 + %r69 = load i32, ptr %r68 + %r70 = uitofp i32 %r69 to double + br label %plen.merge.10 + +plen.slow.9: + %r71 = call double @js_value_length_f64(double %r46) + br label %plen.merge.10 + +plen.merge.10: + %r72 = phi double [ %r70, %plen.fast.8 ], [ %r71, %plen.slow.9 ] + store double %r72, ptr %r73 + %r74 = load double, ptr %r73 + %r75 = fptosi double %r74 to i32 + store i32 %r75, ptr %r76 + br label %for.cond.11 + +for.cond.11: + %r77 = load i32, ptr %r45 + %r78 = load i32, ptr %r76 + %r79 = icmp slt i32 %r77, %r78 + br i1 %r79, label %for.body.12, label %for.exit.14 + +for.body.12: + %r80 = load double, ptr %r8 + %r81 = load double, ptr %r8 + %r82 = bitcast double %r81 to i64 + %r83 = and i64 %r82, 281474976710655 + %r84 = inttoptr i64 %r83 to ptr + %r85 = getelementptr i8, ptr %r84, i64 32 + %r86 = getelementptr double, ptr %r85, i64 2 + %r87 = load double, ptr %r86 + %r88 = bitcast double %r87 to i64 + %r89 = call i32 @js_gc_temp_root_push(i64 %r88) + %r90 = load double, ptr %r7 + %r91 = load i32, ptr %r45 + %r92 = bitcast double %r90 to i64 + %r93 = and i64 %r92, 281474976710655 + %r94 = sub i64 %r93, 8 + %r95 = inttoptr i64 %r94 to ptr + %r96 = load i8, ptr %r95 + %r97 = icmp eq i8 %r96, 9 + %r98 = sub i64 %r93, 7 + %r99 = inttoptr i64 %r98 to ptr + %r100 = load i8, ptr %r99 + %r101 = and i8 %r100, 128 + %r102 = icmp ne i8 %r101, 0 + %r103 = or i1 %r97, %r102 + %r104 = sub i64 %r93, 6 + %r105 = inttoptr i64 %r104 to ptr + %r106 = load i16, ptr %r105 + %r107 = and i16 %r106, 1024 + %r108 = icmp ne i16 %r107, 0 + %r109 = or i1 %r103, %r108 + br i1 %r109, label %bidx.lazy.15, label %bidx.fast.16 + +for.update.13: + %r342 = load i32, ptr %r45 + %r343 = add i32 %r342, 1 + store i32 %r343, ptr %r45 + %r344 = sitofp i32 %r342 to double + %r345 = sitofp i32 %r343 to double + br label %for.cond.11 + +for.exit.14: + %r346 = load ptr, ptr %r2 + %r347 = icmp eq ptr %r346, null + br i1 %r347, label %ss.slow.53, label %ss.chk_top.54 + +bidx.lazy.15: + %r110 = call double @js_array_get_f64(i64 %r93, i32 %r91) + br label %bidx.merge.17 + +bidx.fast.16: + %r111 = zext i32 %r91 to i64 + %r112 = shl i64 %r111, 3 + %r113 = add i64 %r112, 8 + %r114 = add i64 %r93, %r113 + %r115 = inttoptr i64 %r114 to ptr + %r116 = load double, ptr %r115 + %r117 = bitcast double %r116 to i64 + %r118 = icmp eq i64 %r117, 9222246136947933200 + %r119 = bitcast i64 9222246136947933185 to double + %r120 = select i1 %r118, double %r119, double %r116 + br label %bidx.merge.17 + +bidx.merge.17: + %r121 = phi double [ %r120, %bidx.fast.16 ], [ %r110, %bidx.lazy.15 ] + %r122 = bitcast double %r121 to i64 + %r123 = and i64 %r122, 281474976710655 + %r124 = load double, ptr @batch_ts_.str.1.handle + %r125 = bitcast double %r124 to i64 + %r126 = and i64 %r125, 281474976710655 + %r127 = lshr i64 %r122, 48 + %r128 = icmp eq i64 %r127, 32761 + %r129 = icmp eq i64 %r127, 32766 + %r130 = and i64 %r127, 65533 + %r131 = icmp eq i64 %r130, 32765 + br i1 %r128, label %pget.recv_sso.18, label %pget.check_class_ref.24 + +pget.recv_sso.18: + %r195 = call double @js_object_get_field_by_name_f64(i64 %r122, i64 %r126) + br label %pget.recv_merge.22 + +pget.recv_ok.19: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612097, i64 %r123, i64 %r126) + %r133 = icmp ugt i64 %r123, 1048575 + %r134 = ptrtoint ptr @perry_ic_2 to i64 + %r135 = select i1 %r133, i64 %r123, i64 %r134 + %r136 = sub i64 %r135, 8 + %r137 = inttoptr i64 %r136 to ptr + %r138 = load i8, ptr %r137 + %r139 = icmp eq i8 %r138, 2 + %r140 = and i1 %r133, %r139 + %r141 = add i64 %r135, 12 + %r142 = inttoptr i64 %r141 to ptr + %r143 = load i32, ptr %r142 + %r144 = icmp eq i32 %r143, 1129268819 + %r145 = xor i1 %r144, true + %r146 = and i1 %r140, %r145 + %r147 = inttoptr i64 %r135 to ptr + %r148 = load i32, ptr %r147 + %r149 = icmp eq i32 %r148, 1 + %r150 = and i1 %r146, %r149 + %r151 = sub i64 %r135, 6 + %r152 = inttoptr i64 %r151 to ptr + %r153 = load i16, ptr %r152 + %r154 = and i16 %r153, 2048 + %r155 = icmp eq i16 %r154, 0 + %r156 = and i1 %r150, %r155 + %r157 = add i64 %r135, 16 + %r158 = inttoptr i64 %r157 to ptr + %r159 = load i64, ptr %r158 + %r160 = add i64 %r135, 8 + %r161 = inttoptr i64 %r160 to ptr + %r162 = load i32, ptr %r161 + %r163 = add i32 %r162, -2147483648 + %r164 = icmp ult i32 %r163, 1073741824 + %r165 = zext i32 %r162 to i64 + %r166 = or i64 %r165, 4611686018427387904 + %r167 = select i1 %r164, i64 %r166, i64 %r159 + %r168 = getelementptr i64, ptr @perry_ic_2, i64 0 + %r169 = load i64, ptr %r168 + %r170 = icmp eq i64 %r167, %r169 + %r171 = icmp ne i64 %r167, 0 + %r172 = and i1 %r156, %r170 + %r173 = and i1 %r172, %r171 + br i1 %r173, label %pic.hit.25, label %pic.miss.26 + +pget.recv_bad.20: + %r190 = icmp eq i64 %r122, 9222246136947933185 + %r191 = icmp eq i64 %r122, 9222246136947933186 + %r192 = or i1 %r190, %r191 + br i1 %r192, label %pget.throw_nullish.29, label %pget.recv_undef_return.30 + +pget.recv_class_ref.21: + %r132 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612097, i64 %r122, i64 %r126) + br label %pget.recv_merge.22 + +pget.recv_merge.22: + %r196 = phi double [ %r189, %pic.merge.27 ], [ %r194, %pget.recv_undef_return.30 ], [ %r195, %pget.recv_sso.18 ], [ %r132, %pget.recv_class_ref.21 ] + %r197 = call i64 @js_gc_temp_root_get(i32 %r89) + %r198 = bitcast i64 %r197 to double + %r199 = call double @js_dynamic_string_or_number_add(double %r198, double %r196) + call void @js_gc_temp_root_truncate(i32 %r89) + %r200 = bitcast double %r80 to i64 + %r201 = and i64 %r200, 281474976710655 + %r202 = inttoptr i64 %r201 to ptr + %r203 = getelementptr i8, ptr %r202, i64 32 + %r204 = getelementptr double, ptr %r203, i64 2 + %r205 = bitcast double %r199 to i64 + %r206 = and i64 %r205, 9218868437227405312 + %r207 = icmp ne i64 %r206, 9218868437227405312 + br i1 %r207, label %ptr_shape_set.raw_store.31, label %ptr_shape_set.downgrade.32 + +pget.check_ptr.23: + br i1 %r131, label %pget.recv_ok.19, label %pget.recv_bad.20 + +pget.check_class_ref.24: + br i1 %r129, label %pget.recv_class_ref.21, label %pget.check_ptr.23 + +pic.hit.25: + %r174 = getelementptr i64, ptr @perry_ic_2, i64 1 + %r175 = load i64, ptr %r174 + %r176 = add i64 %r135, 12 + %r177 = inttoptr i64 %r176 to ptr + %r178 = load i32, ptr %r177 + %r179 = zext i32 %r178 to i64 + %r180 = icmp ult i64 %r179, 4 + %r181 = select i1 %r180, i64 4, i64 %r179 + %r182 = icmp ult i64 %r175, %r181 + br i1 %r182, label %pic.hit.load.28, label %pic.miss.26 + +pic.miss.26: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612097) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612097) + %r188 = call double @js_object_get_field_ic_miss(i64 %r123, i64 %r126, ptr @perry_ic_2) + br label %pic.merge.27 + +pic.merge.27: + %r189 = phi double [ %r187, %pic.hit.load.28 ], [ %r188, %pic.miss.26 ] + br label %pget.recv_merge.22 + +pic.hit.load.28: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612097) + %r183 = shl i64 %r175, 3 + %r184 = add i64 %r123, 32 + %r185 = add i64 %r184, %r183 + %r186 = inttoptr i64 %r185 to ptr + %r187 = load double, ptr %r186 + br label %pic.merge.27 + +pget.throw_nullish.29: + %r193 = zext i1 %r191 to i32 + call void @js_throw_type_error_property_access(i32 %r193, ptr @batch_ts_.str.1.bytes, i64 5) + unreachable + +pget.recv_undef_return.30: + %r194 = call double @js_object_get_field_by_name_f64(i64 %r122, i64 %r126) + br label %pget.recv_merge.22 + +ptr_shape_set.raw_store.31: + store double %r199, ptr %r204 + br label %ptr_shape_set.merge.33 + +ptr_shape_set.downgrade.32: + %r208 = load double, ptr @batch_ts_.str.2.handle + %r209 = bitcast double %r208 to i64 + %r210 = and i64 %r209, 281474976710655 + call void @js_class_field_set_fallback(i64 8450987250308612099, i64 %r200, i64 %r210, double %r199) + br label %ptr_shape_set.merge.33 + +ptr_shape_set.merge.33: + %r211 = load double, ptr %r8 + %r212 = load double, ptr %r8 + %r213 = bitcast double %r212 to i64 + %r214 = and i64 %r213, 281474976710655 + %r215 = inttoptr i64 %r214 to ptr + %r216 = getelementptr i8, ptr %r215, i64 32 + %r217 = getelementptr double, ptr %r216, i64 3 + %r218 = load double, ptr %r217 + %r219 = bitcast double %r218 to i64 + %r220 = call i32 @js_gc_temp_root_push(i64 %r219) + %r221 = load double, ptr %r7 + %r222 = load i32, ptr %r45 + %r223 = bitcast double %r221 to i64 + %r224 = and i64 %r223, 281474976710655 + %r225 = sub i64 %r224, 8 + %r226 = inttoptr i64 %r225 to ptr + %r227 = load i8, ptr %r226 + %r228 = icmp eq i8 %r227, 9 + %r229 = sub i64 %r224, 7 + %r230 = inttoptr i64 %r229 to ptr + %r231 = load i8, ptr %r230 + %r232 = and i8 %r231, 128 + %r233 = icmp ne i8 %r232, 0 + %r234 = or i1 %r228, %r233 + %r235 = sub i64 %r224, 6 + %r236 = inttoptr i64 %r235 to ptr + %r237 = load i16, ptr %r236 + %r238 = and i16 %r237, 1024 + %r239 = icmp ne i16 %r238, 0 + %r240 = or i1 %r234, %r239 + br i1 %r240, label %bidx.lazy.34, label %bidx.fast.35 + +bidx.lazy.34: + %r241 = call double @js_array_get_f64(i64 %r224, i32 %r222) + br label %bidx.merge.36 + +bidx.fast.35: + %r242 = zext i32 %r222 to i64 + %r243 = shl i64 %r242, 3 + %r244 = add i64 %r243, 8 + %r245 = add i64 %r224, %r244 + %r246 = inttoptr i64 %r245 to ptr + %r247 = load double, ptr %r246 + %r248 = bitcast double %r247 to i64 + %r249 = icmp eq i64 %r248, 9222246136947933200 + %r250 = bitcast i64 9222246136947933185 to double + %r251 = select i1 %r249, double %r250, double %r247 + br label %bidx.merge.36 + +bidx.merge.36: + %r252 = phi double [ %r251, %bidx.fast.35 ], [ %r241, %bidx.lazy.34 ] + %r253 = bitcast double %r252 to i64 + %r254 = and i64 %r253, 281474976710655 + %r255 = load double, ptr @batch_ts_.str.3.handle + %r256 = bitcast double %r255 to i64 + %r257 = and i64 %r256, 281474976710655 + %r258 = lshr i64 %r253, 48 + %r259 = icmp eq i64 %r258, 32761 + %r260 = icmp eq i64 %r258, 32766 + %r261 = and i64 %r258, 65533 + %r262 = icmp eq i64 %r261, 32765 + br i1 %r259, label %pget.recv_sso.37, label %pget.check_class_ref.43 + +pget.recv_sso.37: + %r326 = call double @js_object_get_field_by_name_f64(i64 %r253, i64 %r257) + br label %pget.recv_merge.41 + +pget.recv_ok.38: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612100, i64 %r254, i64 %r257) + %r264 = icmp ugt i64 %r254, 1048575 + %r265 = ptrtoint ptr @perry_ic_5 to i64 + %r266 = select i1 %r264, i64 %r254, i64 %r265 + %r267 = sub i64 %r266, 8 + %r268 = inttoptr i64 %r267 to ptr + %r269 = load i8, ptr %r268 + %r270 = icmp eq i8 %r269, 2 + %r271 = and i1 %r264, %r270 + %r272 = add i64 %r266, 12 + %r273 = inttoptr i64 %r272 to ptr + %r274 = load i32, ptr %r273 + %r275 = icmp eq i32 %r274, 1129268819 + %r276 = xor i1 %r275, true + %r277 = and i1 %r271, %r276 + %r278 = inttoptr i64 %r266 to ptr + %r279 = load i32, ptr %r278 + %r280 = icmp eq i32 %r279, 1 + %r281 = and i1 %r277, %r280 + %r282 = sub i64 %r266, 6 + %r283 = inttoptr i64 %r282 to ptr + %r284 = load i16, ptr %r283 + %r285 = and i16 %r284, 2048 + %r286 = icmp eq i16 %r285, 0 + %r287 = and i1 %r281, %r286 + %r288 = add i64 %r266, 16 + %r289 = inttoptr i64 %r288 to ptr + %r290 = load i64, ptr %r289 + %r291 = add i64 %r266, 8 + %r292 = inttoptr i64 %r291 to ptr + %r293 = load i32, ptr %r292 + %r294 = add i32 %r293, -2147483648 + %r295 = icmp ult i32 %r294, 1073741824 + %r296 = zext i32 %r293 to i64 + %r297 = or i64 %r296, 4611686018427387904 + %r298 = select i1 %r295, i64 %r297, i64 %r290 + %r299 = getelementptr i64, ptr @perry_ic_5, i64 0 + %r300 = load i64, ptr %r299 + %r301 = icmp eq i64 %r298, %r300 + %r302 = icmp ne i64 %r298, 0 + %r303 = and i1 %r287, %r301 + %r304 = and i1 %r303, %r302 + br i1 %r304, label %pic.hit.44, label %pic.miss.45 + +pget.recv_bad.39: + %r321 = icmp eq i64 %r253, 9222246136947933185 + %r322 = icmp eq i64 %r253, 9222246136947933186 + %r323 = or i1 %r321, %r322 + br i1 %r323, label %pget.throw_nullish.48, label %pget.recv_undef_return.49 + +pget.recv_class_ref.40: + %r263 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612100, i64 %r253, i64 %r257) + br label %pget.recv_merge.41 + +pget.recv_merge.41: + %r327 = phi double [ %r320, %pic.merge.46 ], [ %r325, %pget.recv_undef_return.49 ], [ %r326, %pget.recv_sso.37 ], [ %r263, %pget.recv_class_ref.40 ] + %r328 = call i64 @js_gc_temp_root_get(i32 %r220) + %r329 = bitcast i64 %r328 to double + %r330 = call double @js_dynamic_string_or_number_add(double %r329, double %r327) + call void @js_gc_temp_root_truncate(i32 %r220) + %r331 = bitcast double %r211 to i64 + %r332 = and i64 %r331, 281474976710655 + %r333 = inttoptr i64 %r332 to ptr + %r334 = getelementptr i8, ptr %r333, i64 32 + %r335 = getelementptr double, ptr %r334, i64 3 + %r336 = bitcast double %r330 to i64 + %r337 = and i64 %r336, 9218868437227405312 + %r338 = icmp ne i64 %r337, 9218868437227405312 + br i1 %r338, label %ptr_shape_set.raw_store.50, label %ptr_shape_set.downgrade.51 + +pget.check_ptr.42: + br i1 %r262, label %pget.recv_ok.38, label %pget.recv_bad.39 + +pget.check_class_ref.43: + br i1 %r260, label %pget.recv_class_ref.40, label %pget.check_ptr.42 + +pic.hit.44: + %r305 = getelementptr i64, ptr @perry_ic_5, i64 1 + %r306 = load i64, ptr %r305 + %r307 = add i64 %r266, 12 + %r308 = inttoptr i64 %r307 to ptr + %r309 = load i32, ptr %r308 + %r310 = zext i32 %r309 to i64 + %r311 = icmp ult i64 %r310, 4 + %r312 = select i1 %r311, i64 4, i64 %r310 + %r313 = icmp ult i64 %r306, %r312 + br i1 %r313, label %pic.hit.load.47, label %pic.miss.45 + +pic.miss.45: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612100) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612100) + %r319 = call double @js_object_get_field_ic_miss(i64 %r254, i64 %r257, ptr @perry_ic_5) + br label %pic.merge.46 + +pic.merge.46: + %r320 = phi double [ %r318, %pic.hit.load.47 ], [ %r319, %pic.miss.45 ] + br label %pget.recv_merge.41 + +pic.hit.load.47: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612100) + %r314 = shl i64 %r306, 3 + %r315 = add i64 %r254, 32 + %r316 = add i64 %r315, %r314 + %r317 = inttoptr i64 %r316 to ptr + %r318 = load double, ptr %r317 + br label %pic.merge.46 + +pget.throw_nullish.48: + %r324 = zext i1 %r322 to i32 + call void @js_throw_type_error_property_access(i32 %r324, ptr @batch_ts_.str.3.bytes, i64 4) + unreachable + +pget.recv_undef_return.49: + %r325 = call double @js_object_get_field_by_name_f64(i64 %r253, i64 %r257) + br label %pget.recv_merge.41 + +ptr_shape_set.raw_store.50: + store double %r330, ptr %r335 + br label %ptr_shape_set.merge.52 + +ptr_shape_set.downgrade.51: + %r339 = load double, ptr @batch_ts_.str.4.handle + %r340 = bitcast double %r339 to i64 + %r341 = and i64 %r340, 281474976710655 + call void @js_class_field_set_fallback(i64 8450987250308612102, i64 %r331, i64 %r341, double %r330) + br label %ptr_shape_set.merge.52 + +ptr_shape_set.merge.52: + br label %for.update.13 + +ss.slow.53: + call void @js_shadow_slot_set(i32 0, i64 0) + br label %ss.done.57 + +ss.chk_top.54: + %r348 = getelementptr inbounds i8, ptr %r346, i64 24 + %r349 = load i64, ptr %r348 + %r350 = icmp eq i64 %r349, -1 + br i1 %r350, label %ss.done.57, label %ss.chk_len.55 + +ss.chk_len.55: + %r351 = add i64 %r349, 0 + %r352 = getelementptr inbounds i8, ptr %r346, i64 8 + %r353 = load i64, ptr %r352 + %r354 = icmp ult i64 %r351, %r353 + br i1 %r354, label %ss.store.56, label %ss.done.57 + +ss.store.56: + %r355 = load ptr, ptr %r346 + %r356 = shl i64 %r351, 4 + %r357 = getelementptr inbounds i8, ptr %r355, i64 %r356 + %r358 = getelementptr inbounds i8, ptr %r357, i64 8 + %r359 = load i64, ptr %r358 + %r360 = and i64 %r359, -2 + store i64 0, ptr %r357 + store i64 %r360, ptr %r358 + br label %ss.done.57 + +ss.done.57: + %r361 = load double, ptr %r8 + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r361 +} + +define double @perry_closure_batch_ts__7(i64 %this_closure, double %arg19) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 1) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r174 = alloca [1 x double] + %r191 = alloca i64 + %r192 = load i64, ptr @perry_class_keys_batch_ts__Row + store i64 %r192, ptr %r191 + %r219 = alloca [1 x double] + %r313 = alloca i64 + %r314 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 + store i64 %r314, ptr %r313 + %r7 = alloca double + store double %arg19, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = call i32 @js_gc_temp_root_push(i64 0) + %r9 = load double, ptr %r7 + %r10 = bitcast double %r9 to i64 + %r11 = and i64 %r10, 281474976710655 + %r12 = load double, ptr @batch_ts_.str.5.handle + %r13 = bitcast double %r12 to i64 + %r14 = and i64 %r13, 281474976710655 + %r15 = lshr i64 %r10, 48 + %r16 = icmp eq i64 %r15, 32761 + %r17 = icmp eq i64 %r15, 32766 + %r18 = and i64 %r15, 65533 + %r19 = icmp eq i64 %r18, 32765 + br i1 %r16, label %pget.recv_sso.1, label %pget.check_class_ref.7 + +pget.recv_sso.1: + %r83 = call double @js_object_get_field_by_name_f64(i64 %r10, i64 %r14) + br label %pget.recv_merge.5 + +pget.recv_ok.2: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612103, i64 %r11, i64 %r14) + %r21 = icmp ugt i64 %r11, 1048575 + %r22 = ptrtoint ptr @perry_ic_8 to i64 + %r23 = select i1 %r21, i64 %r11, i64 %r22 + %r24 = sub i64 %r23, 8 + %r25 = inttoptr i64 %r24 to ptr + %r26 = load i8, ptr %r25 + %r27 = icmp eq i8 %r26, 2 + %r28 = and i1 %r21, %r27 + %r29 = add i64 %r23, 12 + %r30 = inttoptr i64 %r29 to ptr + %r31 = load i32, ptr %r30 + %r32 = icmp eq i32 %r31, 1129268819 + %r33 = xor i1 %r32, true + %r34 = and i1 %r28, %r33 + %r35 = inttoptr i64 %r23 to ptr + %r36 = load i32, ptr %r35 + %r37 = icmp eq i32 %r36, 1 + %r38 = and i1 %r34, %r37 + %r39 = sub i64 %r23, 6 + %r40 = inttoptr i64 %r39 to ptr + %r41 = load i16, ptr %r40 + %r42 = and i16 %r41, 2048 + %r43 = icmp eq i16 %r42, 0 + %r44 = and i1 %r38, %r43 + %r45 = add i64 %r23, 16 + %r46 = inttoptr i64 %r45 to ptr + %r47 = load i64, ptr %r46 + %r48 = add i64 %r23, 8 + %r49 = inttoptr i64 %r48 to ptr + %r50 = load i32, ptr %r49 + %r51 = add i32 %r50, -2147483648 + %r52 = icmp ult i32 %r51, 1073741824 + %r53 = zext i32 %r50 to i64 + %r54 = or i64 %r53, 4611686018427387904 + %r55 = select i1 %r52, i64 %r54, i64 %r47 + %r56 = getelementptr i64, ptr @perry_ic_8, i64 0 + %r57 = load i64, ptr %r56 + %r58 = icmp eq i64 %r55, %r57 + %r59 = icmp ne i64 %r55, 0 + %r60 = and i1 %r44, %r58 + %r61 = and i1 %r60, %r59 + br i1 %r61, label %pic.hit.8, label %pic.miss.9 + +pget.recv_bad.3: + %r78 = icmp eq i64 %r10, 9222246136947933185 + %r79 = icmp eq i64 %r10, 9222246136947933186 + %r80 = or i1 %r78, %r79 + br i1 %r80, label %pget.throw_nullish.12, label %pget.recv_undef_return.13 + +pget.recv_class_ref.4: + %r20 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612103, i64 %r10, i64 %r14) + br label %pget.recv_merge.5 + +pget.recv_merge.5: + %r84 = phi double [ %r77, %pic.merge.10 ], [ %r82, %pget.recv_undef_return.13 ], [ %r83, %pget.recv_sso.1 ], [ %r20, %pget.recv_class_ref.4 ] + %r85 = load double, ptr @batch_ts_.str.6.handle + %r86 = call double @js_dynamic_string_or_number_add(double %r84, double %r85) + %r87 = bitcast double %r86 to i64 + %r88 = call i32 @js_gc_temp_root_push(i64 %r87) + %r89 = load double, ptr %r7 + %r90 = bitcast double %r89 to i64 + %r91 = and i64 %r90, 281474976710655 + %r92 = load double, ptr @batch_ts_.str.7.handle + %r93 = bitcast double %r92 to i64 + %r94 = and i64 %r93, 281474976710655 + %r95 = lshr i64 %r90, 48 + %r96 = icmp eq i64 %r95, 32761 + %r97 = icmp eq i64 %r95, 32766 + %r98 = and i64 %r95, 65533 + %r99 = icmp eq i64 %r98, 32765 + br i1 %r96, label %pget.recv_sso.14, label %pget.check_class_ref.20 + +pget.check_ptr.6: + br i1 %r19, label %pget.recv_ok.2, label %pget.recv_bad.3 + +pget.check_class_ref.7: + br i1 %r17, label %pget.recv_class_ref.4, label %pget.check_ptr.6 + +pic.hit.8: + %r62 = getelementptr i64, ptr @perry_ic_8, i64 1 + %r63 = load i64, ptr %r62 + %r64 = add i64 %r23, 12 + %r65 = inttoptr i64 %r64 to ptr + %r66 = load i32, ptr %r65 + %r67 = zext i32 %r66 to i64 + %r68 = icmp ult i64 %r67, 4 + %r69 = select i1 %r68, i64 4, i64 %r67 + %r70 = icmp ult i64 %r63, %r69 + br i1 %r70, label %pic.hit.load.11, label %pic.miss.9 + +pic.miss.9: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612103) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612103) + %r76 = call double @js_object_get_field_ic_miss(i64 %r11, i64 %r14, ptr @perry_ic_8) + br label %pic.merge.10 + +pic.merge.10: + %r77 = phi double [ %r75, %pic.hit.load.11 ], [ %r76, %pic.miss.9 ] + br label %pget.recv_merge.5 + +pic.hit.load.11: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612103) + %r71 = shl i64 %r63, 3 + %r72 = add i64 %r11, 32 + %r73 = add i64 %r72, %r71 + %r74 = inttoptr i64 %r73 to ptr + %r75 = load double, ptr %r74 + br label %pic.merge.10 + +pget.throw_nullish.12: + %r81 = zext i1 %r79 to i32 + call void @js_throw_type_error_property_access(i32 %r81, ptr @batch_ts_.str.5.bytes, i64 6) + unreachable + +pget.recv_undef_return.13: + %r82 = call double @js_object_get_field_by_name_f64(i64 %r10, i64 %r14) + br label %pget.recv_merge.5 + +pget.recv_sso.14: + %r163 = call double @js_object_get_field_by_name_f64(i64 %r90, i64 %r94) + br label %pget.recv_merge.18 + +pget.recv_ok.15: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612105, i64 %r91, i64 %r94) + %r101 = icmp ugt i64 %r91, 1048575 + %r102 = ptrtoint ptr @perry_ic_10 to i64 + %r103 = select i1 %r101, i64 %r91, i64 %r102 + %r104 = sub i64 %r103, 8 + %r105 = inttoptr i64 %r104 to ptr + %r106 = load i8, ptr %r105 + %r107 = icmp eq i8 %r106, 2 + %r108 = and i1 %r101, %r107 + %r109 = add i64 %r103, 12 + %r110 = inttoptr i64 %r109 to ptr + %r111 = load i32, ptr %r110 + %r112 = icmp eq i32 %r111, 1129268819 + %r113 = xor i1 %r112, true + %r114 = and i1 %r108, %r113 + %r115 = inttoptr i64 %r103 to ptr + %r116 = load i32, ptr %r115 + %r117 = icmp eq i32 %r116, 1 + %r118 = and i1 %r114, %r117 + %r119 = sub i64 %r103, 6 + %r120 = inttoptr i64 %r119 to ptr + %r121 = load i16, ptr %r120 + %r122 = and i16 %r121, 2048 + %r123 = icmp eq i16 %r122, 0 + %r124 = and i1 %r118, %r123 + %r125 = add i64 %r103, 16 + %r126 = inttoptr i64 %r125 to ptr + %r127 = load i64, ptr %r126 + %r128 = add i64 %r103, 8 + %r129 = inttoptr i64 %r128 to ptr + %r130 = load i32, ptr %r129 + %r131 = add i32 %r130, -2147483648 + %r132 = icmp ult i32 %r131, 1073741824 + %r133 = zext i32 %r130 to i64 + %r134 = or i64 %r133, 4611686018427387904 + %r135 = select i1 %r132, i64 %r134, i64 %r127 + %r136 = getelementptr i64, ptr @perry_ic_10, i64 0 + %r137 = load i64, ptr %r136 + %r138 = icmp eq i64 %r135, %r137 + %r139 = icmp ne i64 %r135, 0 + %r140 = and i1 %r124, %r138 + %r141 = and i1 %r140, %r139 + br i1 %r141, label %pic.hit.21, label %pic.miss.22 + +pget.recv_bad.16: + %r158 = icmp eq i64 %r90, 9222246136947933185 + %r159 = icmp eq i64 %r90, 9222246136947933186 + %r160 = or i1 %r158, %r159 + br i1 %r160, label %pget.throw_nullish.25, label %pget.recv_undef_return.26 + +pget.recv_class_ref.17: + %r100 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612105, i64 %r90, i64 %r94) + br label %pget.recv_merge.18 + +pget.recv_merge.18: + %r164 = phi double [ %r157, %pic.merge.23 ], [ %r162, %pget.recv_undef_return.26 ], [ %r163, %pget.recv_sso.14 ], [ %r100, %pget.recv_class_ref.17 ] + %r165 = call i64 @js_gc_temp_root_get(i32 %r88) + %r166 = bitcast i64 %r165 to double + %r167 = call double @js_dynamic_string_or_number_add(double %r166, double %r164) + call void @js_gc_temp_root_truncate(i32 %r88) + %r168 = bitcast double %r167 to i64 + %r169 = call i32 @js_gc_temp_root_push(i64 %r168) + %r170 = load double, ptr %r7 + %r171 = call double @js_object_get_own_field_or_undef(double %r170, ptr @batch_ts_.str.8.bytes, i64 7) + %r172 = bitcast double %r171 to i64 + %r173 = icmp eq i64 %r172, 9222246136947933185 + br i1 %r173, label %idisp.dispatch.28, label %idisp.override.27 + +pget.check_ptr.19: + br i1 %r99, label %pget.recv_ok.15, label %pget.recv_bad.16 + +pget.check_class_ref.20: + br i1 %r97, label %pget.recv_class_ref.17, label %pget.check_ptr.19 + +pic.hit.21: + %r142 = getelementptr i64, ptr @perry_ic_10, i64 1 + %r143 = load i64, ptr %r142 + %r144 = add i64 %r103, 12 + %r145 = inttoptr i64 %r144 to ptr + %r146 = load i32, ptr %r145 + %r147 = zext i32 %r146 to i64 + %r148 = icmp ult i64 %r147, 4 + %r149 = select i1 %r148, i64 4, i64 %r147 + %r150 = icmp ult i64 %r143, %r149 + br i1 %r150, label %pic.hit.load.24, label %pic.miss.22 + +pic.miss.22: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612105) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612105) + %r156 = call double @js_object_get_field_ic_miss(i64 %r91, i64 %r94, ptr @perry_ic_10) + br label %pic.merge.23 + +pic.merge.23: + %r157 = phi double [ %r155, %pic.hit.load.24 ], [ %r156, %pic.miss.22 ] + br label %pget.recv_merge.18 + +pic.hit.load.24: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612105) + %r151 = shl i64 %r143, 3 + %r152 = add i64 %r91, 32 + %r153 = add i64 %r152, %r151 + %r154 = inttoptr i64 %r153 to ptr + %r155 = load double, ptr %r154 + br label %pic.merge.23 + +pget.throw_nullish.25: + %r161 = zext i1 %r159 to i32 + call void @js_throw_type_error_property_access(i32 %r161, ptr @batch_ts_.str.7.bytes, i64 2) + unreachable + +pget.recv_undef_return.26: + %r162 = call double @js_object_get_field_by_name_f64(i64 %r90, i64 %r94) + br label %pget.recv_merge.18 + +idisp.override.27: + %r175 = getelementptr double, ptr %r174, i64 0 + store double 1.5, ptr %r175 + %r176 = getelementptr [1 x double], ptr %r174, i64 0, i64 0 + %r177 = call double @js_implicit_this_set(double %r170) + %r178 = bitcast double %r177 to i64 + %r179 = call i32 @js_gc_temp_root_push(i64 %r178) + %r180 = call double @js_native_call_value(double %r171, ptr %r176, i64 1) + %r181 = call i64 @js_gc_temp_root_get(i32 %r179) + %r182 = bitcast i64 %r181 to double + call void @js_gc_temp_root_truncate(i32 %r179) + %r183 = call double @js_implicit_this_set(double %r182) + br label %idisp.outer_merge.29 + +idisp.dispatch.28: + %r184 = bitcast double %r170 to i64 + %r185 = lshr i64 %r184, 48 + %r186 = icmp eq i64 %r185, 32765 + br i1 %r186, label %idispatch.tower.33, label %idispatch.default.31 + +idisp.outer_merge.29: + %r224 = phi double [ %r180, %idisp.override.27 ], [ %r223, %idispatch.merge.32 ] + %r225 = bitcast double %r224 to i64 + %r226 = call i32 @js_gc_temp_root_push(i64 %r225) + %r227 = load double, ptr %r7 + %r228 = bitcast double %r227 to i64 + %r229 = and i64 %r228, 281474976710655 + %r230 = load double, ptr @batch_ts_.str.7.handle + %r231 = bitcast double %r230 to i64 + %r232 = and i64 %r231, 281474976710655 + %r233 = lshr i64 %r228, 48 + %r234 = icmp eq i64 %r233, 32761 + %r235 = icmp eq i64 %r233, 32766 + %r236 = and i64 %r233, 65533 + %r237 = icmp eq i64 %r236, 32765 + br i1 %r234, label %pget.recv_sso.37, label %pget.check_class_ref.43 + +idispatch.case0.30: + %r193 = load i64, ptr %r191 + %r194 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r195 = icmp eq i8 %r194, 0 + %r196 = inttoptr i64 %r188 to ptr + %r197 = getelementptr i8, ptr %r196, i64 -7 + %r198 = load i8, ptr %r197 + %r199 = and i8 %r198, -128 + %r200 = icmp eq i8 %r199, 0 + %r201 = getelementptr i8, ptr %r196, i64 -6 + %r202 = load i16, ptr %r201 + %r203 = and i16 %r202, 2049 + %r204 = icmp eq i16 %r203, 0 + %r205 = load i32, ptr %r196 + %r206 = icmp eq i32 %r205, 1 + %r207 = getelementptr i8, ptr %r196, i64 16 + %r208 = load i64, ptr %r207 + %r209 = icmp eq i64 %r208, %r193 + %r210 = and i1 %r195, %r200 + %r211 = and i1 %r210, %r204 + %r212 = and i1 %r211, %r206 + %r213 = and i1 %r212, %r209 + br i1 %r213, label %idispatch.case0.pshape.34, label %idispatch.case0.generic.35 + +idispatch.default.31: + %r217 = ptrtoint ptr @batch_ts_.str.8.dispatch to i64 + %r218 = or i64 %r217, 9221120237041090560 + %r220 = getelementptr double, ptr %r219, i64 0 + store double 1.5, ptr %r220 + %r221 = getelementptr [1 x double], ptr %r219, i64 0, i64 0 + %r222 = call double @js_native_call_method_by_id(double %r170, i64 %r218, ptr %r221, i64 1) + br label %idispatch.merge.32 + +idispatch.merge.32: + %r223 = phi double [ %r216, %idispatch.case0.join.36 ], [ %r222, %idispatch.default.31 ] + br label %idisp.outer_merge.29 + +idispatch.tower.33: + %r187 = bitcast double %r170 to i64 + %r188 = and i64 %r187, 281474976710655 + %r189 = call i32 @js_object_get_class_id(i64 %r188) + %r190 = icmp eq i32 %r189, 1 + br i1 %r190, label %idispatch.case0.30, label %idispatch.default.31 + +idispatch.case0.pshape.34: + %r214 = call double @perry_method_batch_ts__Row__rescore__pshape(double %r170, double 1.5) + br label %idispatch.case0.join.36 + +idispatch.case0.generic.35: + %r215 = call double @perry_method_batch_ts__Row__rescore(double %r170, double 1.5) + br label %idispatch.case0.join.36 + +idispatch.case0.join.36: + %r216 = phi double [ %r214, %idispatch.case0.pshape.34 ], [ %r215, %idispatch.case0.generic.35 ] + br label %idispatch.merge.32 + +pget.recv_sso.37: + %r301 = call double @js_object_get_field_by_name_f64(i64 %r228, i64 %r232) + br label %pget.recv_merge.41 + +pget.recv_ok.38: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612107, i64 %r229, i64 %r232) + %r239 = icmp ugt i64 %r229, 1048575 + %r240 = ptrtoint ptr @perry_ic_12 to i64 + %r241 = select i1 %r239, i64 %r229, i64 %r240 + %r242 = sub i64 %r241, 8 + %r243 = inttoptr i64 %r242 to ptr + %r244 = load i8, ptr %r243 + %r245 = icmp eq i8 %r244, 2 + %r246 = and i1 %r239, %r245 + %r247 = add i64 %r241, 12 + %r248 = inttoptr i64 %r247 to ptr + %r249 = load i32, ptr %r248 + %r250 = icmp eq i32 %r249, 1129268819 + %r251 = xor i1 %r250, true + %r252 = and i1 %r246, %r251 + %r253 = inttoptr i64 %r241 to ptr + %r254 = load i32, ptr %r253 + %r255 = icmp eq i32 %r254, 1 + %r256 = and i1 %r252, %r255 + %r257 = sub i64 %r241, 6 + %r258 = inttoptr i64 %r257 to ptr + %r259 = load i16, ptr %r258 + %r260 = and i16 %r259, 2048 + %r261 = icmp eq i16 %r260, 0 + %r262 = and i1 %r256, %r261 + %r263 = add i64 %r241, 16 + %r264 = inttoptr i64 %r263 to ptr + %r265 = load i64, ptr %r264 + %r266 = add i64 %r241, 8 + %r267 = inttoptr i64 %r266 to ptr + %r268 = load i32, ptr %r267 + %r269 = add i32 %r268, -2147483648 + %r270 = icmp ult i32 %r269, 1073741824 + %r271 = zext i32 %r268 to i64 + %r272 = or i64 %r271, 4611686018427387904 + %r273 = select i1 %r270, i64 %r272, i64 %r265 + %r274 = getelementptr i64, ptr @perry_ic_12, i64 0 + %r275 = load i64, ptr %r274 + %r276 = icmp eq i64 %r273, %r275 + %r277 = icmp ne i64 %r273, 0 + %r278 = and i1 %r262, %r276 + %r279 = and i1 %r278, %r277 + br i1 %r279, label %pic.hit.44, label %pic.miss.45 + +pget.recv_bad.39: + %r296 = icmp eq i64 %r228, 9222246136947933185 + %r297 = icmp eq i64 %r228, 9222246136947933186 + %r298 = or i1 %r296, %r297 + br i1 %r298, label %pget.throw_nullish.48, label %pget.recv_undef_return.49 + +pget.recv_class_ref.40: + %r238 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612107, i64 %r228, i64 %r232) + br label %pget.recv_merge.41 + +pget.recv_merge.41: + %r302 = phi double [ %r295, %pic.merge.46 ], [ %r300, %pget.recv_undef_return.49 ], [ %r301, %pget.recv_sso.37 ], [ %r238, %pget.recv_class_ref.40 ] + %r303 = call double @js_dynamic_mod(double %r302, double 2.0) + %r304 = fcmp oeq double %r303, 0.0 + %r305 = select i1 %r304, i64 9222246136947933188, i64 9222246136947933187 + %r306 = bitcast i64 %r305 to double + %r307 = icmp eq i64 %r305, 9222246136947933188 + br i1 %r307, label %ternary.then.50, label %ternary.else.51 + +pget.check_ptr.42: + br i1 %r237, label %pget.recv_ok.38, label %pget.recv_bad.39 + +pget.check_class_ref.43: + br i1 %r235, label %pget.recv_class_ref.40, label %pget.check_ptr.42 + +pic.hit.44: + %r280 = getelementptr i64, ptr @perry_ic_12, i64 1 + %r281 = load i64, ptr %r280 + %r282 = add i64 %r241, 12 + %r283 = inttoptr i64 %r282 to ptr + %r284 = load i32, ptr %r283 + %r285 = zext i32 %r284 to i64 + %r286 = icmp ult i64 %r285, 4 + %r287 = select i1 %r286, i64 4, i64 %r285 + %r288 = icmp ult i64 %r281, %r287 + br i1 %r288, label %pic.hit.load.47, label %pic.miss.45 + +pic.miss.45: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612107) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612107) + %r294 = call double @js_object_get_field_ic_miss(i64 %r229, i64 %r232, ptr @perry_ic_12) + br label %pic.merge.46 + +pic.merge.46: + %r295 = phi double [ %r293, %pic.hit.load.47 ], [ %r294, %pic.miss.45 ] + br label %pget.recv_merge.41 + +pic.hit.load.47: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612107) + %r289 = shl i64 %r281, 3 + %r290 = add i64 %r229, 32 + %r291 = add i64 %r290, %r289 + %r292 = inttoptr i64 %r291 to ptr + %r293 = load double, ptr %r292 + br label %pic.merge.46 + +pget.throw_nullish.48: + %r299 = zext i1 %r297 to i32 + call void @js_throw_type_error_property_access(i32 %r299, ptr @batch_ts_.str.7.bytes, i64 2) + unreachable + +pget.recv_undef_return.49: + %r300 = call double @js_object_get_field_by_name_f64(i64 %r228, i64 %r232) + br label %pget.recv_merge.41 + +ternary.then.50: + %r308 = load double, ptr @batch_ts_.str.9.handle + br label %ternary.merge.52 + +ternary.else.51: + %r309 = load double, ptr @batch_ts_.str.10.handle + br label %ternary.merge.52 + +ternary.merge.52: + %r310 = phi double [ %r308, %ternary.then.50 ], [ %r309, %ternary.else.51 ] + %r311 = bitcast double %r310 to i64 + %r312 = call i32 @js_gc_temp_root_push(i64 %r311) + %r315 = load i64, ptr %r313 + %r316 = call i64 @js_object_alloc_class_inline_keys(i32 2, i32 0, i32 3, i64 %r315) + %r317 = call i32 @js_gc_temp_root_push(i64 %r316) + %r318 = or i64 %r316, 9222527611924643840 + %r319 = bitcast i64 %r318 to double + %r320 = call i64 @js_gc_temp_root_get(i32 %r169) + %r321 = bitcast i64 %r320 to double + %r322 = call i64 @js_gc_temp_root_get(i32 %r226) + %r323 = bitcast i64 %r322 to double + %r324 = call i64 @js_gc_temp_root_get(i32 %r312) + %r325 = bitcast i64 %r324 to double + %r326 = call double @batch_ts____AnonShape_e75d7e32e87dc826_constructor(double %r319, double %r321, double %r323, double %r325) + %r327 = call i64 @js_gc_temp_root_get(i32 %r317) + %r328 = or i64 %r327, 9222527611924643840 + %r329 = bitcast i64 %r328 to double + call void @js_gc_init_typed_shape_layout(i64 %r327, i32 3, ptr null, i32 0, ptr @perry_typed_shape_mask_batch_ts____AnonShape_e75d7e32e87dc826, i32 1) + %r330 = call double @js_ctor_return_override(double %r329, double %r326, i32 0) + call void @js_gc_temp_root_truncate(i32 %r8) + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r330 +} + +define double @perry_closure_batch_ts__9(i64 %this_closure, double %arg25, double %arg26) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 2) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %arg25, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = alloca double + store double %arg26, ptr %r8 + call void @js_shadow_slot_bind(i32 1, ptr %r8) + %r9 = load double, ptr %r7 + %r10 = bitcast double %r9 to i64 + %r11 = and i64 %r10, 281474976710655 + %r12 = load double, ptr @batch_ts_.str.11.handle + %r13 = bitcast double %r12 to i64 + %r14 = and i64 %r13, 281474976710655 + %r15 = lshr i64 %r10, 48 + %r16 = icmp eq i64 %r15, 32761 + %r17 = icmp eq i64 %r15, 32766 + %r18 = and i64 %r15, 65533 + %r19 = icmp eq i64 %r18, 32765 + br i1 %r16, label %pget.recv_sso.1, label %pget.check_class_ref.7 + +pget.recv_sso.1: + %r83 = call double @js_object_get_field_by_name_f64(i64 %r10, i64 %r14) + br label %pget.recv_merge.5 + +pget.recv_ok.2: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612109, i64 %r11, i64 %r14) + %r21 = icmp ugt i64 %r11, 1048575 + %r22 = ptrtoint ptr @perry_ic_14 to i64 + %r23 = select i1 %r21, i64 %r11, i64 %r22 + %r24 = sub i64 %r23, 8 + %r25 = inttoptr i64 %r24 to ptr + %r26 = load i8, ptr %r25 + %r27 = icmp eq i8 %r26, 2 + %r28 = and i1 %r21, %r27 + %r29 = add i64 %r23, 12 + %r30 = inttoptr i64 %r29 to ptr + %r31 = load i32, ptr %r30 + %r32 = icmp eq i32 %r31, 1129268819 + %r33 = xor i1 %r32, true + %r34 = and i1 %r28, %r33 + %r35 = inttoptr i64 %r23 to ptr + %r36 = load i32, ptr %r35 + %r37 = icmp eq i32 %r36, 1 + %r38 = and i1 %r34, %r37 + %r39 = sub i64 %r23, 6 + %r40 = inttoptr i64 %r39 to ptr + %r41 = load i16, ptr %r40 + %r42 = and i16 %r41, 2048 + %r43 = icmp eq i16 %r42, 0 + %r44 = and i1 %r38, %r43 + %r45 = add i64 %r23, 16 + %r46 = inttoptr i64 %r45 to ptr + %r47 = load i64, ptr %r46 + %r48 = add i64 %r23, 8 + %r49 = inttoptr i64 %r48 to ptr + %r50 = load i32, ptr %r49 + %r51 = add i32 %r50, -2147483648 + %r52 = icmp ult i32 %r51, 1073741824 + %r53 = zext i32 %r50 to i64 + %r54 = or i64 %r53, 4611686018427387904 + %r55 = select i1 %r52, i64 %r54, i64 %r47 + %r56 = getelementptr i64, ptr @perry_ic_14, i64 0 + %r57 = load i64, ptr %r56 + %r58 = icmp eq i64 %r55, %r57 + %r59 = icmp ne i64 %r55, 0 + %r60 = and i1 %r44, %r58 + %r61 = and i1 %r60, %r59 + br i1 %r61, label %pic.hit.8, label %pic.miss.9 + +pget.recv_bad.3: + %r78 = icmp eq i64 %r10, 9222246136947933185 + %r79 = icmp eq i64 %r10, 9222246136947933186 + %r80 = or i1 %r78, %r79 + br i1 %r80, label %pget.throw_nullish.12, label %pget.recv_undef_return.13 + +pget.recv_class_ref.4: + %r20 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612109, i64 %r10, i64 %r14) + br label %pget.recv_merge.5 + +pget.recv_merge.5: + %r84 = phi double [ %r77, %pic.merge.10 ], [ %r82, %pget.recv_undef_return.13 ], [ %r83, %pget.recv_sso.1 ], [ %r20, %pget.recv_class_ref.4 ] + %r85 = load double, ptr %r8 + %r86 = bitcast double %r85 to i64 + %r87 = and i64 %r86, 281474976710655 + %r88 = load double, ptr @batch_ts_.str.11.handle + %r89 = bitcast double %r88 to i64 + %r90 = and i64 %r89, 281474976710655 + %r91 = lshr i64 %r86, 48 + %r92 = icmp eq i64 %r91, 32761 + %r93 = icmp eq i64 %r91, 32766 + %r94 = and i64 %r91, 65533 + %r95 = icmp eq i64 %r94, 32765 + br i1 %r92, label %pget.recv_sso.14, label %pget.check_class_ref.20 + +pget.check_ptr.6: + br i1 %r19, label %pget.recv_ok.2, label %pget.recv_bad.3 + +pget.check_class_ref.7: + br i1 %r17, label %pget.recv_class_ref.4, label %pget.check_ptr.6 + +pic.hit.8: + %r62 = getelementptr i64, ptr @perry_ic_14, i64 1 + %r63 = load i64, ptr %r62 + %r64 = add i64 %r23, 12 + %r65 = inttoptr i64 %r64 to ptr + %r66 = load i32, ptr %r65 + %r67 = zext i32 %r66 to i64 + %r68 = icmp ult i64 %r67, 4 + %r69 = select i1 %r68, i64 4, i64 %r67 + %r70 = icmp ult i64 %r63, %r69 + br i1 %r70, label %pic.hit.load.11, label %pic.miss.9 + +pic.miss.9: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612109) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612109) + %r76 = call double @js_object_get_field_ic_miss(i64 %r11, i64 %r14, ptr @perry_ic_14) + br label %pic.merge.10 + +pic.merge.10: + %r77 = phi double [ %r75, %pic.hit.load.11 ], [ %r76, %pic.miss.9 ] + br label %pget.recv_merge.5 + +pic.hit.load.11: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612109) + %r71 = shl i64 %r63, 3 + %r72 = add i64 %r11, 32 + %r73 = add i64 %r72, %r71 + %r74 = inttoptr i64 %r73 to ptr + %r75 = load double, ptr %r74 + br label %pic.merge.10 + +pget.throw_nullish.12: + %r81 = zext i1 %r79 to i32 + call void @js_throw_type_error_property_access(i32 %r81, ptr @batch_ts_.str.11.bytes, i64 5) + unreachable + +pget.recv_undef_return.13: + %r82 = call double @js_object_get_field_by_name_f64(i64 %r10, i64 %r14) + br label %pget.recv_merge.5 + +pget.recv_sso.14: + %r159 = call double @js_object_get_field_by_name_f64(i64 %r86, i64 %r90) + br label %pget.recv_merge.18 + +pget.recv_ok.15: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612111, i64 %r87, i64 %r90) + %r97 = icmp ugt i64 %r87, 1048575 + %r98 = ptrtoint ptr @perry_ic_16 to i64 + %r99 = select i1 %r97, i64 %r87, i64 %r98 + %r100 = sub i64 %r99, 8 + %r101 = inttoptr i64 %r100 to ptr + %r102 = load i8, ptr %r101 + %r103 = icmp eq i8 %r102, 2 + %r104 = and i1 %r97, %r103 + %r105 = add i64 %r99, 12 + %r106 = inttoptr i64 %r105 to ptr + %r107 = load i32, ptr %r106 + %r108 = icmp eq i32 %r107, 1129268819 + %r109 = xor i1 %r108, true + %r110 = and i1 %r104, %r109 + %r111 = inttoptr i64 %r99 to ptr + %r112 = load i32, ptr %r111 + %r113 = icmp eq i32 %r112, 1 + %r114 = and i1 %r110, %r113 + %r115 = sub i64 %r99, 6 + %r116 = inttoptr i64 %r115 to ptr + %r117 = load i16, ptr %r116 + %r118 = and i16 %r117, 2048 + %r119 = icmp eq i16 %r118, 0 + %r120 = and i1 %r114, %r119 + %r121 = add i64 %r99, 16 + %r122 = inttoptr i64 %r121 to ptr + %r123 = load i64, ptr %r122 + %r124 = add i64 %r99, 8 + %r125 = inttoptr i64 %r124 to ptr + %r126 = load i32, ptr %r125 + %r127 = add i32 %r126, -2147483648 + %r128 = icmp ult i32 %r127, 1073741824 + %r129 = zext i32 %r126 to i64 + %r130 = or i64 %r129, 4611686018427387904 + %r131 = select i1 %r128, i64 %r130, i64 %r123 + %r132 = getelementptr i64, ptr @perry_ic_16, i64 0 + %r133 = load i64, ptr %r132 + %r134 = icmp eq i64 %r131, %r133 + %r135 = icmp ne i64 %r131, 0 + %r136 = and i1 %r120, %r134 + %r137 = and i1 %r136, %r135 + br i1 %r137, label %pic.hit.21, label %pic.miss.22 + +pget.recv_bad.16: + %r154 = icmp eq i64 %r86, 9222246136947933185 + %r155 = icmp eq i64 %r86, 9222246136947933186 + %r156 = or i1 %r154, %r155 + br i1 %r156, label %pget.throw_nullish.25, label %pget.recv_undef_return.26 + +pget.recv_class_ref.17: + %r96 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612111, i64 %r86, i64 %r90) + br label %pget.recv_merge.18 + +pget.recv_merge.18: + %r160 = phi double [ %r153, %pic.merge.23 ], [ %r158, %pget.recv_undef_return.26 ], [ %r159, %pget.recv_sso.14 ], [ %r96, %pget.recv_class_ref.17 ] + %r161 = bitcast double %r84 to i64 + %r162 = bitcast double %r160 to i64 + %r163 = call i64 @js_eq(i64 %r161, i64 %r162) + %r164 = bitcast i64 %r163 to double + %r165 = icmp eq i64 %r163, 9222246136947933188 + %r166 = xor i1 %r165, true + %r167 = select i1 %r166, i64 9222246136947933188, i64 9222246136947933187 + %r168 = bitcast i64 %r167 to double + %r169 = icmp eq i64 %r167, 9222246136947933188 + br i1 %r169, label %if.then.27, label %if.else.28 + +pget.check_ptr.19: + br i1 %r95, label %pget.recv_ok.15, label %pget.recv_bad.16 + +pget.check_class_ref.20: + br i1 %r93, label %pget.recv_class_ref.17, label %pget.check_ptr.19 + +pic.hit.21: + %r138 = getelementptr i64, ptr @perry_ic_16, i64 1 + %r139 = load i64, ptr %r138 + %r140 = add i64 %r99, 12 + %r141 = inttoptr i64 %r140 to ptr + %r142 = load i32, ptr %r141 + %r143 = zext i32 %r142 to i64 + %r144 = icmp ult i64 %r143, 4 + %r145 = select i1 %r144, i64 4, i64 %r143 + %r146 = icmp ult i64 %r139, %r145 + br i1 %r146, label %pic.hit.load.24, label %pic.miss.22 + +pic.miss.22: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612111) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612111) + %r152 = call double @js_object_get_field_ic_miss(i64 %r87, i64 %r90, ptr @perry_ic_16) + br label %pic.merge.23 + +pic.merge.23: + %r153 = phi double [ %r151, %pic.hit.load.24 ], [ %r152, %pic.miss.22 ] + br label %pget.recv_merge.18 + +pic.hit.load.24: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612111) + %r147 = shl i64 %r139, 3 + %r148 = add i64 %r87, 32 + %r149 = add i64 %r148, %r147 + %r150 = inttoptr i64 %r149 to ptr + %r151 = load double, ptr %r150 + br label %pic.merge.23 + +pget.throw_nullish.25: + %r157 = zext i1 %r155 to i32 + call void @js_throw_type_error_property_access(i32 %r157, ptr @batch_ts_.str.11.bytes, i64 5) + unreachable + +pget.recv_undef_return.26: + %r158 = call double @js_object_get_field_by_name_f64(i64 %r86, i64 %r90) + br label %pget.recv_merge.18 + +if.then.27: + %r170 = load double, ptr %r8 + %r171 = bitcast double %r170 to i64 + %r172 = and i64 %r171, 281474976710655 + %r173 = load double, ptr @batch_ts_.str.11.handle + %r174 = bitcast double %r173 to i64 + %r175 = and i64 %r174, 281474976710655 + %r176 = lshr i64 %r171, 48 + %r177 = icmp eq i64 %r176, 32761 + %r178 = icmp eq i64 %r176, 32766 + %r179 = and i64 %r176, 65533 + %r180 = icmp eq i64 %r179, 32765 + br i1 %r177, label %pget.recv_sso.30, label %pget.check_class_ref.36 + +if.else.28: + br label %if.merge.29 + +if.merge.29: + %r327 = load double, ptr %r7 + %r328 = bitcast double %r327 to i64 + %r329 = and i64 %r328, 281474976710655 + %r330 = load double, ptr @batch_ts_.str.12.handle + %r331 = bitcast double %r330 to i64 + %r332 = and i64 %r331, 281474976710655 + %r333 = lshr i64 %r328, 48 + %r334 = icmp eq i64 %r333, 32761 + %r335 = icmp eq i64 %r333, 32766 + %r336 = and i64 %r333, 65533 + %r337 = icmp eq i64 %r336, 32765 + br i1 %r334, label %pget.recv_sso.56, label %pget.check_class_ref.62 + +pget.recv_sso.30: + %r244 = call double @js_object_get_field_by_name_f64(i64 %r171, i64 %r175) + br label %pget.recv_merge.34 + +pget.recv_ok.31: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612113, i64 %r172, i64 %r175) + %r182 = icmp ugt i64 %r172, 1048575 + %r183 = ptrtoint ptr @perry_ic_18 to i64 + %r184 = select i1 %r182, i64 %r172, i64 %r183 + %r185 = sub i64 %r184, 8 + %r186 = inttoptr i64 %r185 to ptr + %r187 = load i8, ptr %r186 + %r188 = icmp eq i8 %r187, 2 + %r189 = and i1 %r182, %r188 + %r190 = add i64 %r184, 12 + %r191 = inttoptr i64 %r190 to ptr + %r192 = load i32, ptr %r191 + %r193 = icmp eq i32 %r192, 1129268819 + %r194 = xor i1 %r193, true + %r195 = and i1 %r189, %r194 + %r196 = inttoptr i64 %r184 to ptr + %r197 = load i32, ptr %r196 + %r198 = icmp eq i32 %r197, 1 + %r199 = and i1 %r195, %r198 + %r200 = sub i64 %r184, 6 + %r201 = inttoptr i64 %r200 to ptr + %r202 = load i16, ptr %r201 + %r203 = and i16 %r202, 2048 + %r204 = icmp eq i16 %r203, 0 + %r205 = and i1 %r199, %r204 + %r206 = add i64 %r184, 16 + %r207 = inttoptr i64 %r206 to ptr + %r208 = load i64, ptr %r207 + %r209 = add i64 %r184, 8 + %r210 = inttoptr i64 %r209 to ptr + %r211 = load i32, ptr %r210 + %r212 = add i32 %r211, -2147483648 + %r213 = icmp ult i32 %r212, 1073741824 + %r214 = zext i32 %r211 to i64 + %r215 = or i64 %r214, 4611686018427387904 + %r216 = select i1 %r213, i64 %r215, i64 %r208 + %r217 = getelementptr i64, ptr @perry_ic_18, i64 0 + %r218 = load i64, ptr %r217 + %r219 = icmp eq i64 %r216, %r218 + %r220 = icmp ne i64 %r216, 0 + %r221 = and i1 %r205, %r219 + %r222 = and i1 %r221, %r220 + br i1 %r222, label %pic.hit.37, label %pic.miss.38 + +pget.recv_bad.32: + %r239 = icmp eq i64 %r171, 9222246136947933185 + %r240 = icmp eq i64 %r171, 9222246136947933186 + %r241 = or i1 %r239, %r240 + br i1 %r241, label %pget.throw_nullish.41, label %pget.recv_undef_return.42 + +pget.recv_class_ref.33: + %r181 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612113, i64 %r171, i64 %r175) + br label %pget.recv_merge.34 + +pget.recv_merge.34: + %r245 = phi double [ %r238, %pic.merge.39 ], [ %r243, %pget.recv_undef_return.42 ], [ %r244, %pget.recv_sso.30 ], [ %r181, %pget.recv_class_ref.33 ] + %r246 = bitcast double %r245 to i64 + %r247 = call i32 @js_gc_temp_root_push(i64 %r246) + %r248 = load double, ptr %r7 + %r249 = bitcast double %r248 to i64 + %r250 = and i64 %r249, 281474976710655 + %r251 = load double, ptr @batch_ts_.str.11.handle + %r252 = bitcast double %r251 to i64 + %r253 = and i64 %r252, 281474976710655 + %r254 = lshr i64 %r249, 48 + %r255 = icmp eq i64 %r254, 32761 + %r256 = icmp eq i64 %r254, 32766 + %r257 = and i64 %r254, 65533 + %r258 = icmp eq i64 %r257, 32765 + br i1 %r255, label %pget.recv_sso.43, label %pget.check_class_ref.49 + +pget.check_ptr.35: + br i1 %r180, label %pget.recv_ok.31, label %pget.recv_bad.32 + +pget.check_class_ref.36: + br i1 %r178, label %pget.recv_class_ref.33, label %pget.check_ptr.35 + +pic.hit.37: + %r223 = getelementptr i64, ptr @perry_ic_18, i64 1 + %r224 = load i64, ptr %r223 + %r225 = add i64 %r184, 12 + %r226 = inttoptr i64 %r225 to ptr + %r227 = load i32, ptr %r226 + %r228 = zext i32 %r227 to i64 + %r229 = icmp ult i64 %r228, 4 + %r230 = select i1 %r229, i64 4, i64 %r228 + %r231 = icmp ult i64 %r224, %r230 + br i1 %r231, label %pic.hit.load.40, label %pic.miss.38 + +pic.miss.38: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612113) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612113) + %r237 = call double @js_object_get_field_ic_miss(i64 %r172, i64 %r175, ptr @perry_ic_18) + br label %pic.merge.39 + +pic.merge.39: + %r238 = phi double [ %r236, %pic.hit.load.40 ], [ %r237, %pic.miss.38 ] + br label %pget.recv_merge.34 + +pic.hit.load.40: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612113) + %r232 = shl i64 %r224, 3 + %r233 = add i64 %r172, 32 + %r234 = add i64 %r233, %r232 + %r235 = inttoptr i64 %r234 to ptr + %r236 = load double, ptr %r235 + br label %pic.merge.39 + +pget.throw_nullish.41: + %r242 = zext i1 %r240 to i32 + call void @js_throw_type_error_property_access(i32 %r242, ptr @batch_ts_.str.11.bytes, i64 5) + unreachable + +pget.recv_undef_return.42: + %r243 = call double @js_object_get_field_by_name_f64(i64 %r171, i64 %r175) + br label %pget.recv_merge.34 + +pget.recv_sso.43: + %r322 = call double @js_object_get_field_by_name_f64(i64 %r249, i64 %r253) + br label %pget.recv_merge.47 + +pget.recv_ok.44: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612115, i64 %r250, i64 %r253) + %r260 = icmp ugt i64 %r250, 1048575 + %r261 = ptrtoint ptr @perry_ic_20 to i64 + %r262 = select i1 %r260, i64 %r250, i64 %r261 + %r263 = sub i64 %r262, 8 + %r264 = inttoptr i64 %r263 to ptr + %r265 = load i8, ptr %r264 + %r266 = icmp eq i8 %r265, 2 + %r267 = and i1 %r260, %r266 + %r268 = add i64 %r262, 12 + %r269 = inttoptr i64 %r268 to ptr + %r270 = load i32, ptr %r269 + %r271 = icmp eq i32 %r270, 1129268819 + %r272 = xor i1 %r271, true + %r273 = and i1 %r267, %r272 + %r274 = inttoptr i64 %r262 to ptr + %r275 = load i32, ptr %r274 + %r276 = icmp eq i32 %r275, 1 + %r277 = and i1 %r273, %r276 + %r278 = sub i64 %r262, 6 + %r279 = inttoptr i64 %r278 to ptr + %r280 = load i16, ptr %r279 + %r281 = and i16 %r280, 2048 + %r282 = icmp eq i16 %r281, 0 + %r283 = and i1 %r277, %r282 + %r284 = add i64 %r262, 16 + %r285 = inttoptr i64 %r284 to ptr + %r286 = load i64, ptr %r285 + %r287 = add i64 %r262, 8 + %r288 = inttoptr i64 %r287 to ptr + %r289 = load i32, ptr %r288 + %r290 = add i32 %r289, -2147483648 + %r291 = icmp ult i32 %r290, 1073741824 + %r292 = zext i32 %r289 to i64 + %r293 = or i64 %r292, 4611686018427387904 + %r294 = select i1 %r291, i64 %r293, i64 %r286 + %r295 = getelementptr i64, ptr @perry_ic_20, i64 0 + %r296 = load i64, ptr %r295 + %r297 = icmp eq i64 %r294, %r296 + %r298 = icmp ne i64 %r294, 0 + %r299 = and i1 %r283, %r297 + %r300 = and i1 %r299, %r298 + br i1 %r300, label %pic.hit.50, label %pic.miss.51 + +pget.recv_bad.45: + %r317 = icmp eq i64 %r249, 9222246136947933185 + %r318 = icmp eq i64 %r249, 9222246136947933186 + %r319 = or i1 %r317, %r318 + br i1 %r319, label %pget.throw_nullish.54, label %pget.recv_undef_return.55 + +pget.recv_class_ref.46: + %r259 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612115, i64 %r249, i64 %r253) + br label %pget.recv_merge.47 + +pget.recv_merge.47: + %r323 = phi double [ %r316, %pic.merge.52 ], [ %r321, %pget.recv_undef_return.55 ], [ %r322, %pget.recv_sso.43 ], [ %r259, %pget.recv_class_ref.46 ] + %r324 = call i64 @js_gc_temp_root_get(i32 %r247) + %r325 = bitcast i64 %r324 to double + %r326 = call double @js_dynamic_sub(double %r325, double %r323) + call void @js_gc_temp_root_truncate(i32 %r247) + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r326 + +pget.check_ptr.48: + br i1 %r258, label %pget.recv_ok.44, label %pget.recv_bad.45 + +pget.check_class_ref.49: + br i1 %r256, label %pget.recv_class_ref.46, label %pget.check_ptr.48 + +pic.hit.50: + %r301 = getelementptr i64, ptr @perry_ic_20, i64 1 + %r302 = load i64, ptr %r301 + %r303 = add i64 %r262, 12 + %r304 = inttoptr i64 %r303 to ptr + %r305 = load i32, ptr %r304 + %r306 = zext i32 %r305 to i64 + %r307 = icmp ult i64 %r306, 4 + %r308 = select i1 %r307, i64 4, i64 %r306 + %r309 = icmp ult i64 %r302, %r308 + br i1 %r309, label %pic.hit.load.53, label %pic.miss.51 + +pic.miss.51: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612115) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612115) + %r315 = call double @js_object_get_field_ic_miss(i64 %r250, i64 %r253, ptr @perry_ic_20) + br label %pic.merge.52 + +pic.merge.52: + %r316 = phi double [ %r314, %pic.hit.load.53 ], [ %r315, %pic.miss.51 ] + br label %pget.recv_merge.47 + +pic.hit.load.53: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612115) + %r310 = shl i64 %r302, 3 + %r311 = add i64 %r250, 32 + %r312 = add i64 %r311, %r310 + %r313 = inttoptr i64 %r312 to ptr + %r314 = load double, ptr %r313 + br label %pic.merge.52 + +pget.throw_nullish.54: + %r320 = zext i1 %r318 to i32 + call void @js_throw_type_error_property_access(i32 %r320, ptr @batch_ts_.str.11.bytes, i64 5) + unreachable + +pget.recv_undef_return.55: + %r321 = call double @js_object_get_field_by_name_f64(i64 %r249, i64 %r253) + br label %pget.recv_merge.47 + +pget.recv_sso.56: + %r401 = call double @js_object_get_field_by_name_f64(i64 %r328, i64 %r332) + br label %pget.recv_merge.60 + +pget.recv_ok.57: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612117, i64 %r329, i64 %r332) + %r339 = icmp ugt i64 %r329, 1048575 + %r340 = ptrtoint ptr @perry_ic_22 to i64 + %r341 = select i1 %r339, i64 %r329, i64 %r340 + %r342 = sub i64 %r341, 8 + %r343 = inttoptr i64 %r342 to ptr + %r344 = load i8, ptr %r343 + %r345 = icmp eq i8 %r344, 2 + %r346 = and i1 %r339, %r345 + %r347 = add i64 %r341, 12 + %r348 = inttoptr i64 %r347 to ptr + %r349 = load i32, ptr %r348 + %r350 = icmp eq i32 %r349, 1129268819 + %r351 = xor i1 %r350, true + %r352 = and i1 %r346, %r351 + %r353 = inttoptr i64 %r341 to ptr + %r354 = load i32, ptr %r353 + %r355 = icmp eq i32 %r354, 1 + %r356 = and i1 %r352, %r355 + %r357 = sub i64 %r341, 6 + %r358 = inttoptr i64 %r357 to ptr + %r359 = load i16, ptr %r358 + %r360 = and i16 %r359, 2048 + %r361 = icmp eq i16 %r360, 0 + %r362 = and i1 %r356, %r361 + %r363 = add i64 %r341, 16 + %r364 = inttoptr i64 %r363 to ptr + %r365 = load i64, ptr %r364 + %r366 = add i64 %r341, 8 + %r367 = inttoptr i64 %r366 to ptr + %r368 = load i32, ptr %r367 + %r369 = add i32 %r368, -2147483648 + %r370 = icmp ult i32 %r369, 1073741824 + %r371 = zext i32 %r368 to i64 + %r372 = or i64 %r371, 4611686018427387904 + %r373 = select i1 %r370, i64 %r372, i64 %r365 + %r374 = getelementptr i64, ptr @perry_ic_22, i64 0 + %r375 = load i64, ptr %r374 + %r376 = icmp eq i64 %r373, %r375 + %r377 = icmp ne i64 %r373, 0 + %r378 = and i1 %r362, %r376 + %r379 = and i1 %r378, %r377 + br i1 %r379, label %pic.hit.63, label %pic.miss.64 + +pget.recv_bad.58: + %r396 = icmp eq i64 %r328, 9222246136947933185 + %r397 = icmp eq i64 %r328, 9222246136947933186 + %r398 = or i1 %r396, %r397 + br i1 %r398, label %pget.throw_nullish.67, label %pget.recv_undef_return.68 + +pget.recv_class_ref.59: + %r338 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612117, i64 %r328, i64 %r332) + br label %pget.recv_merge.60 + +pget.recv_merge.60: + %r402 = phi double [ %r395, %pic.merge.65 ], [ %r400, %pget.recv_undef_return.68 ], [ %r401, %pget.recv_sso.56 ], [ %r338, %pget.recv_class_ref.59 ] + %r403 = load double, ptr %r8 + %r404 = bitcast double %r403 to i64 + %r405 = and i64 %r404, 281474976710655 + %r406 = load double, ptr @batch_ts_.str.12.handle + %r407 = bitcast double %r406 to i64 + %r408 = and i64 %r407, 281474976710655 + %r409 = lshr i64 %r404, 48 + %r410 = icmp eq i64 %r409, 32761 + %r411 = icmp eq i64 %r409, 32766 + %r412 = and i64 %r409, 65533 + %r413 = icmp eq i64 %r412, 32765 + br i1 %r410, label %pget.recv_sso.69, label %pget.check_class_ref.75 + +pget.check_ptr.61: + br i1 %r337, label %pget.recv_ok.57, label %pget.recv_bad.58 + +pget.check_class_ref.62: + br i1 %r335, label %pget.recv_class_ref.59, label %pget.check_ptr.61 + +pic.hit.63: + %r380 = getelementptr i64, ptr @perry_ic_22, i64 1 + %r381 = load i64, ptr %r380 + %r382 = add i64 %r341, 12 + %r383 = inttoptr i64 %r382 to ptr + %r384 = load i32, ptr %r383 + %r385 = zext i32 %r384 to i64 + %r386 = icmp ult i64 %r385, 4 + %r387 = select i1 %r386, i64 4, i64 %r385 + %r388 = icmp ult i64 %r381, %r387 + br i1 %r388, label %pic.hit.load.66, label %pic.miss.64 + +pic.miss.64: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612117) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612117) + %r394 = call double @js_object_get_field_ic_miss(i64 %r329, i64 %r332, ptr @perry_ic_22) + br label %pic.merge.65 + +pic.merge.65: + %r395 = phi double [ %r393, %pic.hit.load.66 ], [ %r394, %pic.miss.64 ] + br label %pget.recv_merge.60 + +pic.hit.load.66: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612117) + %r389 = shl i64 %r381, 3 + %r390 = add i64 %r329, 32 + %r391 = add i64 %r390, %r389 + %r392 = inttoptr i64 %r391 to ptr + %r393 = load double, ptr %r392 + br label %pic.merge.65 + +pget.throw_nullish.67: + %r399 = zext i1 %r397 to i32 + call void @js_throw_type_error_property_access(i32 %r399, ptr @batch_ts_.str.12.bytes, i64 3) + unreachable + +pget.recv_undef_return.68: + %r400 = call double @js_object_get_field_by_name_f64(i64 %r328, i64 %r332) + br label %pget.recv_merge.60 + +pget.recv_sso.69: + %r477 = call double @js_object_get_field_by_name_f64(i64 %r404, i64 %r408) + br label %pget.recv_merge.73 + +pget.recv_ok.70: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612119, i64 %r405, i64 %r408) + %r415 = icmp ugt i64 %r405, 1048575 + %r416 = ptrtoint ptr @perry_ic_24 to i64 + %r417 = select i1 %r415, i64 %r405, i64 %r416 + %r418 = sub i64 %r417, 8 + %r419 = inttoptr i64 %r418 to ptr + %r420 = load i8, ptr %r419 + %r421 = icmp eq i8 %r420, 2 + %r422 = and i1 %r415, %r421 + %r423 = add i64 %r417, 12 + %r424 = inttoptr i64 %r423 to ptr + %r425 = load i32, ptr %r424 + %r426 = icmp eq i32 %r425, 1129268819 + %r427 = xor i1 %r426, true + %r428 = and i1 %r422, %r427 + %r429 = inttoptr i64 %r417 to ptr + %r430 = load i32, ptr %r429 + %r431 = icmp eq i32 %r430, 1 + %r432 = and i1 %r428, %r431 + %r433 = sub i64 %r417, 6 + %r434 = inttoptr i64 %r433 to ptr + %r435 = load i16, ptr %r434 + %r436 = and i16 %r435, 2048 + %r437 = icmp eq i16 %r436, 0 + %r438 = and i1 %r432, %r437 + %r439 = add i64 %r417, 16 + %r440 = inttoptr i64 %r439 to ptr + %r441 = load i64, ptr %r440 + %r442 = add i64 %r417, 8 + %r443 = inttoptr i64 %r442 to ptr + %r444 = load i32, ptr %r443 + %r445 = add i32 %r444, -2147483648 + %r446 = icmp ult i32 %r445, 1073741824 + %r447 = zext i32 %r444 to i64 + %r448 = or i64 %r447, 4611686018427387904 + %r449 = select i1 %r446, i64 %r448, i64 %r441 + %r450 = getelementptr i64, ptr @perry_ic_24, i64 0 + %r451 = load i64, ptr %r450 + %r452 = icmp eq i64 %r449, %r451 + %r453 = icmp ne i64 %r449, 0 + %r454 = and i1 %r438, %r452 + %r455 = and i1 %r454, %r453 + br i1 %r455, label %pic.hit.76, label %pic.miss.77 + +pget.recv_bad.71: + %r472 = icmp eq i64 %r404, 9222246136947933185 + %r473 = icmp eq i64 %r404, 9222246136947933186 + %r474 = or i1 %r472, %r473 + br i1 %r474, label %pget.throw_nullish.80, label %pget.recv_undef_return.81 + +pget.recv_class_ref.72: + %r414 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612119, i64 %r404, i64 %r408) + br label %pget.recv_merge.73 + +pget.recv_merge.73: + %r478 = phi double [ %r471, %pic.merge.78 ], [ %r476, %pget.recv_undef_return.81 ], [ %r477, %pget.recv_sso.69 ], [ %r414, %pget.recv_class_ref.72 ] + %r479 = call double @js_rel_lt(double %r402, double %r478) + %r480 = bitcast double %r479 to i64 + %r481 = icmp eq i64 %r480, 9222246136947933188 + br i1 %r481, label %ternary.then.82, label %ternary.else.83 + +pget.check_ptr.74: + br i1 %r413, label %pget.recv_ok.70, label %pget.recv_bad.71 + +pget.check_class_ref.75: + br i1 %r411, label %pget.recv_class_ref.72, label %pget.check_ptr.74 + +pic.hit.76: + %r456 = getelementptr i64, ptr @perry_ic_24, i64 1 + %r457 = load i64, ptr %r456 + %r458 = add i64 %r417, 12 + %r459 = inttoptr i64 %r458 to ptr + %r460 = load i32, ptr %r459 + %r461 = zext i32 %r460 to i64 + %r462 = icmp ult i64 %r461, 4 + %r463 = select i1 %r462, i64 4, i64 %r461 + %r464 = icmp ult i64 %r457, %r463 + br i1 %r464, label %pic.hit.load.79, label %pic.miss.77 + +pic.miss.77: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612119) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612119) + %r470 = call double @js_object_get_field_ic_miss(i64 %r405, i64 %r408, ptr @perry_ic_24) + br label %pic.merge.78 + +pic.merge.78: + %r471 = phi double [ %r469, %pic.hit.load.79 ], [ %r470, %pic.miss.77 ] + br label %pget.recv_merge.73 + +pic.hit.load.79: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612119) + %r465 = shl i64 %r457, 3 + %r466 = add i64 %r405, 32 + %r467 = add i64 %r466, %r465 + %r468 = inttoptr i64 %r467 to ptr + %r469 = load double, ptr %r468 + br label %pic.merge.78 + +pget.throw_nullish.80: + %r475 = zext i1 %r473 to i32 + call void @js_throw_type_error_property_access(i32 %r475, ptr @batch_ts_.str.12.bytes, i64 3) + unreachable + +pget.recv_undef_return.81: + %r476 = call double @js_object_get_field_by_name_f64(i64 %r404, i64 %r408) + br label %pget.recv_merge.73 + +ternary.then.82: + br label %ternary.merge.84 + +ternary.else.83: + %r482 = load double, ptr %r7 + %r483 = bitcast double %r482 to i64 + %r484 = and i64 %r483, 281474976710655 + %r485 = load double, ptr @batch_ts_.str.12.handle + %r486 = bitcast double %r485 to i64 + %r487 = and i64 %r486, 281474976710655 + %r488 = lshr i64 %r483, 48 + %r489 = icmp eq i64 %r488, 32761 + %r490 = icmp eq i64 %r488, 32766 + %r491 = and i64 %r488, 65533 + %r492 = icmp eq i64 %r491, 32765 + br i1 %r489, label %pget.recv_sso.85, label %pget.check_class_ref.91 + +ternary.merge.84: + %r638 = phi double [ -1.0, %ternary.then.82 ], [ %r637, %ternary.merge.113 ] + %shadow_pop_l_1 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_1) + ret double %r638 + +pget.recv_sso.85: + %r556 = call double @js_object_get_field_by_name_f64(i64 %r483, i64 %r487) + br label %pget.recv_merge.89 + +pget.recv_ok.86: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612121, i64 %r484, i64 %r487) + %r494 = icmp ugt i64 %r484, 1048575 + %r495 = ptrtoint ptr @perry_ic_26 to i64 + %r496 = select i1 %r494, i64 %r484, i64 %r495 + %r497 = sub i64 %r496, 8 + %r498 = inttoptr i64 %r497 to ptr + %r499 = load i8, ptr %r498 + %r500 = icmp eq i8 %r499, 2 + %r501 = and i1 %r494, %r500 + %r502 = add i64 %r496, 12 + %r503 = inttoptr i64 %r502 to ptr + %r504 = load i32, ptr %r503 + %r505 = icmp eq i32 %r504, 1129268819 + %r506 = xor i1 %r505, true + %r507 = and i1 %r501, %r506 + %r508 = inttoptr i64 %r496 to ptr + %r509 = load i32, ptr %r508 + %r510 = icmp eq i32 %r509, 1 + %r511 = and i1 %r507, %r510 + %r512 = sub i64 %r496, 6 + %r513 = inttoptr i64 %r512 to ptr + %r514 = load i16, ptr %r513 + %r515 = and i16 %r514, 2048 + %r516 = icmp eq i16 %r515, 0 + %r517 = and i1 %r511, %r516 + %r518 = add i64 %r496, 16 + %r519 = inttoptr i64 %r518 to ptr + %r520 = load i64, ptr %r519 + %r521 = add i64 %r496, 8 + %r522 = inttoptr i64 %r521 to ptr + %r523 = load i32, ptr %r522 + %r524 = add i32 %r523, -2147483648 + %r525 = icmp ult i32 %r524, 1073741824 + %r526 = zext i32 %r523 to i64 + %r527 = or i64 %r526, 4611686018427387904 + %r528 = select i1 %r525, i64 %r527, i64 %r520 + %r529 = getelementptr i64, ptr @perry_ic_26, i64 0 + %r530 = load i64, ptr %r529 + %r531 = icmp eq i64 %r528, %r530 + %r532 = icmp ne i64 %r528, 0 + %r533 = and i1 %r517, %r531 + %r534 = and i1 %r533, %r532 + br i1 %r534, label %pic.hit.92, label %pic.miss.93 + +pget.recv_bad.87: + %r551 = icmp eq i64 %r483, 9222246136947933185 + %r552 = icmp eq i64 %r483, 9222246136947933186 + %r553 = or i1 %r551, %r552 + br i1 %r553, label %pget.throw_nullish.96, label %pget.recv_undef_return.97 + +pget.recv_class_ref.88: + %r493 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612121, i64 %r483, i64 %r487) + br label %pget.recv_merge.89 + +pget.recv_merge.89: + %r557 = phi double [ %r550, %pic.merge.94 ], [ %r555, %pget.recv_undef_return.97 ], [ %r556, %pget.recv_sso.85 ], [ %r493, %pget.recv_class_ref.88 ] + %r558 = load double, ptr %r8 + %r559 = bitcast double %r558 to i64 + %r560 = and i64 %r559, 281474976710655 + %r561 = load double, ptr @batch_ts_.str.12.handle + %r562 = bitcast double %r561 to i64 + %r563 = and i64 %r562, 281474976710655 + %r564 = lshr i64 %r559, 48 + %r565 = icmp eq i64 %r564, 32761 + %r566 = icmp eq i64 %r564, 32766 + %r567 = and i64 %r564, 65533 + %r568 = icmp eq i64 %r567, 32765 + br i1 %r565, label %pget.recv_sso.98, label %pget.check_class_ref.104 + +pget.check_ptr.90: + br i1 %r492, label %pget.recv_ok.86, label %pget.recv_bad.87 + +pget.check_class_ref.91: + br i1 %r490, label %pget.recv_class_ref.88, label %pget.check_ptr.90 + +pic.hit.92: + %r535 = getelementptr i64, ptr @perry_ic_26, i64 1 + %r536 = load i64, ptr %r535 + %r537 = add i64 %r496, 12 + %r538 = inttoptr i64 %r537 to ptr + %r539 = load i32, ptr %r538 + %r540 = zext i32 %r539 to i64 + %r541 = icmp ult i64 %r540, 4 + %r542 = select i1 %r541, i64 4, i64 %r540 + %r543 = icmp ult i64 %r536, %r542 + br i1 %r543, label %pic.hit.load.95, label %pic.miss.93 + +pic.miss.93: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612121) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612121) + %r549 = call double @js_object_get_field_ic_miss(i64 %r484, i64 %r487, ptr @perry_ic_26) + br label %pic.merge.94 + +pic.merge.94: + %r550 = phi double [ %r548, %pic.hit.load.95 ], [ %r549, %pic.miss.93 ] + br label %pget.recv_merge.89 + +pic.hit.load.95: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612121) + %r544 = shl i64 %r536, 3 + %r545 = add i64 %r484, 32 + %r546 = add i64 %r545, %r544 + %r547 = inttoptr i64 %r546 to ptr + %r548 = load double, ptr %r547 + br label %pic.merge.94 + +pget.throw_nullish.96: + %r554 = zext i1 %r552 to i32 + call void @js_throw_type_error_property_access(i32 %r554, ptr @batch_ts_.str.12.bytes, i64 3) + unreachable + +pget.recv_undef_return.97: + %r555 = call double @js_object_get_field_by_name_f64(i64 %r483, i64 %r487) + br label %pget.recv_merge.89 + +pget.recv_sso.98: + %r632 = call double @js_object_get_field_by_name_f64(i64 %r559, i64 %r563) + br label %pget.recv_merge.102 + +pget.recv_ok.99: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612123, i64 %r560, i64 %r563) + %r570 = icmp ugt i64 %r560, 1048575 + %r571 = ptrtoint ptr @perry_ic_28 to i64 + %r572 = select i1 %r570, i64 %r560, i64 %r571 + %r573 = sub i64 %r572, 8 + %r574 = inttoptr i64 %r573 to ptr + %r575 = load i8, ptr %r574 + %r576 = icmp eq i8 %r575, 2 + %r577 = and i1 %r570, %r576 + %r578 = add i64 %r572, 12 + %r579 = inttoptr i64 %r578 to ptr + %r580 = load i32, ptr %r579 + %r581 = icmp eq i32 %r580, 1129268819 + %r582 = xor i1 %r581, true + %r583 = and i1 %r577, %r582 + %r584 = inttoptr i64 %r572 to ptr + %r585 = load i32, ptr %r584 + %r586 = icmp eq i32 %r585, 1 + %r587 = and i1 %r583, %r586 + %r588 = sub i64 %r572, 6 + %r589 = inttoptr i64 %r588 to ptr + %r590 = load i16, ptr %r589 + %r591 = and i16 %r590, 2048 + %r592 = icmp eq i16 %r591, 0 + %r593 = and i1 %r587, %r592 + %r594 = add i64 %r572, 16 + %r595 = inttoptr i64 %r594 to ptr + %r596 = load i64, ptr %r595 + %r597 = add i64 %r572, 8 + %r598 = inttoptr i64 %r597 to ptr + %r599 = load i32, ptr %r598 + %r600 = add i32 %r599, -2147483648 + %r601 = icmp ult i32 %r600, 1073741824 + %r602 = zext i32 %r599 to i64 + %r603 = or i64 %r602, 4611686018427387904 + %r604 = select i1 %r601, i64 %r603, i64 %r596 + %r605 = getelementptr i64, ptr @perry_ic_28, i64 0 + %r606 = load i64, ptr %r605 + %r607 = icmp eq i64 %r604, %r606 + %r608 = icmp ne i64 %r604, 0 + %r609 = and i1 %r593, %r607 + %r610 = and i1 %r609, %r608 + br i1 %r610, label %pic.hit.105, label %pic.miss.106 + +pget.recv_bad.100: + %r627 = icmp eq i64 %r559, 9222246136947933185 + %r628 = icmp eq i64 %r559, 9222246136947933186 + %r629 = or i1 %r627, %r628 + br i1 %r629, label %pget.throw_nullish.109, label %pget.recv_undef_return.110 + +pget.recv_class_ref.101: + %r569 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612123, i64 %r559, i64 %r563) + br label %pget.recv_merge.102 + +pget.recv_merge.102: + %r633 = phi double [ %r626, %pic.merge.107 ], [ %r631, %pget.recv_undef_return.110 ], [ %r632, %pget.recv_sso.98 ], [ %r569, %pget.recv_class_ref.101 ] + %r634 = call double @js_rel_gt(double %r557, double %r633) + %r635 = bitcast double %r634 to i64 + %r636 = icmp eq i64 %r635, 9222246136947933188 + br i1 %r636, label %ternary.then.111, label %ternary.else.112 + +pget.check_ptr.103: + br i1 %r568, label %pget.recv_ok.99, label %pget.recv_bad.100 + +pget.check_class_ref.104: + br i1 %r566, label %pget.recv_class_ref.101, label %pget.check_ptr.103 + +pic.hit.105: + %r611 = getelementptr i64, ptr @perry_ic_28, i64 1 + %r612 = load i64, ptr %r611 + %r613 = add i64 %r572, 12 + %r614 = inttoptr i64 %r613 to ptr + %r615 = load i32, ptr %r614 + %r616 = zext i32 %r615 to i64 + %r617 = icmp ult i64 %r616, 4 + %r618 = select i1 %r617, i64 4, i64 %r616 + %r619 = icmp ult i64 %r612, %r618 + br i1 %r619, label %pic.hit.load.108, label %pic.miss.106 + +pic.miss.106: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612123) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612123) + %r625 = call double @js_object_get_field_ic_miss(i64 %r560, i64 %r563, ptr @perry_ic_28) + br label %pic.merge.107 + +pic.merge.107: + %r626 = phi double [ %r624, %pic.hit.load.108 ], [ %r625, %pic.miss.106 ] + br label %pget.recv_merge.102 + +pic.hit.load.108: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612123) + %r620 = shl i64 %r612, 3 + %r621 = add i64 %r560, 32 + %r622 = add i64 %r621, %r620 + %r623 = inttoptr i64 %r622 to ptr + %r624 = load double, ptr %r623 + br label %pic.merge.107 + +pget.throw_nullish.109: + %r630 = zext i1 %r628 to i32 + call void @js_throw_type_error_property_access(i32 %r630, ptr @batch_ts_.str.12.bytes, i64 3) + unreachable + +pget.recv_undef_return.110: + %r631 = call double @js_object_get_field_by_name_f64(i64 %r559, i64 %r563) + br label %pget.recv_merge.102 + +ternary.then.111: + br label %ternary.merge.113 + +ternary.else.112: + br label %ternary.merge.113 + +ternary.merge.113: + %r637 = phi double [ 1.0, %ternary.then.111 ], [ 0.0, %ternary.else.112 ] + br label %ternary.merge.84 +} + +define double @perry_closure_batch_ts__11(i64 %this_closure, double %arg35, double %arg36) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 3) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r9 = alloca double + store double 0x7FFC000000000001, ptr %r9 + %r66 = alloca double + store double 0x7FFC000000000001, ptr %r66 + call void @js_shadow_slot_bind(i32 2, ptr %r66) + %r7 = alloca double + store double %arg35, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = alloca double + store double %arg36, ptr %r8 + call void @js_shadow_slot_bind(i32 1, ptr %r8) + %r10 = load double, ptr @perry_global_batch_ts__1 + %r11 = load double, ptr %r8 + %r12 = bitcast double %r11 to i64 + %r13 = and i64 %r12, 281474976710655 + %r14 = load double, ptr @batch_ts_.str.5.handle + %r15 = bitcast double %r14 to i64 + %r16 = and i64 %r15, 281474976710655 + %r17 = load i64, ptr @perry_class_keys_batch_ts__Row + %r18 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r19 = icmp eq i8 %r18, 0 + %r20 = lshr i64 %r12, 48 + %r21 = icmp eq i64 %r20, 32765 + %r22 = icmp ugt i64 %r13, 1048575 + %r23 = and i1 %r21, %r22 + %r24 = and i1 %r23, %r19 + br i1 %r24, label %class_field_inline.deref.4, label %class_field_inline.guardcall.5 + +class_field_get.fast.1: + %r56 = inttoptr i64 %r13 to ptr + %r57 = getelementptr i8, ptr %r56, i64 32 + %r58 = getelementptr double, ptr %r57, i64 1 + %r59 = load double, ptr %r58 + br label %class_field_get.merge.3 + +class_field_get.fallback.2: + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612125) + %r60 = call double @js_object_get_field_by_name_f64(i64 %r12, i64 %r16) + br label %class_field_get.merge.3 + +class_field_get.merge.3: + %r61 = phi double [ %r59, %class_field_get.fast.1 ], [ %r60, %class_field_get.fallback.2 ] + %r62 = bitcast double %r10 to i64 + %r63 = and i64 %r62, 281474976710655 + %r64 = call i64 @js_array_indexOf_jsvalue(i64 %r63, double %r61, double %r61, i32 0) + %r65 = sitofp i64 %r64 to double + store double %r65, ptr %r9 + %r67 = load double, ptr %r7 + %r68 = load double, ptr %r9 + %r69 = bitcast double %r67 to i64 + %r70 = and i64 %r69, 281474976710655 + %r71 = call double @js_array_get_index_or_string(i64 %r70, double %r68) + store double %r71, ptr %r66 + %r72 = bitcast double %r71 to i64 + %r73 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r74 = icmp ne i32 %r73, 0 + br i1 %r74, label %shadow.root.barrier.6, label %shadow.root.barrier.done.7 + +class_field_inline.deref.4: + %r25 = inttoptr i64 %r13 to ptr + %r26 = getelementptr i8, ptr %r25, i64 -8 + %r27 = load i8, ptr %r26 + %r28 = icmp eq i8 %r27, 2 + %r29 = getelementptr i8, ptr %r25, i64 -7 + %r30 = load i8, ptr %r29 + %r31 = and i8 %r30, -128 + %r32 = icmp eq i8 %r31, 0 + %r33 = getelementptr i8, ptr %r25, i64 -6 + %r34 = load i16, ptr %r33 + %r35 = load i32, ptr %r25 + %r36 = icmp eq i32 %r35, 1 + %r37 = getelementptr i8, ptr %r25, i64 4 + %r38 = load i32, ptr %r37 + %r39 = icmp eq i32 %r38, 1 + %r40 = getelementptr i8, ptr %r25, i64 12 + %r41 = load i32, ptr %r40 + %r42 = icmp ugt i32 %r41, 1 + %r43 = getelementptr i8, ptr %r25, i64 16 + %r44 = load i64, ptr %r43 + %r45 = icmp eq i64 %r44, %r17 + %r46 = and i1 %r28, %r32 + %r47 = and i1 %r46, %r36 + %r48 = and i1 %r47, %r39 + %r49 = and i1 %r48, %r42 + %r50 = and i1 %r49, %r45 + %r51 = and i16 %r34, 2048 + %r52 = icmp eq i16 %r51, 0 + %r53 = and i1 %r50, %r52 + br i1 %r53, label %class_field_get.fast.1, label %class_field_inline.guardcall.5 + +class_field_inline.guardcall.5: + %r54 = call i32 @js_typed_feedback_class_field_get_guard(i64 8450987250308612125, double %r11, i32 1, i64 %r17, i64 %r16, i32 1, i32 0) + %r55 = icmp ne i32 %r54, 0 + br i1 %r55, label %class_field_get.fast.1, label %class_field_get.fallback.2 + +shadow.root.barrier.6: + call void @js_write_barrier_root_nanbox(i64 %r72) + br label %shadow.root.barrier.done.7 + +shadow.root.barrier.done.7: + %r75 = load double, ptr @batch_ts_.str.13.handle + %r76 = load double, ptr %r66 + %r77 = bitcast double %r76 to i64 + %r78 = and i64 %r77, 281474976710655 + %r79 = load double, ptr @batch_ts_.str.13.handle + %r80 = bitcast double %r79 to i64 + %r81 = and i64 %r80, 281474976710655 + %r82 = lshr i64 %r77, 48 + %r83 = icmp eq i64 %r82, 32761 + %r84 = icmp eq i64 %r82, 32766 + %r85 = and i64 %r82, 65533 + %r86 = icmp eq i64 %r85, 32765 + br i1 %r83, label %pget.recv_sso.8, label %pget.check_class_ref.14 + +pget.recv_sso.8: + %r150 = call double @js_object_get_field_by_name_f64(i64 %r77, i64 %r81) + br label %pget.recv_merge.12 + +pget.recv_ok.9: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612126, i64 %r78, i64 %r81) + %r88 = icmp ugt i64 %r78, 1048575 + %r89 = ptrtoint ptr @perry_ic_31 to i64 + %r90 = select i1 %r88, i64 %r78, i64 %r89 + %r91 = sub i64 %r90, 8 + %r92 = inttoptr i64 %r91 to ptr + %r93 = load i8, ptr %r92 + %r94 = icmp eq i8 %r93, 2 + %r95 = and i1 %r88, %r94 + %r96 = add i64 %r90, 12 + %r97 = inttoptr i64 %r96 to ptr + %r98 = load i32, ptr %r97 + %r99 = icmp eq i32 %r98, 1129268819 + %r100 = xor i1 %r99, true + %r101 = and i1 %r95, %r100 + %r102 = inttoptr i64 %r90 to ptr + %r103 = load i32, ptr %r102 + %r104 = icmp eq i32 %r103, 1 + %r105 = and i1 %r101, %r104 + %r106 = sub i64 %r90, 6 + %r107 = inttoptr i64 %r106 to ptr + %r108 = load i16, ptr %r107 + %r109 = and i16 %r108, 2048 + %r110 = icmp eq i16 %r109, 0 + %r111 = and i1 %r105, %r110 + %r112 = add i64 %r90, 16 + %r113 = inttoptr i64 %r112 to ptr + %r114 = load i64, ptr %r113 + %r115 = add i64 %r90, 8 + %r116 = inttoptr i64 %r115 to ptr + %r117 = load i32, ptr %r116 + %r118 = add i32 %r117, -2147483648 + %r119 = icmp ult i32 %r118, 1073741824 + %r120 = zext i32 %r117 to i64 + %r121 = or i64 %r120, 4611686018427387904 + %r122 = select i1 %r119, i64 %r121, i64 %r114 + %r123 = getelementptr i64, ptr @perry_ic_31, i64 0 + %r124 = load i64, ptr %r123 + %r125 = icmp eq i64 %r122, %r124 + %r126 = icmp ne i64 %r122, 0 + %r127 = and i1 %r111, %r125 + %r128 = and i1 %r127, %r126 + br i1 %r128, label %pic.hit.15, label %pic.miss.16 + +pget.recv_bad.10: + %r145 = icmp eq i64 %r77, 9222246136947933185 + %r146 = icmp eq i64 %r77, 9222246136947933186 + %r147 = or i1 %r145, %r146 + br i1 %r147, label %pget.throw_nullish.19, label %pget.recv_undef_return.20 + +pget.recv_class_ref.11: + %r87 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612126, i64 %r77, i64 %r81) + br label %pget.recv_merge.12 + +pget.recv_merge.12: + %r151 = phi double [ %r144, %pic.merge.17 ], [ %r149, %pget.recv_undef_return.20 ], [ %r150, %pget.recv_sso.8 ], [ %r87, %pget.recv_class_ref.11 ] + %r152 = call double @js_dynamic_string_or_number_add(double %r151, double 1.0) + %r153 = load double, ptr @batch_ts_.str.13.handle + %r154 = load double, ptr %r66 + %r155 = bitcast double %r153 to i64 + %r156 = bitcast double %r152 to i64 + %r157 = bitcast double %r154 to i64 + %r158 = and i64 %r157, 281474976710655 + %r159 = lshr i64 %r157, 48 + %r160 = icmp eq i64 %r159, 32765 + %r161 = icmp ugt i64 %r158, 1048575 + %r162 = lshr i64 %r156, 48 + %r163 = icmp ne i64 %r162, 32765 + %r164 = icmp ne i64 %r162, 32767 + %r165 = icmp ne i64 %r162, 32762 + %r166 = icmp ne i64 %r155, 0 + %r167 = and i1 %r160, %r161 + %r168 = and i1 %r167, %r163 + %r169 = and i1 %r168, %r164 + %r170 = and i1 %r169, %r165 + %r171 = and i1 %r170, %r166 + br i1 %r171, label %put.dynic.guard.21, label %put.dynic.slow.27 + +pget.check_ptr.13: + br i1 %r86, label %pget.recv_ok.9, label %pget.recv_bad.10 + +pget.check_class_ref.14: + br i1 %r84, label %pget.recv_class_ref.11, label %pget.check_ptr.13 + +pic.hit.15: + %r129 = getelementptr i64, ptr @perry_ic_31, i64 1 + %r130 = load i64, ptr %r129 + %r131 = add i64 %r90, 12 + %r132 = inttoptr i64 %r131 to ptr + %r133 = load i32, ptr %r132 + %r134 = zext i32 %r133 to i64 + %r135 = icmp ult i64 %r134, 4 + %r136 = select i1 %r135, i64 4, i64 %r134 + %r137 = icmp ult i64 %r130, %r136 + br i1 %r137, label %pic.hit.load.18, label %pic.miss.16 + +pic.miss.16: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612126) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612126) + %r143 = call double @js_object_get_field_ic_miss(i64 %r78, i64 %r81, ptr @perry_ic_31) + br label %pic.merge.17 + +pic.merge.17: + %r144 = phi double [ %r142, %pic.hit.load.18 ], [ %r143, %pic.miss.16 ] + br label %pget.recv_merge.12 + +pic.hit.load.18: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612126) + %r138 = shl i64 %r130, 3 + %r139 = add i64 %r78, 32 + %r140 = add i64 %r139, %r138 + %r141 = inttoptr i64 %r140 to ptr + %r142 = load double, ptr %r141 + br label %pic.merge.17 + +pget.throw_nullish.19: + %r148 = zext i1 %r146 to i32 + call void @js_throw_type_error_property_access(i32 %r148, ptr @batch_ts_.str.13.bytes, i64 5) + unreachable + +pget.recv_undef_return.20: + %r149 = call double @js_object_get_field_by_name_f64(i64 %r77, i64 %r81) + br label %pget.recv_merge.12 + +put.dynic.guard.21: + %r172 = sub i64 %r158, 8 + %r173 = inttoptr i64 %r172 to ptr + %r174 = load i8, ptr %r173 + %r175 = icmp eq i8 %r174, 2 + %r176 = sub i64 %r158, 7 + %r177 = inttoptr i64 %r176 to ptr + %r178 = load i8, ptr %r177 + %r179 = and i8 %r178, 128 + %r180 = icmp eq i8 %r179, 0 + %r181 = sub i64 %r158, 6 + %r182 = inttoptr i64 %r181 to ptr + %r183 = load i16, ptr %r182 + %r184 = and i16 %r183, 6407 + %r185 = icmp eq i16 %r184, 0 + %r186 = inttoptr i64 %r158 to ptr + %r187 = load i32, ptr %r186 + %r188 = icmp eq i32 %r187, 1 + %r189 = add i64 %r158, 4 + %r190 = inttoptr i64 %r189 to ptr + %r191 = load i32, ptr %r190 + %r192 = icmp ne i32 %r191, 0 + %r193 = icmp ne i32 %r191, -2 + %r194 = add i64 %r158, 16 + %r195 = inttoptr i64 %r194 to ptr + %r196 = load i64, ptr %r195 + %r197 = add i64 %r158, 8 + %r198 = inttoptr i64 %r197 to ptr + %r199 = load i32, ptr %r198 + %r200 = add i32 %r199, -2147483648 + %r201 = icmp ult i32 %r200, 1073741824 + %r202 = zext i32 %r199 to i64 + %r203 = or i64 %r202, 4611686018427387904 + %r204 = select i1 %r201, i64 %r203, i64 %r196 + %r205 = getelementptr i64, ptr @perry_ic_32, i64 0 + %r206 = load i64, ptr %r205 + %r207 = icmp eq i64 %r204, %r206 + %r208 = icmp ne i64 %r204, 0 + %r209 = and i1 %r175, %r180 + %r210 = and i1 %r209, %r185 + %r211 = and i1 %r210, %r188 + %r212 = and i1 %r211, %r192 + %r213 = and i1 %r212, %r193 + %r214 = and i1 %r213, %r207 + %r215 = and i1 %r214, %r208 + br i1 %r215, label %put.dynic.ways.22, label %put.dynic.slow.27 + +put.dynic.ways.22: + %r216 = getelementptr i64, ptr @perry_ic_32, i64 1 + %r217 = load i64, ptr %r216 + %r218 = getelementptr i64, ptr @perry_ic_32, i64 2 + %r219 = load i64, ptr %r218 + %r220 = icmp eq i64 %r155, %r217 + br i1 %r220, label %put.dynic.bounds.25, label %put.dynic.way1.23 + +put.dynic.way1.23: + %r221 = getelementptr i64, ptr @perry_ic_32, i64 3 + %r222 = load i64, ptr %r221 + %r223 = getelementptr i64, ptr @perry_ic_32, i64 4 + %r224 = load i64, ptr %r223 + %r225 = icmp eq i64 %r155, %r222 + br i1 %r225, label %put.dynic.bounds.25, label %put.dynic.way2.24 + +put.dynic.way2.24: + %r226 = getelementptr i64, ptr @perry_ic_32, i64 5 + %r227 = load i64, ptr %r226 + %r228 = getelementptr i64, ptr @perry_ic_32, i64 6 + %r229 = load i64, ptr %r228 + %r230 = icmp eq i64 %r155, %r227 + br i1 %r230, label %put.dynic.bounds.25, label %put.dynic.slow.27 + +put.dynic.bounds.25: + %r231 = phi i64 [ %r219, %put.dynic.ways.22 ], [ %r224, %put.dynic.way1.23 ], [ %r229, %put.dynic.way2.24 ] + %r232 = add i64 %r158, 12 + %r233 = inttoptr i64 %r232 to ptr + %r234 = load i32, ptr %r233 + %r235 = zext i32 %r234 to i64 + %r236 = icmp ult i64 %r235, 4 + %r237 = select i1 %r236, i64 4, i64 %r235 + %r238 = icmp ult i64 %r231, %r237 + br i1 %r238, label %put.dynic.store.26, label %put.dynic.slow.27 + +put.dynic.store.26: + %r239 = add i64 %r231, 4 + %r240 = inttoptr i64 %r158 to ptr + %r241 = getelementptr inbounds i64, ptr %r240, i64 %r239 + store double %r152, ptr %r241 + br label %put.dynic.merge.28 + +put.dynic.slow.27: + %r242 = call double @js_put_value_set_dyn_ic(ptr @perry_ic_32, double %r154, double %r153, double %r152, i32 1) + br label %put.dynic.merge.28 + +put.dynic.merge.28: + %r243 = phi double [ %r152, %put.dynic.store.26 ], [ %r242, %put.dynic.slow.27 ] + %r244 = load double, ptr @batch_ts_.str.1.handle + %r245 = load double, ptr %r66 + %r246 = bitcast double %r245 to i64 + %r247 = and i64 %r246, 281474976710655 + %r248 = load double, ptr @batch_ts_.str.1.handle + %r249 = bitcast double %r248 to i64 + %r250 = and i64 %r249, 281474976710655 + %r251 = lshr i64 %r246, 48 + %r252 = icmp eq i64 %r251, 32761 + %r253 = icmp eq i64 %r251, 32766 + %r254 = and i64 %r251, 65533 + %r255 = icmp eq i64 %r254, 32765 + br i1 %r252, label %pget.recv_sso.29, label %pget.check_class_ref.35 + +pget.recv_sso.29: + %r319 = call double @js_object_get_field_by_name_f64(i64 %r246, i64 %r250) + br label %pget.recv_merge.33 + +pget.recv_ok.30: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612129, i64 %r247, i64 %r250) + %r257 = icmp ugt i64 %r247, 1048575 + %r258 = ptrtoint ptr @perry_ic_34 to i64 + %r259 = select i1 %r257, i64 %r247, i64 %r258 + %r260 = sub i64 %r259, 8 + %r261 = inttoptr i64 %r260 to ptr + %r262 = load i8, ptr %r261 + %r263 = icmp eq i8 %r262, 2 + %r264 = and i1 %r257, %r263 + %r265 = add i64 %r259, 12 + %r266 = inttoptr i64 %r265 to ptr + %r267 = load i32, ptr %r266 + %r268 = icmp eq i32 %r267, 1129268819 + %r269 = xor i1 %r268, true + %r270 = and i1 %r264, %r269 + %r271 = inttoptr i64 %r259 to ptr + %r272 = load i32, ptr %r271 + %r273 = icmp eq i32 %r272, 1 + %r274 = and i1 %r270, %r273 + %r275 = sub i64 %r259, 6 + %r276 = inttoptr i64 %r275 to ptr + %r277 = load i16, ptr %r276 + %r278 = and i16 %r277, 2048 + %r279 = icmp eq i16 %r278, 0 + %r280 = and i1 %r274, %r279 + %r281 = add i64 %r259, 16 + %r282 = inttoptr i64 %r281 to ptr + %r283 = load i64, ptr %r282 + %r284 = add i64 %r259, 8 + %r285 = inttoptr i64 %r284 to ptr + %r286 = load i32, ptr %r285 + %r287 = add i32 %r286, -2147483648 + %r288 = icmp ult i32 %r287, 1073741824 + %r289 = zext i32 %r286 to i64 + %r290 = or i64 %r289, 4611686018427387904 + %r291 = select i1 %r288, i64 %r290, i64 %r283 + %r292 = getelementptr i64, ptr @perry_ic_34, i64 0 + %r293 = load i64, ptr %r292 + %r294 = icmp eq i64 %r291, %r293 + %r295 = icmp ne i64 %r291, 0 + %r296 = and i1 %r280, %r294 + %r297 = and i1 %r296, %r295 + br i1 %r297, label %pic.hit.36, label %pic.miss.37 + +pget.recv_bad.31: + %r314 = icmp eq i64 %r246, 9222246136947933185 + %r315 = icmp eq i64 %r246, 9222246136947933186 + %r316 = or i1 %r314, %r315 + br i1 %r316, label %pget.throw_nullish.40, label %pget.recv_undef_return.41 + +pget.recv_class_ref.32: + %r256 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612129, i64 %r246, i64 %r250) + br label %pget.recv_merge.33 + +pget.recv_merge.33: + %r320 = phi double [ %r313, %pic.merge.38 ], [ %r318, %pget.recv_undef_return.41 ], [ %r319, %pget.recv_sso.29 ], [ %r256, %pget.recv_class_ref.32 ] + %r321 = bitcast double %r320 to i64 + %r322 = call i32 @js_gc_temp_root_push(i64 %r321) + %r323 = load double, ptr %r8 + %r324 = bitcast double %r323 to i64 + %r325 = and i64 %r324, 281474976710655 + %r326 = load double, ptr @batch_ts_.str.4.handle + %r327 = bitcast double %r326 to i64 + %r328 = and i64 %r327, 281474976710655 + %r329 = load i64, ptr @perry_class_keys_batch_ts__Row + %r330 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r331 = icmp eq i8 %r330, 0 + %r332 = lshr i64 %r324, 48 + %r333 = icmp eq i64 %r332, 32765 + %r334 = icmp ugt i64 %r325, 1048575 + %r335 = and i1 %r333, %r334 + %r336 = and i1 %r335, %r331 + br i1 %r336, label %class_field_inline.deref.45, label %class_field_inline.guardcall.46 + +pget.check_ptr.34: + br i1 %r255, label %pget.recv_ok.30, label %pget.recv_bad.31 + +pget.check_class_ref.35: + br i1 %r253, label %pget.recv_class_ref.32, label %pget.check_ptr.34 + +pic.hit.36: + %r298 = getelementptr i64, ptr @perry_ic_34, i64 1 + %r299 = load i64, ptr %r298 + %r300 = add i64 %r259, 12 + %r301 = inttoptr i64 %r300 to ptr + %r302 = load i32, ptr %r301 + %r303 = zext i32 %r302 to i64 + %r304 = icmp ult i64 %r303, 4 + %r305 = select i1 %r304, i64 4, i64 %r303 + %r306 = icmp ult i64 %r299, %r305 + br i1 %r306, label %pic.hit.load.39, label %pic.miss.37 + +pic.miss.37: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612129) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612129) + %r312 = call double @js_object_get_field_ic_miss(i64 %r247, i64 %r250, ptr @perry_ic_34) + br label %pic.merge.38 + +pic.merge.38: + %r313 = phi double [ %r311, %pic.hit.load.39 ], [ %r312, %pic.miss.37 ] + br label %pget.recv_merge.33 + +pic.hit.load.39: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612129) + %r307 = shl i64 %r299, 3 + %r308 = add i64 %r247, 32 + %r309 = add i64 %r308, %r307 + %r310 = inttoptr i64 %r309 to ptr + %r311 = load double, ptr %r310 + br label %pic.merge.38 + +pget.throw_nullish.40: + %r317 = zext i1 %r315 to i32 + call void @js_throw_type_error_property_access(i32 %r317, ptr @batch_ts_.str.1.bytes, i64 5) + unreachable + +pget.recv_undef_return.41: + %r318 = call double @js_object_get_field_by_name_f64(i64 %r246, i64 %r250) + br label %pget.recv_merge.33 + +class_field_get.fast.42: + %r371 = inttoptr i64 %r325 to ptr + %r372 = getelementptr i8, ptr %r371, i64 32 + %r373 = getelementptr double, ptr %r372, i64 3 + %r374 = load double, ptr %r373 + br label %class_field_get.merge.44 + +class_field_get.fallback.43: + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612131) + %r375 = call double @js_object_get_field_by_name_f64(i64 %r324, i64 %r328) + br label %class_field_get.merge.44 + +class_field_get.merge.44: + %r376 = phi double [ %r374, %class_field_get.fast.42 ], [ %r375, %class_field_get.fallback.43 ] + %r377 = call i64 @js_gc_temp_root_get(i32 %r322) + %r378 = bitcast i64 %r377 to double + %r379 = call double @js_dynamic_string_or_number_add(double %r378, double %r376) + call void @js_gc_temp_root_truncate(i32 %r322) + %r380 = load double, ptr @batch_ts_.str.1.handle + %r381 = load double, ptr %r66 + %r382 = bitcast double %r380 to i64 + %r383 = bitcast double %r379 to i64 + %r384 = bitcast double %r381 to i64 + %r385 = and i64 %r384, 281474976710655 + %r386 = lshr i64 %r384, 48 + %r387 = icmp eq i64 %r386, 32765 + %r388 = icmp ugt i64 %r385, 1048575 + %r389 = lshr i64 %r383, 48 + %r390 = icmp ne i64 %r389, 32765 + %r391 = icmp ne i64 %r389, 32767 + %r392 = icmp ne i64 %r389, 32762 + %r393 = icmp ne i64 %r382, 0 + %r394 = and i1 %r387, %r388 + %r395 = and i1 %r394, %r390 + %r396 = and i1 %r395, %r391 + %r397 = and i1 %r396, %r392 + %r398 = and i1 %r397, %r393 + br i1 %r398, label %put.dynic.guard.47, label %put.dynic.slow.53 + +class_field_inline.deref.45: + %r337 = inttoptr i64 %r325 to ptr + %r338 = getelementptr i8, ptr %r337, i64 -8 + %r339 = load i8, ptr %r338 + %r340 = icmp eq i8 %r339, 2 + %r341 = getelementptr i8, ptr %r337, i64 -7 + %r342 = load i8, ptr %r341 + %r343 = and i8 %r342, -128 + %r344 = icmp eq i8 %r343, 0 + %r345 = getelementptr i8, ptr %r337, i64 -6 + %r346 = load i16, ptr %r345 + %r347 = load i32, ptr %r337 + %r348 = icmp eq i32 %r347, 1 + %r349 = getelementptr i8, ptr %r337, i64 4 + %r350 = load i32, ptr %r349 + %r351 = icmp eq i32 %r350, 1 + %r352 = getelementptr i8, ptr %r337, i64 12 + %r353 = load i32, ptr %r352 + %r354 = icmp ugt i32 %r353, 3 + %r355 = getelementptr i8, ptr %r337, i64 16 + %r356 = load i64, ptr %r355 + %r357 = icmp eq i64 %r356, %r329 + %r358 = and i1 %r340, %r344 + %r359 = and i1 %r358, %r348 + %r360 = and i1 %r359, %r351 + %r361 = and i1 %r360, %r354 + %r362 = and i1 %r361, %r357 + %r363 = and i16 %r346, 2048 + %r364 = icmp eq i16 %r363, 0 + %r365 = and i1 %r362, %r364 + %r366 = and i16 %r346, 4096 + %r367 = icmp ne i16 %r366, 0 + %r368 = and i1 %r365, %r367 + br i1 %r368, label %class_field_get.fast.42, label %class_field_inline.guardcall.46 + +class_field_inline.guardcall.46: + %r369 = call i32 @js_typed_feedback_class_field_get_guard(i64 8450987250308612131, double %r323, i32 1, i64 %r329, i64 %r328, i32 3, i32 1) + %r370 = icmp ne i32 %r369, 0 + br i1 %r370, label %class_field_get.fast.42, label %class_field_get.fallback.43 + +put.dynic.guard.47: + %r399 = sub i64 %r385, 8 + %r400 = inttoptr i64 %r399 to ptr + %r401 = load i8, ptr %r400 + %r402 = icmp eq i8 %r401, 2 + %r403 = sub i64 %r385, 7 + %r404 = inttoptr i64 %r403 to ptr + %r405 = load i8, ptr %r404 + %r406 = and i8 %r405, 128 + %r407 = icmp eq i8 %r406, 0 + %r408 = sub i64 %r385, 6 + %r409 = inttoptr i64 %r408 to ptr + %r410 = load i16, ptr %r409 + %r411 = and i16 %r410, 6407 + %r412 = icmp eq i16 %r411, 0 + %r413 = inttoptr i64 %r385 to ptr + %r414 = load i32, ptr %r413 + %r415 = icmp eq i32 %r414, 1 + %r416 = add i64 %r385, 4 + %r417 = inttoptr i64 %r416 to ptr + %r418 = load i32, ptr %r417 + %r419 = icmp ne i32 %r418, 0 + %r420 = icmp ne i32 %r418, -2 + %r421 = add i64 %r385, 16 + %r422 = inttoptr i64 %r421 to ptr + %r423 = load i64, ptr %r422 + %r424 = add i64 %r385, 8 + %r425 = inttoptr i64 %r424 to ptr + %r426 = load i32, ptr %r425 + %r427 = add i32 %r426, -2147483648 + %r428 = icmp ult i32 %r427, 1073741824 + %r429 = zext i32 %r426 to i64 + %r430 = or i64 %r429, 4611686018427387904 + %r431 = select i1 %r428, i64 %r430, i64 %r423 + %r432 = getelementptr i64, ptr @perry_ic_36, i64 0 + %r433 = load i64, ptr %r432 + %r434 = icmp eq i64 %r431, %r433 + %r435 = icmp ne i64 %r431, 0 + %r436 = and i1 %r402, %r407 + %r437 = and i1 %r436, %r412 + %r438 = and i1 %r437, %r415 + %r439 = and i1 %r438, %r419 + %r440 = and i1 %r439, %r420 + %r441 = and i1 %r440, %r434 + %r442 = and i1 %r441, %r435 + br i1 %r442, label %put.dynic.ways.48, label %put.dynic.slow.53 + +put.dynic.ways.48: + %r443 = getelementptr i64, ptr @perry_ic_36, i64 1 + %r444 = load i64, ptr %r443 + %r445 = getelementptr i64, ptr @perry_ic_36, i64 2 + %r446 = load i64, ptr %r445 + %r447 = icmp eq i64 %r382, %r444 + br i1 %r447, label %put.dynic.bounds.51, label %put.dynic.way1.49 + +put.dynic.way1.49: + %r448 = getelementptr i64, ptr @perry_ic_36, i64 3 + %r449 = load i64, ptr %r448 + %r450 = getelementptr i64, ptr @perry_ic_36, i64 4 + %r451 = load i64, ptr %r450 + %r452 = icmp eq i64 %r382, %r449 + br i1 %r452, label %put.dynic.bounds.51, label %put.dynic.way2.50 + +put.dynic.way2.50: + %r453 = getelementptr i64, ptr @perry_ic_36, i64 5 + %r454 = load i64, ptr %r453 + %r455 = getelementptr i64, ptr @perry_ic_36, i64 6 + %r456 = load i64, ptr %r455 + %r457 = icmp eq i64 %r382, %r454 + br i1 %r457, label %put.dynic.bounds.51, label %put.dynic.slow.53 + +put.dynic.bounds.51: + %r458 = phi i64 [ %r446, %put.dynic.ways.48 ], [ %r451, %put.dynic.way1.49 ], [ %r456, %put.dynic.way2.50 ] + %r459 = add i64 %r385, 12 + %r460 = inttoptr i64 %r459 to ptr + %r461 = load i32, ptr %r460 + %r462 = zext i32 %r461 to i64 + %r463 = icmp ult i64 %r462, 4 + %r464 = select i1 %r463, i64 4, i64 %r462 + %r465 = icmp ult i64 %r458, %r464 + br i1 %r465, label %put.dynic.store.52, label %put.dynic.slow.53 + +put.dynic.store.52: + %r466 = add i64 %r458, 4 + %r467 = inttoptr i64 %r385 to ptr + %r468 = getelementptr inbounds i64, ptr %r467, i64 %r466 + store double %r379, ptr %r468 + br label %put.dynic.merge.54 + +put.dynic.slow.53: + %r469 = call double @js_put_value_set_dyn_ic(ptr @perry_ic_36, double %r381, double %r380, double %r379, i32 1) + br label %put.dynic.merge.54 + +put.dynic.merge.54: + %r470 = phi double [ %r379, %put.dynic.store.52 ], [ %r469, %put.dynic.slow.53 ] + %r471 = load double, ptr %r8 + %r472 = bitcast double %r471 to i64 + %r473 = and i64 %r472, 281474976710655 + %r474 = load double, ptr @batch_ts_.str.4.handle + %r475 = bitcast double %r474 to i64 + %r476 = and i64 %r475, 281474976710655 + %r477 = load i64, ptr @perry_class_keys_batch_ts__Row + %r478 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r479 = icmp eq i8 %r478, 0 + %r480 = lshr i64 %r472, 48 + %r481 = icmp eq i64 %r480, 32765 + %r482 = icmp ugt i64 %r473, 1048575 + %r483 = and i1 %r481, %r482 + %r484 = and i1 %r483, %r479 + br i1 %r484, label %class_field_inline.deref.58, label %class_field_inline.guardcall.59 + +class_field_get.fast.55: + %r519 = inttoptr i64 %r473 to ptr + %r520 = getelementptr i8, ptr %r519, i64 32 + %r521 = getelementptr double, ptr %r520, i64 3 + %r522 = load double, ptr %r521 + br label %class_field_get.merge.57 + +class_field_get.fallback.56: + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612133) + %r523 = call double @js_object_get_field_by_name_f64(i64 %r472, i64 %r476) + br label %class_field_get.merge.57 + +class_field_get.merge.57: + %r524 = phi double [ %r522, %class_field_get.fast.55 ], [ %r523, %class_field_get.fallback.56 ] + %r525 = load double, ptr %r66 + %r526 = bitcast double %r525 to i64 + %r527 = and i64 %r526, 281474976710655 + %r528 = load double, ptr @batch_ts_.str.3.handle + %r529 = bitcast double %r528 to i64 + %r530 = and i64 %r529, 281474976710655 + %r531 = lshr i64 %r526, 48 + %r532 = icmp eq i64 %r531, 32761 + %r533 = icmp eq i64 %r531, 32766 + %r534 = and i64 %r531, 65533 + %r535 = icmp eq i64 %r534, 32765 + br i1 %r532, label %pget.recv_sso.60, label %pget.check_class_ref.66 + +class_field_inline.deref.58: + %r485 = inttoptr i64 %r473 to ptr + %r486 = getelementptr i8, ptr %r485, i64 -8 + %r487 = load i8, ptr %r486 + %r488 = icmp eq i8 %r487, 2 + %r489 = getelementptr i8, ptr %r485, i64 -7 + %r490 = load i8, ptr %r489 + %r491 = and i8 %r490, -128 + %r492 = icmp eq i8 %r491, 0 + %r493 = getelementptr i8, ptr %r485, i64 -6 + %r494 = load i16, ptr %r493 + %r495 = load i32, ptr %r485 + %r496 = icmp eq i32 %r495, 1 + %r497 = getelementptr i8, ptr %r485, i64 4 + %r498 = load i32, ptr %r497 + %r499 = icmp eq i32 %r498, 1 + %r500 = getelementptr i8, ptr %r485, i64 12 + %r501 = load i32, ptr %r500 + %r502 = icmp ugt i32 %r501, 3 + %r503 = getelementptr i8, ptr %r485, i64 16 + %r504 = load i64, ptr %r503 + %r505 = icmp eq i64 %r504, %r477 + %r506 = and i1 %r488, %r492 + %r507 = and i1 %r506, %r496 + %r508 = and i1 %r507, %r499 + %r509 = and i1 %r508, %r502 + %r510 = and i1 %r509, %r505 + %r511 = and i16 %r494, 2048 + %r512 = icmp eq i16 %r511, 0 + %r513 = and i1 %r510, %r512 + %r514 = and i16 %r494, 4096 + %r515 = icmp ne i16 %r514, 0 + %r516 = and i1 %r513, %r515 + br i1 %r516, label %class_field_get.fast.55, label %class_field_inline.guardcall.59 + +class_field_inline.guardcall.59: + %r517 = call i32 @js_typed_feedback_class_field_get_guard(i64 8450987250308612133, double %r471, i32 1, i64 %r477, i64 %r476, i32 3, i32 1) + %r518 = icmp ne i32 %r517, 0 + br i1 %r518, label %class_field_get.fast.55, label %class_field_get.fallback.56 + +pget.recv_sso.60: + %r599 = call double @js_object_get_field_by_name_f64(i64 %r526, i64 %r530) + br label %pget.recv_merge.64 + +pget.recv_ok.61: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612134, i64 %r527, i64 %r530) + %r537 = icmp ugt i64 %r527, 1048575 + %r538 = ptrtoint ptr @perry_ic_39 to i64 + %r539 = select i1 %r537, i64 %r527, i64 %r538 + %r540 = sub i64 %r539, 8 + %r541 = inttoptr i64 %r540 to ptr + %r542 = load i8, ptr %r541 + %r543 = icmp eq i8 %r542, 2 + %r544 = and i1 %r537, %r543 + %r545 = add i64 %r539, 12 + %r546 = inttoptr i64 %r545 to ptr + %r547 = load i32, ptr %r546 + %r548 = icmp eq i32 %r547, 1129268819 + %r549 = xor i1 %r548, true + %r550 = and i1 %r544, %r549 + %r551 = inttoptr i64 %r539 to ptr + %r552 = load i32, ptr %r551 + %r553 = icmp eq i32 %r552, 1 + %r554 = and i1 %r550, %r553 + %r555 = sub i64 %r539, 6 + %r556 = inttoptr i64 %r555 to ptr + %r557 = load i16, ptr %r556 + %r558 = and i16 %r557, 2048 + %r559 = icmp eq i16 %r558, 0 + %r560 = and i1 %r554, %r559 + %r561 = add i64 %r539, 16 + %r562 = inttoptr i64 %r561 to ptr + %r563 = load i64, ptr %r562 + %r564 = add i64 %r539, 8 + %r565 = inttoptr i64 %r564 to ptr + %r566 = load i32, ptr %r565 + %r567 = add i32 %r566, -2147483648 + %r568 = icmp ult i32 %r567, 1073741824 + %r569 = zext i32 %r566 to i64 + %r570 = or i64 %r569, 4611686018427387904 + %r571 = select i1 %r568, i64 %r570, i64 %r563 + %r572 = getelementptr i64, ptr @perry_ic_39, i64 0 + %r573 = load i64, ptr %r572 + %r574 = icmp eq i64 %r571, %r573 + %r575 = icmp ne i64 %r571, 0 + %r576 = and i1 %r560, %r574 + %r577 = and i1 %r576, %r575 + br i1 %r577, label %pic.hit.67, label %pic.miss.68 + +pget.recv_bad.62: + %r594 = icmp eq i64 %r526, 9222246136947933185 + %r595 = icmp eq i64 %r526, 9222246136947933186 + %r596 = or i1 %r594, %r595 + br i1 %r596, label %pget.throw_nullish.71, label %pget.recv_undef_return.72 + +pget.recv_class_ref.63: + %r536 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612134, i64 %r526, i64 %r530) + br label %pget.recv_merge.64 + +pget.recv_merge.64: + %r600 = phi double [ %r593, %pic.merge.69 ], [ %r598, %pget.recv_undef_return.72 ], [ %r599, %pget.recv_sso.60 ], [ %r536, %pget.recv_class_ref.63 ] + %r601 = call double @js_rel_gt(double %r524, double %r600) + %r602 = bitcast double %r601 to i64 + %r603 = icmp eq i64 %r602, 9222246136947933188 + br i1 %r603, label %if.then.73, label %if.else.74 + +pget.check_ptr.65: + br i1 %r535, label %pget.recv_ok.61, label %pget.recv_bad.62 + +pget.check_class_ref.66: + br i1 %r533, label %pget.recv_class_ref.63, label %pget.check_ptr.65 + +pic.hit.67: + %r578 = getelementptr i64, ptr @perry_ic_39, i64 1 + %r579 = load i64, ptr %r578 + %r580 = add i64 %r539, 12 + %r581 = inttoptr i64 %r580 to ptr + %r582 = load i32, ptr %r581 + %r583 = zext i32 %r582 to i64 + %r584 = icmp ult i64 %r583, 4 + %r585 = select i1 %r584, i64 4, i64 %r583 + %r586 = icmp ult i64 %r579, %r585 + br i1 %r586, label %pic.hit.load.70, label %pic.miss.68 + +pic.miss.68: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612134) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612134) + %r592 = call double @js_object_get_field_ic_miss(i64 %r527, i64 %r530, ptr @perry_ic_39) + br label %pic.merge.69 + +pic.merge.69: + %r593 = phi double [ %r591, %pic.hit.load.70 ], [ %r592, %pic.miss.68 ] + br label %pget.recv_merge.64 + +pic.hit.load.70: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612134) + %r587 = shl i64 %r579, 3 + %r588 = add i64 %r527, 32 + %r589 = add i64 %r588, %r587 + %r590 = inttoptr i64 %r589 to ptr + %r591 = load double, ptr %r590 + br label %pic.merge.69 + +pget.throw_nullish.71: + %r597 = zext i1 %r595 to i32 + call void @js_throw_type_error_property_access(i32 %r597, ptr @batch_ts_.str.3.bytes, i64 4) + unreachable + +pget.recv_undef_return.72: + %r598 = call double @js_object_get_field_by_name_f64(i64 %r526, i64 %r530) + br label %pget.recv_merge.64 + +if.then.73: + %r604 = load double, ptr @batch_ts_.str.3.handle + %r605 = load double, ptr %r8 + %r606 = bitcast double %r605 to i64 + %r607 = and i64 %r606, 281474976710655 + %r608 = load double, ptr @batch_ts_.str.4.handle + %r609 = bitcast double %r608 to i64 + %r610 = and i64 %r609, 281474976710655 + %r611 = load i64, ptr @perry_class_keys_batch_ts__Row + %r612 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r613 = icmp eq i8 %r612, 0 + %r614 = lshr i64 %r606, 48 + %r615 = icmp eq i64 %r614, 32765 + %r616 = icmp ugt i64 %r607, 1048575 + %r617 = and i1 %r615, %r616 + %r618 = and i1 %r617, %r613 + br i1 %r618, label %class_field_inline.deref.79, label %class_field_inline.guardcall.80 + +if.else.74: + br label %if.merge.75 + +if.merge.75: + %r750 = load double, ptr %r7 + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r750 + +class_field_get.fast.76: + %r653 = inttoptr i64 %r607 to ptr + %r654 = getelementptr i8, ptr %r653, i64 32 + %r655 = getelementptr double, ptr %r654, i64 3 + %r656 = load double, ptr %r655 + br label %class_field_get.merge.78 + +class_field_get.fallback.77: + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612136) + %r657 = call double @js_object_get_field_by_name_f64(i64 %r606, i64 %r610) + br label %class_field_get.merge.78 + +class_field_get.merge.78: + %r658 = phi double [ %r656, %class_field_get.fast.76 ], [ %r657, %class_field_get.fallback.77 ] + %r659 = load double, ptr @batch_ts_.str.3.handle + %r660 = load double, ptr %r66 + %r661 = bitcast double %r659 to i64 + %r662 = bitcast double %r658 to i64 + %r663 = bitcast double %r660 to i64 + %r664 = and i64 %r663, 281474976710655 + %r665 = lshr i64 %r663, 48 + %r666 = icmp eq i64 %r665, 32765 + %r667 = icmp ugt i64 %r664, 1048575 + %r668 = lshr i64 %r662, 48 + %r669 = icmp ne i64 %r668, 32765 + %r670 = icmp ne i64 %r668, 32767 + %r671 = icmp ne i64 %r668, 32762 + %r672 = icmp ne i64 %r661, 0 + %r673 = and i1 %r666, %r667 + %r674 = and i1 %r673, %r669 + %r675 = and i1 %r674, %r670 + %r676 = and i1 %r675, %r671 + %r677 = and i1 %r676, %r672 + br i1 %r677, label %put.dynic.guard.81, label %put.dynic.slow.87 + +class_field_inline.deref.79: + %r619 = inttoptr i64 %r607 to ptr + %r620 = getelementptr i8, ptr %r619, i64 -8 + %r621 = load i8, ptr %r620 + %r622 = icmp eq i8 %r621, 2 + %r623 = getelementptr i8, ptr %r619, i64 -7 + %r624 = load i8, ptr %r623 + %r625 = and i8 %r624, -128 + %r626 = icmp eq i8 %r625, 0 + %r627 = getelementptr i8, ptr %r619, i64 -6 + %r628 = load i16, ptr %r627 + %r629 = load i32, ptr %r619 + %r630 = icmp eq i32 %r629, 1 + %r631 = getelementptr i8, ptr %r619, i64 4 + %r632 = load i32, ptr %r631 + %r633 = icmp eq i32 %r632, 1 + %r634 = getelementptr i8, ptr %r619, i64 12 + %r635 = load i32, ptr %r634 + %r636 = icmp ugt i32 %r635, 3 + %r637 = getelementptr i8, ptr %r619, i64 16 + %r638 = load i64, ptr %r637 + %r639 = icmp eq i64 %r638, %r611 + %r640 = and i1 %r622, %r626 + %r641 = and i1 %r640, %r630 + %r642 = and i1 %r641, %r633 + %r643 = and i1 %r642, %r636 + %r644 = and i1 %r643, %r639 + %r645 = and i16 %r628, 2048 + %r646 = icmp eq i16 %r645, 0 + %r647 = and i1 %r644, %r646 + %r648 = and i16 %r628, 4096 + %r649 = icmp ne i16 %r648, 0 + %r650 = and i1 %r647, %r649 + br i1 %r650, label %class_field_get.fast.76, label %class_field_inline.guardcall.80 + +class_field_inline.guardcall.80: + %r651 = call i32 @js_typed_feedback_class_field_get_guard(i64 8450987250308612136, double %r605, i32 1, i64 %r611, i64 %r610, i32 3, i32 1) + %r652 = icmp ne i32 %r651, 0 + br i1 %r652, label %class_field_get.fast.76, label %class_field_get.fallback.77 + +put.dynic.guard.81: + %r678 = sub i64 %r664, 8 + %r679 = inttoptr i64 %r678 to ptr + %r680 = load i8, ptr %r679 + %r681 = icmp eq i8 %r680, 2 + %r682 = sub i64 %r664, 7 + %r683 = inttoptr i64 %r682 to ptr + %r684 = load i8, ptr %r683 + %r685 = and i8 %r684, 128 + %r686 = icmp eq i8 %r685, 0 + %r687 = sub i64 %r664, 6 + %r688 = inttoptr i64 %r687 to ptr + %r689 = load i16, ptr %r688 + %r690 = and i16 %r689, 6407 + %r691 = icmp eq i16 %r690, 0 + %r692 = inttoptr i64 %r664 to ptr + %r693 = load i32, ptr %r692 + %r694 = icmp eq i32 %r693, 1 + %r695 = add i64 %r664, 4 + %r696 = inttoptr i64 %r695 to ptr + %r697 = load i32, ptr %r696 + %r698 = icmp ne i32 %r697, 0 + %r699 = icmp ne i32 %r697, -2 + %r700 = add i64 %r664, 16 + %r701 = inttoptr i64 %r700 to ptr + %r702 = load i64, ptr %r701 + %r703 = add i64 %r664, 8 + %r704 = inttoptr i64 %r703 to ptr + %r705 = load i32, ptr %r704 + %r706 = add i32 %r705, -2147483648 + %r707 = icmp ult i32 %r706, 1073741824 + %r708 = zext i32 %r705 to i64 + %r709 = or i64 %r708, 4611686018427387904 + %r710 = select i1 %r707, i64 %r709, i64 %r702 + %r711 = getelementptr i64, ptr @perry_ic_41, i64 0 + %r712 = load i64, ptr %r711 + %r713 = icmp eq i64 %r710, %r712 + %r714 = icmp ne i64 %r710, 0 + %r715 = and i1 %r681, %r686 + %r716 = and i1 %r715, %r691 + %r717 = and i1 %r716, %r694 + %r718 = and i1 %r717, %r698 + %r719 = and i1 %r718, %r699 + %r720 = and i1 %r719, %r713 + %r721 = and i1 %r720, %r714 + br i1 %r721, label %put.dynic.ways.82, label %put.dynic.slow.87 + +put.dynic.ways.82: + %r722 = getelementptr i64, ptr @perry_ic_41, i64 1 + %r723 = load i64, ptr %r722 + %r724 = getelementptr i64, ptr @perry_ic_41, i64 2 + %r725 = load i64, ptr %r724 + %r726 = icmp eq i64 %r661, %r723 + br i1 %r726, label %put.dynic.bounds.85, label %put.dynic.way1.83 + +put.dynic.way1.83: + %r727 = getelementptr i64, ptr @perry_ic_41, i64 3 + %r728 = load i64, ptr %r727 + %r729 = getelementptr i64, ptr @perry_ic_41, i64 4 + %r730 = load i64, ptr %r729 + %r731 = icmp eq i64 %r661, %r728 + br i1 %r731, label %put.dynic.bounds.85, label %put.dynic.way2.84 + +put.dynic.way2.84: + %r732 = getelementptr i64, ptr @perry_ic_41, i64 5 + %r733 = load i64, ptr %r732 + %r734 = getelementptr i64, ptr @perry_ic_41, i64 6 + %r735 = load i64, ptr %r734 + %r736 = icmp eq i64 %r661, %r733 + br i1 %r736, label %put.dynic.bounds.85, label %put.dynic.slow.87 + +put.dynic.bounds.85: + %r737 = phi i64 [ %r725, %put.dynic.ways.82 ], [ %r730, %put.dynic.way1.83 ], [ %r735, %put.dynic.way2.84 ] + %r738 = add i64 %r664, 12 + %r739 = inttoptr i64 %r738 to ptr + %r740 = load i32, ptr %r739 + %r741 = zext i32 %r740 to i64 + %r742 = icmp ult i64 %r741, 4 + %r743 = select i1 %r742, i64 4, i64 %r741 + %r744 = icmp ult i64 %r737, %r743 + br i1 %r744, label %put.dynic.store.86, label %put.dynic.slow.87 + +put.dynic.store.86: + %r745 = add i64 %r737, 4 + %r746 = inttoptr i64 %r664 to ptr + %r747 = getelementptr inbounds i64, ptr %r746, i64 %r745 + store double %r658, ptr %r747 + br label %put.dynic.merge.88 + +put.dynic.slow.87: + %r748 = call double @js_put_value_set_dyn_ic(ptr @perry_ic_41, double %r660, double %r659, double %r658, i32 1) + br label %put.dynic.merge.88 + +put.dynic.merge.88: + %r749 = phi double [ %r658, %put.dynic.store.86 ], [ %r748, %put.dynic.slow.87 ] + br label %if.merge.75 +} + +define double @perry_method_batch_ts__Row__rescore(double %this_arg, double %arg13) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 1) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %this_arg, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = alloca double + store double %arg13, ptr %r8 + %r9 = load double, ptr %r7 + %r10 = load double, ptr %r7 + %r11 = bitcast double %r10 to i64 + %r12 = and i64 %r11, 281474976710655 + %r13 = load double, ptr @batch_ts_.str.2.handle + %r14 = bitcast double %r13 to i64 + %r15 = and i64 %r14, 281474976710655 + %r16 = load i64, ptr @perry_class_keys_batch_ts__Row + %r17 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r18 = icmp eq i8 %r17, 0 + %r19 = lshr i64 %r11, 48 + %r20 = icmp eq i64 %r19, 32765 + %r21 = icmp ugt i64 %r12, 1048575 + %r22 = and i1 %r20, %r21 + %r23 = and i1 %r22, %r18 + br i1 %r23, label %class_field_inline.deref.4, label %class_field_inline.guardcall.5 + +class_field_get_number.fast.1: + %r58 = inttoptr i64 %r12 to ptr + %r59 = getelementptr i8, ptr %r58, i64 32 + %r60 = getelementptr double, ptr %r59, i64 2 + %r61 = load double, ptr %r60 + br label %class_field_get_number.merge.3 + +class_field_get_number.fallback.2: + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612138) + %r62 = call double @js_object_get_field_by_name_f64(i64 %r11, i64 %r15) + %r63 = call double @js_number_coerce(double %r62) + br label %class_field_get_number.merge.3 + +class_field_get_number.merge.3: + %r64 = phi double [ %r61, %class_field_get_number.fast.1 ], [ %r63, %class_field_get_number.fallback.2 ] + %r65 = load double, ptr %r8 + %r66 = fmul double %r64, %r65 + %r67 = load double, ptr %r7 + %r68 = bitcast double %r67 to i64 + %r69 = and i64 %r68, 281474976710655 + %r70 = load double, ptr @batch_ts_.str.7.handle + %r71 = bitcast double %r70 to i64 + %r72 = and i64 %r71, 281474976710655 + %r73 = load i64, ptr @perry_class_keys_batch_ts__Row + %r74 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r75 = icmp eq i8 %r74, 0 + %r76 = lshr i64 %r68, 48 + %r77 = icmp eq i64 %r76, 32765 + %r78 = icmp ugt i64 %r69, 1048575 + %r79 = and i1 %r77, %r78 + %r80 = and i1 %r79, %r75 + br i1 %r80, label %class_field_inline.deref.9, label %class_field_inline.guardcall.10 + +class_field_inline.deref.4: + %r24 = inttoptr i64 %r12 to ptr + %r25 = getelementptr i8, ptr %r24, i64 -8 + %r26 = load i8, ptr %r25 + %r27 = icmp eq i8 %r26, 2 + %r28 = getelementptr i8, ptr %r24, i64 -7 + %r29 = load i8, ptr %r28 + %r30 = and i8 %r29, -128 + %r31 = icmp eq i8 %r30, 0 + %r32 = getelementptr i8, ptr %r24, i64 -6 + %r33 = load i16, ptr %r32 + %r34 = load i32, ptr %r24 + %r35 = icmp eq i32 %r34, 1 + %r36 = getelementptr i8, ptr %r24, i64 4 + %r37 = load i32, ptr %r36 + %r38 = icmp eq i32 %r37, 1 + %r39 = getelementptr i8, ptr %r24, i64 12 + %r40 = load i32, ptr %r39 + %r41 = icmp ugt i32 %r40, 2 + %r42 = getelementptr i8, ptr %r24, i64 16 + %r43 = load i64, ptr %r42 + %r44 = icmp eq i64 %r43, %r16 + %r45 = and i1 %r27, %r31 + %r46 = and i1 %r45, %r35 + %r47 = and i1 %r46, %r38 + %r48 = and i1 %r47, %r41 + %r49 = and i1 %r48, %r44 + %r50 = and i16 %r33, 2048 + %r51 = icmp eq i16 %r50, 0 + %r52 = and i1 %r49, %r51 + %r53 = and i16 %r33, 4096 + %r54 = icmp ne i16 %r53, 0 + %r55 = and i1 %r52, %r54 + br i1 %r55, label %class_field_get_number.fast.1, label %class_field_inline.guardcall.5 + +class_field_inline.guardcall.5: + %r56 = call i32 @js_typed_feedback_class_field_get_guard(i64 8450987250308612138, double %r10, i32 1, i64 %r16, i64 %r15, i32 2, i32 1) + %r57 = icmp ne i32 %r56, 0 + br i1 %r57, label %class_field_get_number.fast.1, label %class_field_get_number.fallback.2 + +class_field_get_number.fast.6: + %r115 = inttoptr i64 %r69 to ptr + %r116 = getelementptr i8, ptr %r115, i64 32 + %r117 = getelementptr double, ptr %r116, i64 0 + %r118 = load double, ptr %r117 + br label %class_field_get_number.merge.8 + +class_field_get_number.fallback.7: + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612139) + %r119 = call double @js_object_get_field_by_name_f64(i64 %r68, i64 %r72) + %r120 = call double @js_number_coerce(double %r119) + br label %class_field_get_number.merge.8 + +class_field_get_number.merge.8: + %r121 = phi double [ %r118, %class_field_get_number.fast.6 ], [ %r120, %class_field_get_number.fallback.7 ] + %r122 = frem double %r121, 7.0 + %r123 = fadd double %r66, %r122 + %r124 = bitcast double %r9 to i64 + %r125 = and i64 %r124, 281474976710655 + %r126 = load double, ptr @batch_ts_.str.4.handle + %r127 = bitcast double %r126 to i64 + %r128 = and i64 %r127, 281474976710655 + %r129 = load i64, ptr @perry_class_keys_batch_ts__Row + %r130 = bitcast double %r123 to i64 + %r131 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r132 = icmp eq i8 %r131, 0 + %r133 = lshr i64 %r124, 48 + %r134 = icmp eq i64 %r133, 32765 + %r135 = icmp ugt i64 %r125, 1048575 + %r136 = and i1 %r134, %r135 + %r137 = and i1 %r136, %r132 + br i1 %r137, label %class_field_inline.deref.14, label %class_field_inline.guardcall.15 + +class_field_inline.deref.9: + %r81 = inttoptr i64 %r69 to ptr + %r82 = getelementptr i8, ptr %r81, i64 -8 + %r83 = load i8, ptr %r82 + %r84 = icmp eq i8 %r83, 2 + %r85 = getelementptr i8, ptr %r81, i64 -7 + %r86 = load i8, ptr %r85 + %r87 = and i8 %r86, -128 + %r88 = icmp eq i8 %r87, 0 + %r89 = getelementptr i8, ptr %r81, i64 -6 + %r90 = load i16, ptr %r89 + %r91 = load i32, ptr %r81 + %r92 = icmp eq i32 %r91, 1 + %r93 = getelementptr i8, ptr %r81, i64 4 + %r94 = load i32, ptr %r93 + %r95 = icmp eq i32 %r94, 1 + %r96 = getelementptr i8, ptr %r81, i64 12 + %r97 = load i32, ptr %r96 + %r98 = icmp ugt i32 %r97, 0 + %r99 = getelementptr i8, ptr %r81, i64 16 + %r100 = load i64, ptr %r99 + %r101 = icmp eq i64 %r100, %r73 + %r102 = and i1 %r84, %r88 + %r103 = and i1 %r102, %r92 + %r104 = and i1 %r103, %r95 + %r105 = and i1 %r104, %r98 + %r106 = and i1 %r105, %r101 + %r107 = and i16 %r90, 2048 + %r108 = icmp eq i16 %r107, 0 + %r109 = and i1 %r106, %r108 + %r110 = and i16 %r90, 4096 + %r111 = icmp ne i16 %r110, 0 + %r112 = and i1 %r109, %r111 + br i1 %r112, label %class_field_get_number.fast.6, label %class_field_inline.guardcall.10 + +class_field_inline.guardcall.10: + %r113 = call i32 @js_typed_feedback_class_field_get_guard(i64 8450987250308612139, double %r67, i32 1, i64 %r73, i64 %r72, i32 0, i32 1) + %r114 = icmp ne i32 %r113, 0 + br i1 %r114, label %class_field_get_number.fast.6, label %class_field_get_number.fallback.7 + +class_field_set.fast.11: + %r178 = inttoptr i64 %r125 to ptr + %r179 = getelementptr i8, ptr %r178, i64 32 + %r180 = getelementptr double, ptr %r179, i64 3 + %r181 = call double @js_array_numeric_value_to_raw_f64(double %r123) + store double %r181, ptr %r180 + br label %class_field_set.merge.13 + +class_field_set.fallback.12: + call void @js_class_field_set_fallback(i64 8450987250308612140, i64 %r124, i64 %r128, double %r123) + br label %class_field_set.merge.13 + +class_field_set.merge.13: + %r182 = load double, ptr %r7 + %r183 = bitcast double %r182 to i64 + %r184 = and i64 %r183, 281474976710655 + %r185 = load double, ptr @batch_ts_.str.4.handle + %r186 = bitcast double %r185 to i64 + %r187 = and i64 %r186, 281474976710655 + %r188 = load i64, ptr @perry_class_keys_batch_ts__Row + %r189 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r190 = icmp eq i8 %r189, 0 + %r191 = lshr i64 %r183, 48 + %r192 = icmp eq i64 %r191, 32765 + %r193 = icmp ugt i64 %r184, 1048575 + %r194 = and i1 %r192, %r193 + %r195 = and i1 %r194, %r190 + br i1 %r195, label %class_field_inline.deref.19, label %class_field_inline.guardcall.20 + +class_field_inline.deref.14: + %r138 = inttoptr i64 %r125 to ptr + %r139 = getelementptr i8, ptr %r138, i64 -8 + %r140 = load i8, ptr %r139 + %r141 = icmp eq i8 %r140, 2 + %r142 = getelementptr i8, ptr %r138, i64 -7 + %r143 = load i8, ptr %r142 + %r144 = and i8 %r143, -128 + %r145 = icmp eq i8 %r144, 0 + %r146 = getelementptr i8, ptr %r138, i64 -6 + %r147 = load i16, ptr %r146 + %r148 = load i32, ptr %r138 + %r149 = icmp eq i32 %r148, 1 + %r150 = getelementptr i8, ptr %r138, i64 4 + %r151 = load i32, ptr %r150 + %r152 = icmp eq i32 %r151, 1 + %r153 = getelementptr i8, ptr %r138, i64 12 + %r154 = load i32, ptr %r153 + %r155 = icmp ugt i32 %r154, 3 + %r156 = getelementptr i8, ptr %r138, i64 16 + %r157 = load i64, ptr %r156 + %r158 = icmp eq i64 %r157, %r129 + %r159 = and i1 %r141, %r145 + %r160 = and i1 %r159, %r149 + %r161 = and i1 %r160, %r152 + %r162 = and i1 %r161, %r155 + %r163 = and i1 %r162, %r158 + %r164 = and i16 %r147, 2048 + %r165 = icmp eq i16 %r164, 0 + %r166 = and i1 %r163, %r165 + %r167 = and i16 %r147, 4096 + %r168 = icmp ne i16 %r167, 0 + %r169 = and i1 %r166, %r168 + %r170 = and i16 %r147, 1 + %r171 = icmp eq i16 %r170, 0 + %r172 = and i1 %r169, %r171 + %r173 = and i64 %r130, 9218868437227405312 + %r174 = icmp ne i64 %r173, 9218868437227405312 + %r175 = and i1 %r172, %r174 + br i1 %r175, label %class_field_set.fast.11, label %class_field_inline.guardcall.15 + +class_field_inline.guardcall.15: + %r176 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612140, double %r9, i32 1, i64 %r129, i64 %r128, i32 3, double %r123, i32 1) + %r177 = icmp ne i32 %r176, 0 + br i1 %r177, label %class_field_set.fast.11, label %class_field_set.fallback.12 + +class_field_get.fast.16: + %r230 = inttoptr i64 %r184 to ptr + %r231 = getelementptr i8, ptr %r230, i64 32 + %r232 = getelementptr double, ptr %r231, i64 3 + %r233 = load double, ptr %r232 + br label %class_field_get.merge.18 + +class_field_get.fallback.17: + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612141) + %r234 = call double @js_object_get_field_by_name_f64(i64 %r183, i64 %r187) + br label %class_field_get.merge.18 + +class_field_get.merge.18: + %r235 = phi double [ %r233, %class_field_get.fast.16 ], [ %r234, %class_field_get.fallback.17 ] + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r235 + +class_field_inline.deref.19: + %r196 = inttoptr i64 %r184 to ptr + %r197 = getelementptr i8, ptr %r196, i64 -8 + %r198 = load i8, ptr %r197 + %r199 = icmp eq i8 %r198, 2 + %r200 = getelementptr i8, ptr %r196, i64 -7 + %r201 = load i8, ptr %r200 + %r202 = and i8 %r201, -128 + %r203 = icmp eq i8 %r202, 0 + %r204 = getelementptr i8, ptr %r196, i64 -6 + %r205 = load i16, ptr %r204 + %r206 = load i32, ptr %r196 + %r207 = icmp eq i32 %r206, 1 + %r208 = getelementptr i8, ptr %r196, i64 4 + %r209 = load i32, ptr %r208 + %r210 = icmp eq i32 %r209, 1 + %r211 = getelementptr i8, ptr %r196, i64 12 + %r212 = load i32, ptr %r211 + %r213 = icmp ugt i32 %r212, 3 + %r214 = getelementptr i8, ptr %r196, i64 16 + %r215 = load i64, ptr %r214 + %r216 = icmp eq i64 %r215, %r188 + %r217 = and i1 %r199, %r203 + %r218 = and i1 %r217, %r207 + %r219 = and i1 %r218, %r210 + %r220 = and i1 %r219, %r213 + %r221 = and i1 %r220, %r216 + %r222 = and i16 %r205, 2048 + %r223 = icmp eq i16 %r222, 0 + %r224 = and i1 %r221, %r223 + %r225 = and i16 %r205, 4096 + %r226 = icmp ne i16 %r225, 0 + %r227 = and i1 %r224, %r226 + br i1 %r227, label %class_field_get.fast.16, label %class_field_inline.guardcall.20 + +class_field_inline.guardcall.20: + %r228 = call i32 @js_typed_feedback_class_field_get_guard(i64 8450987250308612141, double %r182, i32 1, i64 %r188, i64 %r187, i32 3, i32 1) + %r229 = icmp ne i32 %r228, 0 + br i1 %r229, label %class_field_get.fast.16, label %class_field_get.fallback.17 +} + +define internal double @perry_method_batch_ts__Row__rescore__pshape(double %this_arg, double %arg13) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 1) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %this_arg, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = alloca double + store double %arg13, ptr %r8 + %r9 = load double, ptr %r7 + %r10 = load double, ptr %r7 + %r11 = bitcast double %r10 to i64 + %r12 = and i64 %r11, 281474976710655 + %r13 = inttoptr i64 %r12 to ptr + %r14 = getelementptr i8, ptr %r13, i64 32 + %r15 = getelementptr double, ptr %r14, i64 2 + %r16 = load double, ptr %r15 + %r17 = bitcast double %r16 to i64 + %r18 = and i64 %r17, 9218868437227405312 + %r19 = icmp ne i64 %r18, 9218868437227405312 + br i1 %r19, label %ptr_shape_get_number.plain.1, label %ptr_shape_get_number.coerce.2 + +ptr_shape_get_number.plain.1: + br label %ptr_shape_get_number.merge.3 + +ptr_shape_get_number.coerce.2: + %r20 = call double @js_number_coerce(double %r16) + br label %ptr_shape_get_number.merge.3 + +ptr_shape_get_number.merge.3: + %r21 = phi double [ %r16, %ptr_shape_get_number.plain.1 ], [ %r20, %ptr_shape_get_number.coerce.2 ] + %r22 = load double, ptr %r8 + %r23 = fmul double %r21, %r22 + %r24 = load double, ptr %r7 + %r25 = bitcast double %r24 to i64 + %r26 = and i64 %r25, 281474976710655 + %r27 = inttoptr i64 %r26 to ptr + %r28 = getelementptr i8, ptr %r27, i64 32 + %r29 = getelementptr double, ptr %r28, i64 0 + %r30 = load double, ptr %r29 + %r31 = bitcast double %r30 to i64 + %r32 = and i64 %r31, 9218868437227405312 + %r33 = icmp ne i64 %r32, 9218868437227405312 + br i1 %r33, label %ptr_shape_get_number.plain.4, label %ptr_shape_get_number.coerce.5 + +ptr_shape_get_number.plain.4: + br label %ptr_shape_get_number.merge.6 + +ptr_shape_get_number.coerce.5: + %r34 = call double @js_number_coerce(double %r30) + br label %ptr_shape_get_number.merge.6 + +ptr_shape_get_number.merge.6: + %r35 = phi double [ %r30, %ptr_shape_get_number.plain.4 ], [ %r34, %ptr_shape_get_number.coerce.5 ] + %r36 = frem double %r35, 7.0 + %r37 = fadd double %r23, %r36 + %r38 = bitcast double %r9 to i64 + %r39 = and i64 %r38, 281474976710655 + %r40 = inttoptr i64 %r39 to ptr + %r41 = getelementptr i8, ptr %r40, i64 32 + %r42 = getelementptr double, ptr %r41, i64 3 + %r43 = bitcast double %r37 to i64 + %r44 = and i64 %r43, 9218868437227405312 + %r45 = icmp ne i64 %r44, 9218868437227405312 + br i1 %r45, label %ptr_shape_set.raw_store.7, label %ptr_shape_set.downgrade.8 + +ptr_shape_set.raw_store.7: + store double %r37, ptr %r42 + br label %ptr_shape_set.merge.9 + +ptr_shape_set.downgrade.8: + %r46 = load double, ptr @batch_ts_.str.4.handle + %r47 = bitcast double %r46 to i64 + %r48 = and i64 %r47, 281474976710655 + call void @js_class_field_set_fallback(i64 8450987250308612142, i64 %r38, i64 %r48, double %r37) + br label %ptr_shape_set.merge.9 + +ptr_shape_set.merge.9: + %r49 = load double, ptr %r7 + %r50 = bitcast double %r49 to i64 + %r51 = and i64 %r50, 281474976710655 + %r52 = inttoptr i64 %r51 to ptr + %r53 = getelementptr i8, ptr %r52, i64 32 + %r54 = getelementptr double, ptr %r53, i64 3 + %r55 = load double, ptr %r54 + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r55 +} + +define double @batch_ts__Row_constructor(double %this_arg, double %arg9, double %arg10, double %arg11) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 2) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %this_arg, ptr %r7 + call void @js_shadow_slot_bind(i32 1, ptr %r7) + %r8 = alloca double + store double %arg9, ptr %r8 + %r9 = alloca double + store double %arg10, ptr %r9 + call void @js_shadow_slot_bind(i32 0, ptr %r9) + %r10 = alloca double + store double %arg11, ptr %r10 + %r11 = load double, ptr %r7 + %r12 = bitcast double %r11 to i64 + %r13 = and i64 %r12, 281474976710655 + %r14 = load double, ptr @batch_ts_.str.7.handle + %r15 = bitcast double %r14 to i64 + %r16 = and i64 %r15, 281474976710655 + %r17 = load i64, ptr @perry_class_keys_batch_ts__Row + %r18 = bitcast double 0x7FFC000000000001 to i64 + %r19 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r20 = icmp eq i8 %r19, 0 + %r21 = lshr i64 %r12, 48 + %r22 = icmp eq i64 %r21, 32765 + %r23 = icmp ugt i64 %r13, 1048575 + %r24 = and i1 %r22, %r23 + %r25 = and i1 %r24, %r20 + br i1 %r25, label %class_field_inline.deref.4, label %class_field_inline.guardcall.5 + +class_field_set.fast.1: + %r66 = inttoptr i64 %r13 to ptr + %r67 = getelementptr i8, ptr %r66, i64 32 + %r68 = getelementptr double, ptr %r67, i64 0 + %r69 = call double @js_array_numeric_value_to_raw_f64(double 0x7FFC000000000001) + store double %r69, ptr %r68 + br label %class_field_set.merge.3 + +class_field_set.fallback.2: + call void @js_class_field_set_fallback(i64 8450987250308612143, i64 %r12, i64 %r16, double 0x7FFC000000000001) + br label %class_field_set.merge.3 + +class_field_set.merge.3: + %r70 = load double, ptr %r7 + %r71 = bitcast double %r70 to i64 + %r72 = and i64 %r71, 281474976710655 + %r73 = load double, ptr @batch_ts_.str.5.handle + %r74 = bitcast double %r73 to i64 + %r75 = and i64 %r74, 281474976710655 + %r76 = load i64, ptr @perry_class_keys_batch_ts__Row + %r77 = bitcast double 0x7FFC000000000001 to i64 + %r78 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612144, double %r70, i32 1, i64 %r76, i64 %r75, i32 1, double 0x7FFC000000000001, i32 0) + %r79 = icmp ne i32 %r78, 0 + br i1 %r79, label %class_field_set.fast.6, label %class_field_set.fallback.7 + +class_field_inline.deref.4: + %r26 = inttoptr i64 %r13 to ptr + %r27 = getelementptr i8, ptr %r26, i64 -8 + %r28 = load i8, ptr %r27 + %r29 = icmp eq i8 %r28, 2 + %r30 = getelementptr i8, ptr %r26, i64 -7 + %r31 = load i8, ptr %r30 + %r32 = and i8 %r31, -128 + %r33 = icmp eq i8 %r32, 0 + %r34 = getelementptr i8, ptr %r26, i64 -6 + %r35 = load i16, ptr %r34 + %r36 = load i32, ptr %r26 + %r37 = icmp eq i32 %r36, 1 + %r38 = getelementptr i8, ptr %r26, i64 4 + %r39 = load i32, ptr %r38 + %r40 = icmp eq i32 %r39, 1 + %r41 = getelementptr i8, ptr %r26, i64 12 + %r42 = load i32, ptr %r41 + %r43 = icmp ugt i32 %r42, 0 + %r44 = getelementptr i8, ptr %r26, i64 16 + %r45 = load i64, ptr %r44 + %r46 = icmp eq i64 %r45, %r17 + %r47 = and i1 %r29, %r33 + %r48 = and i1 %r47, %r37 + %r49 = and i1 %r48, %r40 + %r50 = and i1 %r49, %r43 + %r51 = and i1 %r50, %r46 + %r52 = and i16 %r35, 2048 + %r53 = icmp eq i16 %r52, 0 + %r54 = and i1 %r51, %r53 + %r55 = and i16 %r35, 4096 + %r56 = icmp ne i16 %r55, 0 + %r57 = and i1 %r54, %r56 + %r58 = and i16 %r35, 1 + %r59 = icmp eq i16 %r58, 0 + %r60 = and i1 %r57, %r59 + %r61 = and i64 %r18, 9218868437227405312 + %r62 = icmp ne i64 %r61, 9218868437227405312 + %r63 = and i1 %r60, %r62 + br i1 %r63, label %class_field_set.fast.1, label %class_field_inline.guardcall.5 + +class_field_inline.guardcall.5: + %r64 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612143, double %r11, i32 1, i64 %r17, i64 %r16, i32 0, double 0x7FFC000000000001, i32 1) + %r65 = icmp ne i32 %r64, 0 + br i1 %r65, label %class_field_set.fast.1, label %class_field_set.fallback.2 + +class_field_set.fast.6: + %r80 = inttoptr i64 %r72 to ptr + %r81 = getelementptr i8, ptr %r80, i64 32 + %r82 = getelementptr double, ptr %r81, i64 1 + %r83 = ptrtoint ptr %r82 to i64 + store double 0x7FFC000000000001, ptr %r82 + call void @js_string_addref_if_heap_string(double 0x7FFC000000000001) + %r84 = bitcast double 0x7FFC000000000001 to i64 + call void @js_gc_note_slot_layout(i64 %r72, i32 1, i64 %r84) + br label %class_field_set.merge.8 + +class_field_set.fallback.7: + call void @js_class_field_set_fallback(i64 8450987250308612144, i64 %r71, i64 %r75, double 0x7FFC000000000001) + br label %class_field_set.merge.8 + +class_field_set.merge.8: + %r85 = load double, ptr %r7 + %r86 = bitcast double %r85 to i64 + %r87 = and i64 %r86, 281474976710655 + %r88 = load double, ptr @batch_ts_.str.2.handle + %r89 = bitcast double %r88 to i64 + %r90 = and i64 %r89, 281474976710655 + %r91 = load i64, ptr @perry_class_keys_batch_ts__Row + %r92 = bitcast double 0x7FFC000000000001 to i64 + %r93 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r94 = icmp eq i8 %r93, 0 + %r95 = lshr i64 %r86, 48 + %r96 = icmp eq i64 %r95, 32765 + %r97 = icmp ugt i64 %r87, 1048575 + %r98 = and i1 %r96, %r97 + %r99 = and i1 %r98, %r94 + br i1 %r99, label %class_field_inline.deref.12, label %class_field_inline.guardcall.13 + +class_field_set.fast.9: + %r140 = inttoptr i64 %r87 to ptr + %r141 = getelementptr i8, ptr %r140, i64 32 + %r142 = getelementptr double, ptr %r141, i64 2 + %r143 = call double @js_array_numeric_value_to_raw_f64(double 0x7FFC000000000001) + store double %r143, ptr %r142 + br label %class_field_set.merge.11 + +class_field_set.fallback.10: + call void @js_class_field_set_fallback(i64 8450987250308612145, i64 %r86, i64 %r90, double 0x7FFC000000000001) + br label %class_field_set.merge.11 + +class_field_set.merge.11: + %r144 = load double, ptr %r7 + %r145 = bitcast double %r144 to i64 + %r146 = and i64 %r145, 281474976710655 + %r147 = load double, ptr @batch_ts_.str.4.handle + %r148 = bitcast double %r147 to i64 + %r149 = and i64 %r148, 281474976710655 + %r150 = load i64, ptr @perry_class_keys_batch_ts__Row + %r151 = bitcast double 0x7FFC000000000001 to i64 + %r152 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r153 = icmp eq i8 %r152, 0 + %r154 = lshr i64 %r145, 48 + %r155 = icmp eq i64 %r154, 32765 + %r156 = icmp ugt i64 %r146, 1048575 + %r157 = and i1 %r155, %r156 + %r158 = and i1 %r157, %r153 + br i1 %r158, label %class_field_inline.deref.17, label %class_field_inline.guardcall.18 + +class_field_inline.deref.12: + %r100 = inttoptr i64 %r87 to ptr + %r101 = getelementptr i8, ptr %r100, i64 -8 + %r102 = load i8, ptr %r101 + %r103 = icmp eq i8 %r102, 2 + %r104 = getelementptr i8, ptr %r100, i64 -7 + %r105 = load i8, ptr %r104 + %r106 = and i8 %r105, -128 + %r107 = icmp eq i8 %r106, 0 + %r108 = getelementptr i8, ptr %r100, i64 -6 + %r109 = load i16, ptr %r108 + %r110 = load i32, ptr %r100 + %r111 = icmp eq i32 %r110, 1 + %r112 = getelementptr i8, ptr %r100, i64 4 + %r113 = load i32, ptr %r112 + %r114 = icmp eq i32 %r113, 1 + %r115 = getelementptr i8, ptr %r100, i64 12 + %r116 = load i32, ptr %r115 + %r117 = icmp ugt i32 %r116, 2 + %r118 = getelementptr i8, ptr %r100, i64 16 + %r119 = load i64, ptr %r118 + %r120 = icmp eq i64 %r119, %r91 + %r121 = and i1 %r103, %r107 + %r122 = and i1 %r121, %r111 + %r123 = and i1 %r122, %r114 + %r124 = and i1 %r123, %r117 + %r125 = and i1 %r124, %r120 + %r126 = and i16 %r109, 2048 + %r127 = icmp eq i16 %r126, 0 + %r128 = and i1 %r125, %r127 + %r129 = and i16 %r109, 4096 + %r130 = icmp ne i16 %r129, 0 + %r131 = and i1 %r128, %r130 + %r132 = and i16 %r109, 1 + %r133 = icmp eq i16 %r132, 0 + %r134 = and i1 %r131, %r133 + %r135 = and i64 %r92, 9218868437227405312 + %r136 = icmp ne i64 %r135, 9218868437227405312 + %r137 = and i1 %r134, %r136 + br i1 %r137, label %class_field_set.fast.9, label %class_field_inline.guardcall.13 + +class_field_inline.guardcall.13: + %r138 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612145, double %r85, i32 1, i64 %r91, i64 %r90, i32 2, double 0x7FFC000000000001, i32 1) + %r139 = icmp ne i32 %r138, 0 + br i1 %r139, label %class_field_set.fast.9, label %class_field_set.fallback.10 + +class_field_set.fast.14: + %r199 = inttoptr i64 %r146 to ptr + %r200 = getelementptr i8, ptr %r199, i64 32 + %r201 = getelementptr double, ptr %r200, i64 3 + %r202 = call double @js_array_numeric_value_to_raw_f64(double 0x7FFC000000000001) + store double %r202, ptr %r201 + br label %class_field_set.merge.16 + +class_field_set.fallback.15: + call void @js_class_field_set_fallback(i64 8450987250308612146, i64 %r145, i64 %r149, double 0x7FFC000000000001) + br label %class_field_set.merge.16 + +class_field_set.merge.16: + %r203 = load double, ptr %r7 + %r204 = load double, ptr %r8 + %r205 = bitcast double %r203 to i64 + %r206 = and i64 %r205, 281474976710655 + %r207 = load double, ptr @batch_ts_.str.7.handle + %r208 = bitcast double %r207 to i64 + %r209 = and i64 %r208, 281474976710655 + %r210 = load i64, ptr @perry_class_keys_batch_ts__Row + %r211 = bitcast double %r204 to i64 + %r212 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r213 = icmp eq i8 %r212, 0 + %r214 = lshr i64 %r205, 48 + %r215 = icmp eq i64 %r214, 32765 + %r216 = icmp ugt i64 %r206, 1048575 + %r217 = and i1 %r215, %r216 + %r218 = and i1 %r217, %r213 + br i1 %r218, label %class_field_inline.deref.22, label %class_field_inline.guardcall.23 + +class_field_inline.deref.17: + %r159 = inttoptr i64 %r146 to ptr + %r160 = getelementptr i8, ptr %r159, i64 -8 + %r161 = load i8, ptr %r160 + %r162 = icmp eq i8 %r161, 2 + %r163 = getelementptr i8, ptr %r159, i64 -7 + %r164 = load i8, ptr %r163 + %r165 = and i8 %r164, -128 + %r166 = icmp eq i8 %r165, 0 + %r167 = getelementptr i8, ptr %r159, i64 -6 + %r168 = load i16, ptr %r167 + %r169 = load i32, ptr %r159 + %r170 = icmp eq i32 %r169, 1 + %r171 = getelementptr i8, ptr %r159, i64 4 + %r172 = load i32, ptr %r171 + %r173 = icmp eq i32 %r172, 1 + %r174 = getelementptr i8, ptr %r159, i64 12 + %r175 = load i32, ptr %r174 + %r176 = icmp ugt i32 %r175, 3 + %r177 = getelementptr i8, ptr %r159, i64 16 + %r178 = load i64, ptr %r177 + %r179 = icmp eq i64 %r178, %r150 + %r180 = and i1 %r162, %r166 + %r181 = and i1 %r180, %r170 + %r182 = and i1 %r181, %r173 + %r183 = and i1 %r182, %r176 + %r184 = and i1 %r183, %r179 + %r185 = and i16 %r168, 2048 + %r186 = icmp eq i16 %r185, 0 + %r187 = and i1 %r184, %r186 + %r188 = and i16 %r168, 4096 + %r189 = icmp ne i16 %r188, 0 + %r190 = and i1 %r187, %r189 + %r191 = and i16 %r168, 1 + %r192 = icmp eq i16 %r191, 0 + %r193 = and i1 %r190, %r192 + %r194 = and i64 %r151, 9218868437227405312 + %r195 = icmp ne i64 %r194, 9218868437227405312 + %r196 = and i1 %r193, %r195 + br i1 %r196, label %class_field_set.fast.14, label %class_field_inline.guardcall.18 + +class_field_inline.guardcall.18: + %r197 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612146, double %r144, i32 1, i64 %r150, i64 %r149, i32 3, double 0x7FFC000000000001, i32 1) + %r198 = icmp ne i32 %r197, 0 + br i1 %r198, label %class_field_set.fast.14, label %class_field_set.fallback.15 + +class_field_set.fast.19: + %r259 = inttoptr i64 %r206 to ptr + %r260 = getelementptr i8, ptr %r259, i64 32 + %r261 = getelementptr double, ptr %r260, i64 0 + %r262 = call double @js_array_numeric_value_to_raw_f64(double %r204) + store double %r262, ptr %r261 + br label %class_field_set.merge.21 + +class_field_set.fallback.20: + call void @js_class_field_set_fallback(i64 8450987250308612147, i64 %r205, i64 %r209, double %r204) + br label %class_field_set.merge.21 + +class_field_set.merge.21: + %r263 = load double, ptr %r7 + %r264 = load double, ptr %r9 + %r265 = bitcast double %r263 to i64 + %r266 = and i64 %r265, 281474976710655 + %r267 = load double, ptr @batch_ts_.str.5.handle + %r268 = bitcast double %r267 to i64 + %r269 = and i64 %r268, 281474976710655 + %r270 = load i64, ptr @perry_class_keys_batch_ts__Row + %r271 = bitcast double %r264 to i64 + %r272 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612148, double %r263, i32 1, i64 %r270, i64 %r269, i32 1, double %r264, i32 0) + %r273 = icmp ne i32 %r272, 0 + br i1 %r273, label %class_field_set.fast.24, label %class_field_set.fallback.25 + +class_field_inline.deref.22: + %r219 = inttoptr i64 %r206 to ptr + %r220 = getelementptr i8, ptr %r219, i64 -8 + %r221 = load i8, ptr %r220 + %r222 = icmp eq i8 %r221, 2 + %r223 = getelementptr i8, ptr %r219, i64 -7 + %r224 = load i8, ptr %r223 + %r225 = and i8 %r224, -128 + %r226 = icmp eq i8 %r225, 0 + %r227 = getelementptr i8, ptr %r219, i64 -6 + %r228 = load i16, ptr %r227 + %r229 = load i32, ptr %r219 + %r230 = icmp eq i32 %r229, 1 + %r231 = getelementptr i8, ptr %r219, i64 4 + %r232 = load i32, ptr %r231 + %r233 = icmp eq i32 %r232, 1 + %r234 = getelementptr i8, ptr %r219, i64 12 + %r235 = load i32, ptr %r234 + %r236 = icmp ugt i32 %r235, 0 + %r237 = getelementptr i8, ptr %r219, i64 16 + %r238 = load i64, ptr %r237 + %r239 = icmp eq i64 %r238, %r210 + %r240 = and i1 %r222, %r226 + %r241 = and i1 %r240, %r230 + %r242 = and i1 %r241, %r233 + %r243 = and i1 %r242, %r236 + %r244 = and i1 %r243, %r239 + %r245 = and i16 %r228, 2048 + %r246 = icmp eq i16 %r245, 0 + %r247 = and i1 %r244, %r246 + %r248 = and i16 %r228, 4096 + %r249 = icmp ne i16 %r248, 0 + %r250 = and i1 %r247, %r249 + %r251 = and i16 %r228, 1 + %r252 = icmp eq i16 %r251, 0 + %r253 = and i1 %r250, %r252 + %r254 = and i64 %r211, 9218868437227405312 + %r255 = icmp ne i64 %r254, 9218868437227405312 + %r256 = and i1 %r253, %r255 + br i1 %r256, label %class_field_set.fast.19, label %class_field_inline.guardcall.23 + +class_field_inline.guardcall.23: + %r257 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612147, double %r203, i32 1, i64 %r210, i64 %r209, i32 0, double %r204, i32 1) + %r258 = icmp ne i32 %r257, 0 + br i1 %r258, label %class_field_set.fast.19, label %class_field_set.fallback.20 + +class_field_set.fast.24: + %r274 = inttoptr i64 %r266 to ptr + %r275 = getelementptr i8, ptr %r274, i64 32 + %r276 = getelementptr double, ptr %r275, i64 1 + %r277 = ptrtoint ptr %r276 to i64 + store double %r264, ptr %r276 + call void @js_string_addref_if_heap_string(double %r264) + %r278 = bitcast double %r264 to i64 + call void @js_gc_note_slot_layout(i64 %r266, i32 1, i64 %r278) + call void @js_write_barrier_slot(i64 %r265, i64 %r277, i64 %r278) + br label %class_field_set.merge.26 + +class_field_set.fallback.25: + call void @js_class_field_set_fallback(i64 8450987250308612148, i64 %r265, i64 %r269, double %r264) + br label %class_field_set.merge.26 + +class_field_set.merge.26: + %r279 = load double, ptr %r7 + %r280 = load double, ptr %r10 + %r281 = bitcast double %r279 to i64 + %r282 = and i64 %r281, 281474976710655 + %r283 = load double, ptr @batch_ts_.str.2.handle + %r284 = bitcast double %r283 to i64 + %r285 = and i64 %r284, 281474976710655 + %r286 = load i64, ptr @perry_class_keys_batch_ts__Row + %r287 = bitcast double %r280 to i64 + %r288 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r289 = icmp eq i8 %r288, 0 + %r290 = lshr i64 %r281, 48 + %r291 = icmp eq i64 %r290, 32765 + %r292 = icmp ugt i64 %r282, 1048575 + %r293 = and i1 %r291, %r292 + %r294 = and i1 %r293, %r289 + br i1 %r294, label %class_field_inline.deref.30, label %class_field_inline.guardcall.31 + +class_field_set.fast.27: + %r335 = inttoptr i64 %r282 to ptr + %r336 = getelementptr i8, ptr %r335, i64 32 + %r337 = getelementptr double, ptr %r336, i64 2 + %r338 = call double @js_array_numeric_value_to_raw_f64(double %r280) + store double %r338, ptr %r337 + br label %class_field_set.merge.29 + +class_field_set.fallback.28: + call void @js_class_field_set_fallback(i64 8450987250308612149, i64 %r281, i64 %r285, double %r280) + br label %class_field_set.merge.29 + +class_field_set.merge.29: + %r339 = load double, ptr %r7 + %r340 = bitcast double %r339 to i64 + %r341 = and i64 %r340, 281474976710655 + %r342 = load double, ptr @batch_ts_.str.4.handle + %r343 = bitcast double %r342 to i64 + %r344 = and i64 %r343, 281474976710655 + %r345 = load i64, ptr @perry_class_keys_batch_ts__Row + %r346 = bitcast double 0.0 to i64 + %r347 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r348 = icmp eq i8 %r347, 0 + %r349 = lshr i64 %r340, 48 + %r350 = icmp eq i64 %r349, 32765 + %r351 = icmp ugt i64 %r341, 1048575 + %r352 = and i1 %r350, %r351 + %r353 = and i1 %r352, %r348 + br i1 %r353, label %class_field_inline.deref.35, label %class_field_inline.guardcall.36 + +class_field_inline.deref.30: + %r295 = inttoptr i64 %r282 to ptr + %r296 = getelementptr i8, ptr %r295, i64 -8 + %r297 = load i8, ptr %r296 + %r298 = icmp eq i8 %r297, 2 + %r299 = getelementptr i8, ptr %r295, i64 -7 + %r300 = load i8, ptr %r299 + %r301 = and i8 %r300, -128 + %r302 = icmp eq i8 %r301, 0 + %r303 = getelementptr i8, ptr %r295, i64 -6 + %r304 = load i16, ptr %r303 + %r305 = load i32, ptr %r295 + %r306 = icmp eq i32 %r305, 1 + %r307 = getelementptr i8, ptr %r295, i64 4 + %r308 = load i32, ptr %r307 + %r309 = icmp eq i32 %r308, 1 + %r310 = getelementptr i8, ptr %r295, i64 12 + %r311 = load i32, ptr %r310 + %r312 = icmp ugt i32 %r311, 2 + %r313 = getelementptr i8, ptr %r295, i64 16 + %r314 = load i64, ptr %r313 + %r315 = icmp eq i64 %r314, %r286 + %r316 = and i1 %r298, %r302 + %r317 = and i1 %r316, %r306 + %r318 = and i1 %r317, %r309 + %r319 = and i1 %r318, %r312 + %r320 = and i1 %r319, %r315 + %r321 = and i16 %r304, 2048 + %r322 = icmp eq i16 %r321, 0 + %r323 = and i1 %r320, %r322 + %r324 = and i16 %r304, 4096 + %r325 = icmp ne i16 %r324, 0 + %r326 = and i1 %r323, %r325 + %r327 = and i16 %r304, 1 + %r328 = icmp eq i16 %r327, 0 + %r329 = and i1 %r326, %r328 + %r330 = and i64 %r287, 9218868437227405312 + %r331 = icmp ne i64 %r330, 9218868437227405312 + %r332 = and i1 %r329, %r331 + br i1 %r332, label %class_field_set.fast.27, label %class_field_inline.guardcall.31 + +class_field_inline.guardcall.31: + %r333 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612149, double %r279, i32 1, i64 %r286, i64 %r285, i32 2, double %r280, i32 1) + %r334 = icmp ne i32 %r333, 0 + br i1 %r334, label %class_field_set.fast.27, label %class_field_set.fallback.28 + +class_field_set.fast.32: + %r394 = inttoptr i64 %r341 to ptr + %r395 = getelementptr i8, ptr %r394, i64 32 + %r396 = getelementptr double, ptr %r395, i64 3 + %r397 = call double @js_array_numeric_value_to_raw_f64(double 0.0) + store double %r397, ptr %r396 + br label %class_field_set.merge.34 + +class_field_set.fallback.33: + call void @js_class_field_set_fallback(i64 8450987250308612150, i64 %r340, i64 %r344, double 0.0) + br label %class_field_set.merge.34 + +class_field_set.merge.34: + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double 0x7FFC000000000001 + +class_field_inline.deref.35: + %r354 = inttoptr i64 %r341 to ptr + %r355 = getelementptr i8, ptr %r354, i64 -8 + %r356 = load i8, ptr %r355 + %r357 = icmp eq i8 %r356, 2 + %r358 = getelementptr i8, ptr %r354, i64 -7 + %r359 = load i8, ptr %r358 + %r360 = and i8 %r359, -128 + %r361 = icmp eq i8 %r360, 0 + %r362 = getelementptr i8, ptr %r354, i64 -6 + %r363 = load i16, ptr %r362 + %r364 = load i32, ptr %r354 + %r365 = icmp eq i32 %r364, 1 + %r366 = getelementptr i8, ptr %r354, i64 4 + %r367 = load i32, ptr %r366 + %r368 = icmp eq i32 %r367, 1 + %r369 = getelementptr i8, ptr %r354, i64 12 + %r370 = load i32, ptr %r369 + %r371 = icmp ugt i32 %r370, 3 + %r372 = getelementptr i8, ptr %r354, i64 16 + %r373 = load i64, ptr %r372 + %r374 = icmp eq i64 %r373, %r345 + %r375 = and i1 %r357, %r361 + %r376 = and i1 %r375, %r365 + %r377 = and i1 %r376, %r368 + %r378 = and i1 %r377, %r371 + %r379 = and i1 %r378, %r374 + %r380 = and i16 %r363, 2048 + %r381 = icmp eq i16 %r380, 0 + %r382 = and i1 %r379, %r381 + %r383 = and i16 %r363, 4096 + %r384 = icmp ne i16 %r383, 0 + %r385 = and i1 %r382, %r384 + %r386 = and i16 %r363, 1 + %r387 = icmp eq i16 %r386, 0 + %r388 = and i1 %r385, %r387 + %r389 = and i64 %r346, 9218868437227405312 + %r390 = icmp ne i64 %r389, 9218868437227405312 + %r391 = and i1 %r388, %r390 + br i1 %r391, label %class_field_set.fast.32, label %class_field_inline.guardcall.36 + +class_field_inline.guardcall.36: + %r392 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612150, double %r339, i32 1, i64 %r345, i64 %r344, i32 3, double 0.0, i32 1) + %r393 = icmp ne i32 %r392, 0 + br i1 %r393, label %class_field_set.fast.32, label %class_field_set.fallback.33 +} + +define double @batch_ts____AnonShape_e75d7e32e87dc826_constructor(double %this_arg, double %arg20, double %arg21, double %arg22) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 4) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %this_arg, ptr %r7 + call void @js_shadow_slot_bind(i32 3, ptr %r7) + %r8 = alloca double + store double %arg20, ptr %r8 + call void @js_shadow_slot_bind(i32 0, ptr %r8) + %r9 = alloca double + store double %arg21, ptr %r9 + call void @js_shadow_slot_bind(i32 1, ptr %r9) + %r10 = alloca double + store double %arg22, ptr %r10 + call void @js_shadow_slot_bind(i32 2, ptr %r10) + %r11 = load double, ptr %r7 + %r12 = bitcast double %r11 to i64 + %r13 = and i64 %r12, 281474976710655 + %r14 = load double, ptr @batch_ts_.str.12.handle + %r15 = bitcast double %r14 to i64 + %r16 = and i64 %r15, 281474976710655 + %r17 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 + %r18 = bitcast double 0x7FFC000000000001 to i64 + %r19 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612151, double %r11, i32 2, i64 %r17, i64 %r16, i32 0, double 0x7FFC000000000001, i32 0) + %r20 = icmp ne i32 %r19, 0 + br i1 %r20, label %class_field_set.fast.1, label %class_field_set.fallback.2 + +class_field_set.fast.1: + %r21 = inttoptr i64 %r13 to ptr + %r22 = getelementptr i8, ptr %r21, i64 32 + %r23 = getelementptr double, ptr %r22, i64 0 + %r24 = ptrtoint ptr %r23 to i64 + store double 0x7FFC000000000001, ptr %r23 + call void @js_string_addref_if_heap_string(double 0x7FFC000000000001) + %r25 = bitcast double 0x7FFC000000000001 to i64 + call void @js_gc_note_slot_layout(i64 %r13, i32 0, i64 %r25) + br label %class_field_set.merge.3 + +class_field_set.fallback.2: + call void @js_class_field_set_fallback(i64 8450987250308612151, i64 %r12, i64 %r16, double 0x7FFC000000000001) + br label %class_field_set.merge.3 + +class_field_set.merge.3: + %r26 = load double, ptr %r7 + %r27 = bitcast double %r26 to i64 + %r28 = and i64 %r27, 281474976710655 + %r29 = load double, ptr @batch_ts_.str.11.handle + %r30 = bitcast double %r29 to i64 + %r31 = and i64 %r30, 281474976710655 + %r32 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 + %r33 = bitcast double 0x7FFC000000000001 to i64 + %r34 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612152, double %r26, i32 2, i64 %r32, i64 %r31, i32 1, double 0x7FFC000000000001, i32 0) + %r35 = icmp ne i32 %r34, 0 + br i1 %r35, label %class_field_set.fast.4, label %class_field_set.fallback.5 + +class_field_set.fast.4: + %r36 = inttoptr i64 %r28 to ptr + %r37 = getelementptr i8, ptr %r36, i64 32 + %r38 = getelementptr double, ptr %r37, i64 1 + %r39 = ptrtoint ptr %r38 to i64 + store double 0x7FFC000000000001, ptr %r38 + call void @js_string_addref_if_heap_string(double 0x7FFC000000000001) + %r40 = bitcast double 0x7FFC000000000001 to i64 + call void @js_gc_note_slot_layout(i64 %r28, i32 1, i64 %r40) + br label %class_field_set.merge.6 + +class_field_set.fallback.5: + call void @js_class_field_set_fallback(i64 8450987250308612152, i64 %r27, i64 %r31, double 0x7FFC000000000001) + br label %class_field_set.merge.6 + +class_field_set.merge.6: + %r41 = load double, ptr %r7 + %r42 = bitcast double %r41 to i64 + %r43 = and i64 %r42, 281474976710655 + %r44 = load double, ptr @batch_ts_.str.14.handle + %r45 = bitcast double %r44 to i64 + %r46 = and i64 %r45, 281474976710655 + %r47 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 + %r48 = bitcast double 0x7FFC000000000001 to i64 + %r49 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612153, double %r41, i32 2, i64 %r47, i64 %r46, i32 2, double 0x7FFC000000000001, i32 0) + %r50 = icmp ne i32 %r49, 0 + br i1 %r50, label %class_field_set.fast.7, label %class_field_set.fallback.8 + +class_field_set.fast.7: + %r51 = inttoptr i64 %r43 to ptr + %r52 = getelementptr i8, ptr %r51, i64 32 + %r53 = getelementptr double, ptr %r52, i64 2 + %r54 = ptrtoint ptr %r53 to i64 + store double 0x7FFC000000000001, ptr %r53 + call void @js_string_addref_if_heap_string(double 0x7FFC000000000001) + %r55 = bitcast double 0x7FFC000000000001 to i64 + call void @js_gc_note_slot_layout(i64 %r43, i32 2, i64 %r55) + br label %class_field_set.merge.9 + +class_field_set.fallback.8: + call void @js_class_field_set_fallback(i64 8450987250308612153, i64 %r42, i64 %r46, double 0x7FFC000000000001) + br label %class_field_set.merge.9 + +class_field_set.merge.9: + %r56 = load double, ptr %r7 + %r57 = load double, ptr %r8 + %r58 = bitcast double %r56 to i64 + %r59 = and i64 %r58, 281474976710655 + %r60 = load double, ptr @batch_ts_.str.12.handle + %r61 = bitcast double %r60 to i64 + %r62 = and i64 %r61, 281474976710655 + %r63 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 + %r64 = bitcast double %r57 to i64 + %r65 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612154, double %r56, i32 2, i64 %r63, i64 %r62, i32 0, double %r57, i32 0) + %r66 = icmp ne i32 %r65, 0 + br i1 %r66, label %class_field_set.fast.10, label %class_field_set.fallback.11 + +class_field_set.fast.10: + %r67 = inttoptr i64 %r59 to ptr + %r68 = getelementptr i8, ptr %r67, i64 32 + %r69 = getelementptr double, ptr %r68, i64 0 + %r70 = ptrtoint ptr %r69 to i64 + store double %r57, ptr %r69 + call void @js_string_addref_if_heap_string(double %r57) + %r71 = bitcast double %r57 to i64 + call void @js_gc_note_slot_layout(i64 %r59, i32 0, i64 %r71) + call void @js_write_barrier_slot(i64 %r58, i64 %r70, i64 %r71) + br label %class_field_set.merge.12 + +class_field_set.fallback.11: + call void @js_class_field_set_fallback(i64 8450987250308612154, i64 %r58, i64 %r62, double %r57) + br label %class_field_set.merge.12 + +class_field_set.merge.12: + %r72 = load double, ptr %r7 + %r73 = load double, ptr %r9 + %r74 = bitcast double %r72 to i64 + %r75 = and i64 %r74, 281474976710655 + %r76 = load double, ptr @batch_ts_.str.11.handle + %r77 = bitcast double %r76 to i64 + %r78 = and i64 %r77, 281474976710655 + %r79 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 + %r80 = bitcast double %r73 to i64 + %r81 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612155, double %r72, i32 2, i64 %r79, i64 %r78, i32 1, double %r73, i32 0) + %r82 = icmp ne i32 %r81, 0 + br i1 %r82, label %class_field_set.fast.13, label %class_field_set.fallback.14 + +class_field_set.fast.13: + %r83 = inttoptr i64 %r75 to ptr + %r84 = getelementptr i8, ptr %r83, i64 32 + %r85 = getelementptr double, ptr %r84, i64 1 + %r86 = ptrtoint ptr %r85 to i64 + store double %r73, ptr %r85 + call void @js_string_addref_if_heap_string(double %r73) + %r87 = bitcast double %r73 to i64 + call void @js_gc_note_slot_layout(i64 %r75, i32 1, i64 %r87) + call void @js_write_barrier_slot(i64 %r74, i64 %r86, i64 %r87) + br label %class_field_set.merge.15 + +class_field_set.fallback.14: + call void @js_class_field_set_fallback(i64 8450987250308612155, i64 %r74, i64 %r78, double %r73) + br label %class_field_set.merge.15 + +class_field_set.merge.15: + %r88 = load double, ptr %r7 + %r89 = load double, ptr %r10 + %r90 = bitcast double %r88 to i64 + %r91 = and i64 %r90, 281474976710655 + %r92 = load double, ptr @batch_ts_.str.14.handle + %r93 = bitcast double %r92 to i64 + %r94 = and i64 %r93, 281474976710655 + %r95 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 + %r96 = bitcast double %r89 to i64 + %r97 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612156, double %r88, i32 2, i64 %r95, i64 %r94, i32 2, double %r89, i32 0) + %r98 = icmp ne i32 %r97, 0 + br i1 %r98, label %class_field_set.fast.16, label %class_field_set.fallback.17 + +class_field_set.fast.16: + %r99 = inttoptr i64 %r91 to ptr + %r100 = getelementptr i8, ptr %r99, i64 32 + %r101 = getelementptr double, ptr %r100, i64 2 + %r102 = ptrtoint ptr %r101 to i64 + store double %r89, ptr %r101 + call void @js_string_addref_if_heap_string(double %r89) + %r103 = bitcast double %r89 to i64 + call void @js_gc_note_slot_layout(i64 %r91, i32 2, i64 %r103) + call void @js_write_barrier_slot(i64 %r90, i64 %r102, i64 %r103) + br label %class_field_set.merge.18 + +class_field_set.fallback.17: + call void @js_class_field_set_fallback(i64 8450987250308612156, i64 %r90, i64 %r94, double %r89) + br label %class_field_set.merge.18 + +class_field_set.merge.18: + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double 0x7FFC000000000001 +} + +define double @batch_ts____AnonShape_c33c4204c28b9430_constructor(double %this_arg, double %arg30, double %arg31, double %arg32, double %arg33) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 2) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %this_arg, ptr %r7 + call void @js_shadow_slot_bind(i32 1, ptr %r7) + %r8 = alloca double + store double %arg30, ptr %r8 + call void @js_shadow_slot_bind(i32 0, ptr %r8) + %r9 = alloca double + store double %arg31, ptr %r9 + %r10 = alloca double + store double %arg32, ptr %r10 + %r11 = alloca double + store double %arg33, ptr %r11 + %r12 = load double, ptr %r7 + %r13 = bitcast double %r12 to i64 + %r14 = and i64 %r13, 281474976710655 + %r15 = load double, ptr @batch_ts_.str.5.handle + %r16 = bitcast double %r15 to i64 + %r17 = and i64 %r16, 281474976710655 + %r18 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + %r19 = bitcast double 0x7FFC000000000001 to i64 + %r20 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612157, double %r12, i32 3, i64 %r18, i64 %r17, i32 0, double 0x7FFC000000000001, i32 0) + %r21 = icmp ne i32 %r20, 0 + br i1 %r21, label %class_field_set.fast.1, label %class_field_set.fallback.2 + +class_field_set.fast.1: + %r22 = inttoptr i64 %r14 to ptr + %r23 = getelementptr i8, ptr %r22, i64 32 + %r24 = getelementptr double, ptr %r23, i64 0 + %r25 = ptrtoint ptr %r24 to i64 + store double 0x7FFC000000000001, ptr %r24 + call void @js_string_addref_if_heap_string(double 0x7FFC000000000001) + %r26 = bitcast double 0x7FFC000000000001 to i64 + call void @js_gc_note_slot_layout(i64 %r14, i32 0, i64 %r26) + br label %class_field_set.merge.3 + +class_field_set.fallback.2: + call void @js_class_field_set_fallback(i64 8450987250308612157, i64 %r13, i64 %r17, double 0x7FFC000000000001) + br label %class_field_set.merge.3 + +class_field_set.merge.3: + %r27 = load double, ptr %r7 + %r28 = bitcast double %r27 to i64 + %r29 = and i64 %r28, 281474976710655 + %r30 = load double, ptr @batch_ts_.str.13.handle + %r31 = bitcast double %r30 to i64 + %r32 = and i64 %r31, 281474976710655 + %r33 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + %r34 = bitcast double 0x7FFC000000000001 to i64 + %r35 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r36 = icmp eq i8 %r35, 0 + %r37 = lshr i64 %r28, 48 + %r38 = icmp eq i64 %r37, 32765 + %r39 = icmp ugt i64 %r29, 1048575 + %r40 = and i1 %r38, %r39 + %r41 = and i1 %r40, %r36 + br i1 %r41, label %class_field_inline.deref.7, label %class_field_inline.guardcall.8 + +class_field_set.fast.4: + %r82 = inttoptr i64 %r29 to ptr + %r83 = getelementptr i8, ptr %r82, i64 32 + %r84 = getelementptr double, ptr %r83, i64 1 + %r85 = call double @js_array_numeric_value_to_raw_f64(double 0x7FFC000000000001) + store double %r85, ptr %r84 + br label %class_field_set.merge.6 + +class_field_set.fallback.5: + call void @js_class_field_set_fallback(i64 8450987250308612158, i64 %r28, i64 %r32, double 0x7FFC000000000001) + br label %class_field_set.merge.6 + +class_field_set.merge.6: + %r86 = load double, ptr %r7 + %r87 = bitcast double %r86 to i64 + %r88 = and i64 %r87, 281474976710655 + %r89 = load double, ptr @batch_ts_.str.1.handle + %r90 = bitcast double %r89 to i64 + %r91 = and i64 %r90, 281474976710655 + %r92 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + %r93 = bitcast double 0x7FFC000000000001 to i64 + %r94 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r95 = icmp eq i8 %r94, 0 + %r96 = lshr i64 %r87, 48 + %r97 = icmp eq i64 %r96, 32765 + %r98 = icmp ugt i64 %r88, 1048575 + %r99 = and i1 %r97, %r98 + %r100 = and i1 %r99, %r95 + br i1 %r100, label %class_field_inline.deref.12, label %class_field_inline.guardcall.13 + +class_field_inline.deref.7: + %r42 = inttoptr i64 %r29 to ptr + %r43 = getelementptr i8, ptr %r42, i64 -8 + %r44 = load i8, ptr %r43 + %r45 = icmp eq i8 %r44, 2 + %r46 = getelementptr i8, ptr %r42, i64 -7 + %r47 = load i8, ptr %r46 + %r48 = and i8 %r47, -128 + %r49 = icmp eq i8 %r48, 0 + %r50 = getelementptr i8, ptr %r42, i64 -6 + %r51 = load i16, ptr %r50 + %r52 = load i32, ptr %r42 + %r53 = icmp eq i32 %r52, 1 + %r54 = getelementptr i8, ptr %r42, i64 4 + %r55 = load i32, ptr %r54 + %r56 = icmp eq i32 %r55, 3 + %r57 = getelementptr i8, ptr %r42, i64 12 + %r58 = load i32, ptr %r57 + %r59 = icmp ugt i32 %r58, 1 + %r60 = getelementptr i8, ptr %r42, i64 16 + %r61 = load i64, ptr %r60 + %r62 = icmp eq i64 %r61, %r33 + %r63 = and i1 %r45, %r49 + %r64 = and i1 %r63, %r53 + %r65 = and i1 %r64, %r56 + %r66 = and i1 %r65, %r59 + %r67 = and i1 %r66, %r62 + %r68 = and i16 %r51, 2048 + %r69 = icmp eq i16 %r68, 0 + %r70 = and i1 %r67, %r69 + %r71 = and i16 %r51, 4096 + %r72 = icmp ne i16 %r71, 0 + %r73 = and i1 %r70, %r72 + %r74 = and i16 %r51, 1 + %r75 = icmp eq i16 %r74, 0 + %r76 = and i1 %r73, %r75 + %r77 = and i64 %r34, 9218868437227405312 + %r78 = icmp ne i64 %r77, 9218868437227405312 + %r79 = and i1 %r76, %r78 + br i1 %r79, label %class_field_set.fast.4, label %class_field_inline.guardcall.8 + +class_field_inline.guardcall.8: + %r80 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612158, double %r27, i32 3, i64 %r33, i64 %r32, i32 1, double 0x7FFC000000000001, i32 1) + %r81 = icmp ne i32 %r80, 0 + br i1 %r81, label %class_field_set.fast.4, label %class_field_set.fallback.5 + +class_field_set.fast.9: + %r141 = inttoptr i64 %r88 to ptr + %r142 = getelementptr i8, ptr %r141, i64 32 + %r143 = getelementptr double, ptr %r142, i64 2 + %r144 = call double @js_array_numeric_value_to_raw_f64(double 0x7FFC000000000001) + store double %r144, ptr %r143 + br label %class_field_set.merge.11 + +class_field_set.fallback.10: + call void @js_class_field_set_fallback(i64 8450987250308612159, i64 %r87, i64 %r91, double 0x7FFC000000000001) + br label %class_field_set.merge.11 + +class_field_set.merge.11: + %r145 = load double, ptr %r7 + %r146 = bitcast double %r145 to i64 + %r147 = and i64 %r146, 281474976710655 + %r148 = load double, ptr @batch_ts_.str.3.handle + %r149 = bitcast double %r148 to i64 + %r150 = and i64 %r149, 281474976710655 + %r151 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + %r152 = bitcast double 0x7FFC000000000001 to i64 + %r153 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r154 = icmp eq i8 %r153, 0 + %r155 = lshr i64 %r146, 48 + %r156 = icmp eq i64 %r155, 32765 + %r157 = icmp ugt i64 %r147, 1048575 + %r158 = and i1 %r156, %r157 + %r159 = and i1 %r158, %r154 + br i1 %r159, label %class_field_inline.deref.17, label %class_field_inline.guardcall.18 + +class_field_inline.deref.12: + %r101 = inttoptr i64 %r88 to ptr + %r102 = getelementptr i8, ptr %r101, i64 -8 + %r103 = load i8, ptr %r102 + %r104 = icmp eq i8 %r103, 2 + %r105 = getelementptr i8, ptr %r101, i64 -7 + %r106 = load i8, ptr %r105 + %r107 = and i8 %r106, -128 + %r108 = icmp eq i8 %r107, 0 + %r109 = getelementptr i8, ptr %r101, i64 -6 + %r110 = load i16, ptr %r109 + %r111 = load i32, ptr %r101 + %r112 = icmp eq i32 %r111, 1 + %r113 = getelementptr i8, ptr %r101, i64 4 + %r114 = load i32, ptr %r113 + %r115 = icmp eq i32 %r114, 3 + %r116 = getelementptr i8, ptr %r101, i64 12 + %r117 = load i32, ptr %r116 + %r118 = icmp ugt i32 %r117, 2 + %r119 = getelementptr i8, ptr %r101, i64 16 + %r120 = load i64, ptr %r119 + %r121 = icmp eq i64 %r120, %r92 + %r122 = and i1 %r104, %r108 + %r123 = and i1 %r122, %r112 + %r124 = and i1 %r123, %r115 + %r125 = and i1 %r124, %r118 + %r126 = and i1 %r125, %r121 + %r127 = and i16 %r110, 2048 + %r128 = icmp eq i16 %r127, 0 + %r129 = and i1 %r126, %r128 + %r130 = and i16 %r110, 4096 + %r131 = icmp ne i16 %r130, 0 + %r132 = and i1 %r129, %r131 + %r133 = and i16 %r110, 1 + %r134 = icmp eq i16 %r133, 0 + %r135 = and i1 %r132, %r134 + %r136 = and i64 %r93, 9218868437227405312 + %r137 = icmp ne i64 %r136, 9218868437227405312 + %r138 = and i1 %r135, %r137 + br i1 %r138, label %class_field_set.fast.9, label %class_field_inline.guardcall.13 + +class_field_inline.guardcall.13: + %r139 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612159, double %r86, i32 3, i64 %r92, i64 %r91, i32 2, double 0x7FFC000000000001, i32 1) + %r140 = icmp ne i32 %r139, 0 + br i1 %r140, label %class_field_set.fast.9, label %class_field_set.fallback.10 + +class_field_set.fast.14: + %r200 = inttoptr i64 %r147 to ptr + %r201 = getelementptr i8, ptr %r200, i64 32 + %r202 = getelementptr double, ptr %r201, i64 3 + %r203 = call double @js_array_numeric_value_to_raw_f64(double 0x7FFC000000000001) + store double %r203, ptr %r202 + br label %class_field_set.merge.16 + +class_field_set.fallback.15: + call void @js_class_field_set_fallback(i64 8450987250308612160, i64 %r146, i64 %r150, double 0x7FFC000000000001) + br label %class_field_set.merge.16 + +class_field_set.merge.16: + %r204 = load double, ptr %r7 + %r205 = load double, ptr %r8 + %r206 = bitcast double %r204 to i64 + %r207 = and i64 %r206, 281474976710655 + %r208 = load double, ptr @batch_ts_.str.5.handle + %r209 = bitcast double %r208 to i64 + %r210 = and i64 %r209, 281474976710655 + %r211 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + %r212 = bitcast double %r205 to i64 + %r213 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612161, double %r204, i32 3, i64 %r211, i64 %r210, i32 0, double %r205, i32 0) + %r214 = icmp ne i32 %r213, 0 + br i1 %r214, label %class_field_set.fast.19, label %class_field_set.fallback.20 + +class_field_inline.deref.17: + %r160 = inttoptr i64 %r147 to ptr + %r161 = getelementptr i8, ptr %r160, i64 -8 + %r162 = load i8, ptr %r161 + %r163 = icmp eq i8 %r162, 2 + %r164 = getelementptr i8, ptr %r160, i64 -7 + %r165 = load i8, ptr %r164 + %r166 = and i8 %r165, -128 + %r167 = icmp eq i8 %r166, 0 + %r168 = getelementptr i8, ptr %r160, i64 -6 + %r169 = load i16, ptr %r168 + %r170 = load i32, ptr %r160 + %r171 = icmp eq i32 %r170, 1 + %r172 = getelementptr i8, ptr %r160, i64 4 + %r173 = load i32, ptr %r172 + %r174 = icmp eq i32 %r173, 3 + %r175 = getelementptr i8, ptr %r160, i64 12 + %r176 = load i32, ptr %r175 + %r177 = icmp ugt i32 %r176, 3 + %r178 = getelementptr i8, ptr %r160, i64 16 + %r179 = load i64, ptr %r178 + %r180 = icmp eq i64 %r179, %r151 + %r181 = and i1 %r163, %r167 + %r182 = and i1 %r181, %r171 + %r183 = and i1 %r182, %r174 + %r184 = and i1 %r183, %r177 + %r185 = and i1 %r184, %r180 + %r186 = and i16 %r169, 2048 + %r187 = icmp eq i16 %r186, 0 + %r188 = and i1 %r185, %r187 + %r189 = and i16 %r169, 4096 + %r190 = icmp ne i16 %r189, 0 + %r191 = and i1 %r188, %r190 + %r192 = and i16 %r169, 1 + %r193 = icmp eq i16 %r192, 0 + %r194 = and i1 %r191, %r193 + %r195 = and i64 %r152, 9218868437227405312 + %r196 = icmp ne i64 %r195, 9218868437227405312 + %r197 = and i1 %r194, %r196 + br i1 %r197, label %class_field_set.fast.14, label %class_field_inline.guardcall.18 + +class_field_inline.guardcall.18: + %r198 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612160, double %r145, i32 3, i64 %r151, i64 %r150, i32 3, double 0x7FFC000000000001, i32 1) + %r199 = icmp ne i32 %r198, 0 + br i1 %r199, label %class_field_set.fast.14, label %class_field_set.fallback.15 + +class_field_set.fast.19: + %r215 = inttoptr i64 %r207 to ptr + %r216 = getelementptr i8, ptr %r215, i64 32 + %r217 = getelementptr double, ptr %r216, i64 0 + %r218 = ptrtoint ptr %r217 to i64 + store double %r205, ptr %r217 + call void @js_string_addref_if_heap_string(double %r205) + %r219 = bitcast double %r205 to i64 + call void @js_gc_note_slot_layout(i64 %r207, i32 0, i64 %r219) + call void @js_write_barrier_slot(i64 %r206, i64 %r218, i64 %r219) + br label %class_field_set.merge.21 + +class_field_set.fallback.20: + call void @js_class_field_set_fallback(i64 8450987250308612161, i64 %r206, i64 %r210, double %r205) + br label %class_field_set.merge.21 + +class_field_set.merge.21: + %r220 = load double, ptr %r7 + %r221 = load double, ptr %r9 + %r222 = bitcast double %r220 to i64 + %r223 = and i64 %r222, 281474976710655 + %r224 = load double, ptr @batch_ts_.str.13.handle + %r225 = bitcast double %r224 to i64 + %r226 = and i64 %r225, 281474976710655 + %r227 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + %r228 = bitcast double %r221 to i64 + %r229 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r230 = icmp eq i8 %r229, 0 + %r231 = lshr i64 %r222, 48 + %r232 = icmp eq i64 %r231, 32765 + %r233 = icmp ugt i64 %r223, 1048575 + %r234 = and i1 %r232, %r233 + %r235 = and i1 %r234, %r230 + br i1 %r235, label %class_field_inline.deref.25, label %class_field_inline.guardcall.26 + +class_field_set.fast.22: + %r276 = inttoptr i64 %r223 to ptr + %r277 = getelementptr i8, ptr %r276, i64 32 + %r278 = getelementptr double, ptr %r277, i64 1 + %r279 = call double @js_array_numeric_value_to_raw_f64(double %r221) + store double %r279, ptr %r278 + br label %class_field_set.merge.24 + +class_field_set.fallback.23: + call void @js_class_field_set_fallback(i64 8450987250308612162, i64 %r222, i64 %r226, double %r221) + br label %class_field_set.merge.24 + +class_field_set.merge.24: + %r280 = load double, ptr %r7 + %r281 = load double, ptr %r10 + %r282 = bitcast double %r280 to i64 + %r283 = and i64 %r282, 281474976710655 + %r284 = load double, ptr @batch_ts_.str.1.handle + %r285 = bitcast double %r284 to i64 + %r286 = and i64 %r285, 281474976710655 + %r287 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + %r288 = bitcast double %r281 to i64 + %r289 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r290 = icmp eq i8 %r289, 0 + %r291 = lshr i64 %r282, 48 + %r292 = icmp eq i64 %r291, 32765 + %r293 = icmp ugt i64 %r283, 1048575 + %r294 = and i1 %r292, %r293 + %r295 = and i1 %r294, %r290 + br i1 %r295, label %class_field_inline.deref.30, label %class_field_inline.guardcall.31 + +class_field_inline.deref.25: + %r236 = inttoptr i64 %r223 to ptr + %r237 = getelementptr i8, ptr %r236, i64 -8 + %r238 = load i8, ptr %r237 + %r239 = icmp eq i8 %r238, 2 + %r240 = getelementptr i8, ptr %r236, i64 -7 + %r241 = load i8, ptr %r240 + %r242 = and i8 %r241, -128 + %r243 = icmp eq i8 %r242, 0 + %r244 = getelementptr i8, ptr %r236, i64 -6 + %r245 = load i16, ptr %r244 + %r246 = load i32, ptr %r236 + %r247 = icmp eq i32 %r246, 1 + %r248 = getelementptr i8, ptr %r236, i64 4 + %r249 = load i32, ptr %r248 + %r250 = icmp eq i32 %r249, 3 + %r251 = getelementptr i8, ptr %r236, i64 12 + %r252 = load i32, ptr %r251 + %r253 = icmp ugt i32 %r252, 1 + %r254 = getelementptr i8, ptr %r236, i64 16 + %r255 = load i64, ptr %r254 + %r256 = icmp eq i64 %r255, %r227 + %r257 = and i1 %r239, %r243 + %r258 = and i1 %r257, %r247 + %r259 = and i1 %r258, %r250 + %r260 = and i1 %r259, %r253 + %r261 = and i1 %r260, %r256 + %r262 = and i16 %r245, 2048 + %r263 = icmp eq i16 %r262, 0 + %r264 = and i1 %r261, %r263 + %r265 = and i16 %r245, 4096 + %r266 = icmp ne i16 %r265, 0 + %r267 = and i1 %r264, %r266 + %r268 = and i16 %r245, 1 + %r269 = icmp eq i16 %r268, 0 + %r270 = and i1 %r267, %r269 + %r271 = and i64 %r228, 9218868437227405312 + %r272 = icmp ne i64 %r271, 9218868437227405312 + %r273 = and i1 %r270, %r272 + br i1 %r273, label %class_field_set.fast.22, label %class_field_inline.guardcall.26 + +class_field_inline.guardcall.26: + %r274 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612162, double %r220, i32 3, i64 %r227, i64 %r226, i32 1, double %r221, i32 1) + %r275 = icmp ne i32 %r274, 0 + br i1 %r275, label %class_field_set.fast.22, label %class_field_set.fallback.23 + +class_field_set.fast.27: + %r336 = inttoptr i64 %r283 to ptr + %r337 = getelementptr i8, ptr %r336, i64 32 + %r338 = getelementptr double, ptr %r337, i64 2 + %r339 = call double @js_array_numeric_value_to_raw_f64(double %r281) + store double %r339, ptr %r338 + br label %class_field_set.merge.29 + +class_field_set.fallback.28: + call void @js_class_field_set_fallback(i64 8450987250308612163, i64 %r282, i64 %r286, double %r281) + br label %class_field_set.merge.29 + +class_field_set.merge.29: + %r340 = load double, ptr %r7 + %r341 = load double, ptr %r11 + %r342 = bitcast double %r340 to i64 + %r343 = and i64 %r342, 281474976710655 + %r344 = load double, ptr @batch_ts_.str.3.handle + %r345 = bitcast double %r344 to i64 + %r346 = and i64 %r345, 281474976710655 + %r347 = load i64, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + %r348 = bitcast double %r341 to i64 + %r349 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r350 = icmp eq i8 %r349, 0 + %r351 = lshr i64 %r342, 48 + %r352 = icmp eq i64 %r351, 32765 + %r353 = icmp ugt i64 %r343, 1048575 + %r354 = and i1 %r352, %r353 + %r355 = and i1 %r354, %r350 + br i1 %r355, label %class_field_inline.deref.35, label %class_field_inline.guardcall.36 + +class_field_inline.deref.30: + %r296 = inttoptr i64 %r283 to ptr + %r297 = getelementptr i8, ptr %r296, i64 -8 + %r298 = load i8, ptr %r297 + %r299 = icmp eq i8 %r298, 2 + %r300 = getelementptr i8, ptr %r296, i64 -7 + %r301 = load i8, ptr %r300 + %r302 = and i8 %r301, -128 + %r303 = icmp eq i8 %r302, 0 + %r304 = getelementptr i8, ptr %r296, i64 -6 + %r305 = load i16, ptr %r304 + %r306 = load i32, ptr %r296 + %r307 = icmp eq i32 %r306, 1 + %r308 = getelementptr i8, ptr %r296, i64 4 + %r309 = load i32, ptr %r308 + %r310 = icmp eq i32 %r309, 3 + %r311 = getelementptr i8, ptr %r296, i64 12 + %r312 = load i32, ptr %r311 + %r313 = icmp ugt i32 %r312, 2 + %r314 = getelementptr i8, ptr %r296, i64 16 + %r315 = load i64, ptr %r314 + %r316 = icmp eq i64 %r315, %r287 + %r317 = and i1 %r299, %r303 + %r318 = and i1 %r317, %r307 + %r319 = and i1 %r318, %r310 + %r320 = and i1 %r319, %r313 + %r321 = and i1 %r320, %r316 + %r322 = and i16 %r305, 2048 + %r323 = icmp eq i16 %r322, 0 + %r324 = and i1 %r321, %r323 + %r325 = and i16 %r305, 4096 + %r326 = icmp ne i16 %r325, 0 + %r327 = and i1 %r324, %r326 + %r328 = and i16 %r305, 1 + %r329 = icmp eq i16 %r328, 0 + %r330 = and i1 %r327, %r329 + %r331 = and i64 %r288, 9218868437227405312 + %r332 = icmp ne i64 %r331, 9218868437227405312 + %r333 = and i1 %r330, %r332 + br i1 %r333, label %class_field_set.fast.27, label %class_field_inline.guardcall.31 + +class_field_inline.guardcall.31: + %r334 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612163, double %r280, i32 3, i64 %r287, i64 %r286, i32 2, double %r281, i32 1) + %r335 = icmp ne i32 %r334, 0 + br i1 %r335, label %class_field_set.fast.27, label %class_field_set.fallback.28 + +class_field_set.fast.32: + %r396 = inttoptr i64 %r343 to ptr + %r397 = getelementptr i8, ptr %r396, i64 32 + %r398 = getelementptr double, ptr %r397, i64 3 + %r399 = call double @js_array_numeric_value_to_raw_f64(double %r341) + store double %r399, ptr %r398 + br label %class_field_set.merge.34 + +class_field_set.fallback.33: + call void @js_class_field_set_fallback(i64 8450987250308612164, i64 %r342, i64 %r346, double %r341) + br label %class_field_set.merge.34 + +class_field_set.merge.34: + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double 0x7FFC000000000001 + +class_field_inline.deref.35: + %r356 = inttoptr i64 %r343 to ptr + %r357 = getelementptr i8, ptr %r356, i64 -8 + %r358 = load i8, ptr %r357 + %r359 = icmp eq i8 %r358, 2 + %r360 = getelementptr i8, ptr %r356, i64 -7 + %r361 = load i8, ptr %r360 + %r362 = and i8 %r361, -128 + %r363 = icmp eq i8 %r362, 0 + %r364 = getelementptr i8, ptr %r356, i64 -6 + %r365 = load i16, ptr %r364 + %r366 = load i32, ptr %r356 + %r367 = icmp eq i32 %r366, 1 + %r368 = getelementptr i8, ptr %r356, i64 4 + %r369 = load i32, ptr %r368 + %r370 = icmp eq i32 %r369, 3 + %r371 = getelementptr i8, ptr %r356, i64 12 + %r372 = load i32, ptr %r371 + %r373 = icmp ugt i32 %r372, 3 + %r374 = getelementptr i8, ptr %r356, i64 16 + %r375 = load i64, ptr %r374 + %r376 = icmp eq i64 %r375, %r347 + %r377 = and i1 %r359, %r363 + %r378 = and i1 %r377, %r367 + %r379 = and i1 %r378, %r370 + %r380 = and i1 %r379, %r373 + %r381 = and i1 %r380, %r376 + %r382 = and i16 %r365, 2048 + %r383 = icmp eq i16 %r382, 0 + %r384 = and i1 %r381, %r383 + %r385 = and i16 %r365, 4096 + %r386 = icmp ne i16 %r385, 0 + %r387 = and i1 %r384, %r386 + %r388 = and i16 %r365, 1 + %r389 = icmp eq i16 %r388, 0 + %r390 = and i1 %r387, %r389 + %r391 = and i64 %r348, 9218868437227405312 + %r392 = icmp ne i64 %r391, 9218868437227405312 + %r393 = and i1 %r390, %r392 + br i1 %r393, label %class_field_set.fast.32, label %class_field_inline.guardcall.36 + +class_field_inline.guardcall.36: + %r394 = call i32 @js_typed_feedback_class_field_set_guard(i64 8450987250308612164, double %r340, i32 3, i64 %r347, i64 %r346, i32 3, double %r341, i32 1) + %r395 = icmp ne i32 %r394, 0 + br i1 %r395, label %class_field_set.fast.32, label %class_field_set.fallback.33 +} + +define double @__perry_wrap_perry_fn_batch_ts__buildRows(i64 %this_closure, double %a0, double %a1) { +entry.0: + %r1 = call double @perry_fn_batch_ts__buildRows(double %a0, double %a1) + ret double %r1 +} + +define double @__perry_wrap_perry_fn_batch_ts__shape(i64 %this_closure, double %a0) { +entry.0: + %r1 = call double @perry_fn_batch_ts__shape(double %a0) + ret double %r1 +} + +define double @__perry_wrap_perry_fn_batch_ts__ranked(i64 %this_closure, double %a0) { +entry.0: + %r1 = call double @perry_fn_batch_ts__ranked(double %a0) + ret double %r1 +} + +define double @__perry_wrap_perry_fn_batch_ts__summarize(i64 %this_closure, double %a0) { +entry.0: + %r1 = call double @perry_fn_batch_ts__summarize(double %a0) + ret double %r1 +} + +define double @__perry_wrap_perry_fn_batch_ts__totalsRow(i64 %this_closure, double %a0) { +entry.0: + %r1 = call double @perry_fn_batch_ts__totalsRow(double %a0) + ret double %r1 +} + +define double @__perry_wrap_perry_method_batch_ts__Row__rescore(i64 %this_closure, double %a0) { +entry.0: + %r1 = call double @js_implicit_this_get() + %r2 = call double @perry_method_batch_ts__Row__rescore(double %r1, double %a0) + ret double %r2 +} + +define internal double @__perry_wrap_perry_unknown_func(i64 %this_closure, double %a0, double %a1, double %a2, double %a3, double %a4) { +entry.0: + ret double 0x7FFC000000000001 +} + +define void @batch_ts__init() { +entry.0: + ret void +} + +define i32 @main() { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r8 = alloca i32 + store i32 0, ptr %r8 + %r13 = alloca ptr + %r14 = call ptr @js_inline_arena_state() + store ptr %r14, ptr %r13 + %r54 = alloca double + store double 0x7FFC000000000001, ptr %r54 + %r83 = alloca double + store double 0x7FFC000000000001, ptr %r83 + %r115 = alloca double + store double 0x7FFC000000000001, ptr %r115 + %r168 = alloca double + store double 0x7FFC000000000001, ptr %r168 + %r206 = alloca double + store double 0x7FFC000000000001, ptr %r206 + %r245 = alloca double + store double 0x7FFC000000000001, ptr %r245 + %r246 = alloca i32 + store i32 0, ptr %r246 + %r408 = alloca i32 + store i32 0, ptr %r408 + %r721 = alloca double + store double 0x7FFC000000000001, ptr %r721 + call void @js_gc_init() + call void @js_gc_write_barriers_emitted(i32 1) + call void @perry_macos_bundle_chdir() + call void @__perry_init_strings_batch_ts() + %r3 = call ptr @js_shadow_frame_enter(i32 7) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = ptrtoint ptr @perry_global_batch_ts__1 to i64 + call void @js_gc_register_global_root(i64 %r7) + store i32 40000, ptr %r8 + %r9 = load double, ptr @batch_ts_.str.15.handle + %r10 = load double, ptr @batch_ts_.str.16.handle + %r11 = load double, ptr @batch_ts_.str.17.handle + %r12 = load double, ptr @batch_ts_.str.18.handle + %r15 = load ptr, ptr %r13 + %r16 = getelementptr i8, ptr %r15, i64 8 + %r17 = load i64, ptr %r16 + %r18 = add i64 %r17, 48 + %r19 = getelementptr i8, ptr %r15, i64 16 + %r20 = load i64, ptr %r19 + %r21 = icmp ule i64 %r18, %r20 + br i1 %r21, label %arrlit.fast.1, label %arrlit.slow.2 + +arrlit.fast.1: + store i64 %r18, ptr %r16 + %r22 = load ptr, ptr %r15 + %r23 = getelementptr i8, ptr %r22, i64 %r17 + br label %arrlit.merge.3 + +arrlit.slow.2: + %r24 = call ptr @js_inline_arena_slow_alloc(ptr %r15, i64 48, i64 8) + br label %arrlit.merge.3 + +arrlit.merge.3: + %r25 = phi ptr [ %r23, %arrlit.fast.1 ], [ %r24, %arrlit.slow.2 ] + store i64 207232172545, ptr %r25 + %r26 = getelementptr i8, ptr %r25, i64 8 + store i64 17179869188, ptr %r26 + %r27 = getelementptr i8, ptr %r25, i64 8 + %r28 = ptrtoint ptr %r27 to i64 + %r29 = getelementptr inbounds i8, ptr %r25, i64 16 + store double %r9, ptr %r29 + call void @js_string_addref_if_heap_string(double %r9) + %r30 = bitcast double %r9 to i64 + call void @js_gc_note_slot_layout(i64 %r28, i32 0, i64 %r30) + %r31 = getelementptr inbounds i8, ptr %r25, i64 24 + store double %r10, ptr %r31 + call void @js_string_addref_if_heap_string(double %r10) + %r32 = bitcast double %r10 to i64 + call void @js_gc_note_slot_layout(i64 %r28, i32 1, i64 %r32) + %r33 = getelementptr inbounds i8, ptr %r25, i64 32 + store double %r11, ptr %r33 + call void @js_string_addref_if_heap_string(double %r11) + %r34 = bitcast double %r11 to i64 + call void @js_gc_note_slot_layout(i64 %r28, i32 2, i64 %r34) + %r35 = getelementptr inbounds i8, ptr %r25, i64 40 + store double %r12, ptr %r35 + call void @js_string_addref_if_heap_string(double %r12) + %r36 = bitcast double %r12 to i64 + call void @js_gc_note_slot_layout(i64 %r28, i32 3, i64 %r36) + %r37 = or i64 %r28, 9222527611924643840 + %r38 = bitcast i64 %r37 to double + store double %r38, ptr @perry_global_batch_ts__1 + call void @js_write_barrier_root_nanbox(i64 %r37) + %r39 = load ptr, ptr %r2 + %r40 = icmp eq ptr %r39, null + br i1 %r40, label %ss.slow.4, label %ss.chk_top.5 + +ss.slow.4: + call void @js_shadow_slot_set(i32 0, i64 0) + br label %ss.done.8 + +ss.chk_top.5: + %r41 = getelementptr inbounds i8, ptr %r39, i64 24 + %r42 = load i64, ptr %r41 + %r43 = icmp eq i64 %r42, -1 + br i1 %r43, label %ss.done.8, label %ss.chk_len.6 + +ss.chk_len.6: + %r44 = add i64 %r42, 0 + %r45 = getelementptr inbounds i8, ptr %r39, i64 8 + %r46 = load i64, ptr %r45 + %r47 = icmp ult i64 %r44, %r46 + br i1 %r47, label %ss.store.7, label %ss.done.8 + +ss.store.7: + %r48 = load ptr, ptr %r39 + %r49 = shl i64 %r44, 4 + %r50 = getelementptr inbounds i8, ptr %r48, i64 %r49 + %r51 = getelementptr inbounds i8, ptr %r50, i64 8 + %r52 = load i64, ptr %r51 + %r53 = and i64 %r52, -2 + store i64 0, ptr %r50 + store i64 %r53, ptr %r51 + br label %ss.done.8 + +ss.done.8: + %r55 = call i64 @js_array_alloc(i32 0) + %r56 = or i64 %r55, 9222527611924643840 + %r57 = bitcast i64 %r56 to double + store double %r57, ptr %r54 + %r58 = load ptr, ptr %r2 + %r59 = icmp eq ptr %r58, null + br i1 %r59, label %ss.slow.9, label %ss.chk_top.10 + +ss.slow.9: + call void @js_shadow_slot_bind(i32 1, ptr %r54) + br label %ss.done.13 + +ss.chk_top.10: + %r60 = getelementptr inbounds i8, ptr %r58, i64 24 + %r61 = load i64, ptr %r60 + %r62 = icmp eq i64 %r61, -1 + br i1 %r62, label %ss.done.13, label %ss.chk_len.11 + +ss.chk_len.11: + %r63 = add i64 %r61, 1 + %r64 = getelementptr inbounds i8, ptr %r58, i64 8 + %r65 = load i64, ptr %r64 + %r66 = icmp ult i64 %r63, %r65 + br i1 %r66, label %ss.store.12, label %ss.done.13 + +ss.store.12: + %r67 = load ptr, ptr %r58 + %r68 = shl i64 %r63, 4 + %r69 = getelementptr inbounds i8, ptr %r67, i64 %r68 + %r70 = getelementptr inbounds i8, ptr %r69, i64 8 + %r71 = load i64, ptr %r54 + %r72 = ptrtoint ptr %r54 to i64 + %r73 = and i64 %r72, 1 + %r74 = icmp eq i64 %r73, 0 + %r75 = select i1 %r74, i64 %r72, i64 0 + %r76 = or i64 %r75, 1 + store i64 %r71, ptr %r69 + store i64 %r76, ptr %r70 + %r77 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r78 = icmp ne i32 %r77, 0 + br i1 %r78, label %ss.barrier.14, label %ss.done.13 + +ss.done.13: + %r79 = load i32, ptr %r8 + %r80 = sitofp i32 %r79 to double + %r81 = load double, ptr %r54 + %r82 = call double @perry_fn_batch_ts__buildRows(double %r80, double %r81) + %r84 = load double, ptr %r54 + %r85 = call i64 @js_closure_alloc_singleton(ptr @perry_closure_batch_ts__7) + %r86 = or i64 %r85, 9222527611924643840 + %r87 = bitcast i64 %r86 to double + %r88 = bitcast double %r84 to i64 + %r89 = and i64 %r88, 281474976710655 + %r90 = call i64 @js_validate_array_map_callback(i64 %r89, double %r87) + %r91 = call i64 @js_array_map(i64 %r89, i64 %r90) + %r92 = or i64 %r91, 9222527611924643840 + %r93 = bitcast i64 %r92 to double + store double %r93, ptr %r83 + %r94 = load ptr, ptr %r2 + %r95 = icmp eq ptr %r94, null + br i1 %r95, label %ss.slow.15, label %ss.chk_top.16 + +ss.barrier.14: + call void @js_write_barrier_root_nanbox(i64 %r71) + br label %ss.done.13 + +ss.slow.15: + call void @js_shadow_slot_bind(i32 2, ptr %r83) + br label %ss.done.19 + +ss.chk_top.16: + %r96 = getelementptr inbounds i8, ptr %r94, i64 24 + %r97 = load i64, ptr %r96 + %r98 = icmp eq i64 %r97, -1 + br i1 %r98, label %ss.done.19, label %ss.chk_len.17 + +ss.chk_len.17: + %r99 = add i64 %r97, 2 + %r100 = getelementptr inbounds i8, ptr %r94, i64 8 + %r101 = load i64, ptr %r100 + %r102 = icmp ult i64 %r99, %r101 + br i1 %r102, label %ss.store.18, label %ss.done.19 + +ss.store.18: + %r103 = load ptr, ptr %r94 + %r104 = shl i64 %r99, 4 + %r105 = getelementptr inbounds i8, ptr %r103, i64 %r104 + %r106 = getelementptr inbounds i8, ptr %r105, i64 8 + %r107 = load i64, ptr %r83 + %r108 = ptrtoint ptr %r83 to i64 + %r109 = and i64 %r108, 1 + %r110 = icmp eq i64 %r109, 0 + %r111 = select i1 %r110, i64 %r108, i64 0 + %r112 = or i64 %r111, 1 + store i64 %r107, ptr %r105 + store i64 %r112, ptr %r106 + %r113 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r114 = icmp ne i32 %r113, 0 + br i1 %r114, label %ss.barrier.20, label %ss.done.19 + +ss.done.19: + %r116 = load double, ptr %r83 + %r117 = bitcast double %r116 to i64 + %r118 = and i64 %r117, 281474976710655 + %r119 = call i64 @js_array_slice_values(i64 %r118, double 0.0, double 0x7FFC000000000001) + %r120 = or i64 %r119, 9222527611924643840 + %r121 = bitcast i64 %r120 to double + store double %r121, ptr %r115 + %r122 = load ptr, ptr %r2 + %r123 = icmp eq ptr %r122, null + br i1 %r123, label %ss.slow.21, label %ss.chk_top.22 + +ss.barrier.20: + call void @js_write_barrier_root_nanbox(i64 %r107) + br label %ss.done.19 + +ss.slow.21: + call void @js_shadow_slot_bind(i32 3, ptr %r115) + br label %ss.done.25 + +ss.chk_top.22: + %r124 = getelementptr inbounds i8, ptr %r122, i64 24 + %r125 = load i64, ptr %r124 + %r126 = icmp eq i64 %r125, -1 + br i1 %r126, label %ss.done.25, label %ss.chk_len.23 + +ss.chk_len.23: + %r127 = add i64 %r125, 3 + %r128 = getelementptr inbounds i8, ptr %r122, i64 8 + %r129 = load i64, ptr %r128 + %r130 = icmp ult i64 %r127, %r129 + br i1 %r130, label %ss.store.24, label %ss.done.25 + +ss.store.24: + %r131 = load ptr, ptr %r122 + %r132 = shl i64 %r127, 4 + %r133 = getelementptr inbounds i8, ptr %r131, i64 %r132 + %r134 = getelementptr inbounds i8, ptr %r133, i64 8 + %r135 = load i64, ptr %r115 + %r136 = ptrtoint ptr %r115 to i64 + %r137 = and i64 %r136, 1 + %r138 = icmp eq i64 %r137, 0 + %r139 = select i1 %r138, i64 %r136, i64 0 + %r140 = or i64 %r139, 1 + store i64 %r135, ptr %r133 + store i64 %r140, ptr %r134 + %r141 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r142 = icmp ne i32 %r141, 0 + br i1 %r142, label %ss.barrier.26, label %ss.done.25 + +ss.done.25: + %r143 = load ptr, ptr %r2 + %r144 = icmp eq ptr %r143, null + br i1 %r144, label %ss.slow.27, label %ss.chk_top.28 + +ss.barrier.26: + call void @js_write_barrier_root_nanbox(i64 %r135) + br label %ss.done.25 + +ss.slow.27: + call void @js_shadow_slot_set(i32 2, i64 0) + br label %ss.done.31 + +ss.chk_top.28: + %r145 = getelementptr inbounds i8, ptr %r143, i64 24 + %r146 = load i64, ptr %r145 + %r147 = icmp eq i64 %r146, -1 + br i1 %r147, label %ss.done.31, label %ss.chk_len.29 + +ss.chk_len.29: + %r148 = add i64 %r146, 2 + %r149 = getelementptr inbounds i8, ptr %r143, i64 8 + %r150 = load i64, ptr %r149 + %r151 = icmp ult i64 %r148, %r150 + br i1 %r151, label %ss.store.30, label %ss.done.31 + +ss.store.30: + %r152 = load ptr, ptr %r143 + %r153 = shl i64 %r148, 4 + %r154 = getelementptr inbounds i8, ptr %r152, i64 %r153 + %r155 = getelementptr inbounds i8, ptr %r154, i64 8 + %r156 = load i64, ptr %r155 + %r157 = and i64 %r156, -2 + store i64 0, ptr %r154 + store i64 %r157, ptr %r155 + br label %ss.done.31 + +ss.done.31: + %r158 = load double, ptr %r115 + %r159 = call i64 @js_closure_alloc_singleton(ptr @perry_closure_batch_ts__9) + %r160 = or i64 %r159, 9222527611924643840 + %r161 = bitcast i64 %r160 to double + %r162 = bitcast double %r158 to i64 + %r163 = and i64 %r162, 281474976710655 + %r164 = call i64 @js_validate_array_comparator(double %r161) + %r165 = call i64 @js_array_sort_with_comparator(i64 %r163, i64 %r164) + %r166 = or i64 %r165, 9222527611924643840 + %r167 = bitcast i64 %r166 to double + %r169 = load double, ptr %r115 + store double %r169, ptr %r168 + %r170 = load ptr, ptr %r2 + %r171 = icmp eq ptr %r170, null + br i1 %r171, label %ss.slow.32, label %ss.chk_top.33 + +ss.slow.32: + call void @js_shadow_slot_bind(i32 4, ptr %r168) + br label %ss.done.36 + +ss.chk_top.33: + %r172 = getelementptr inbounds i8, ptr %r170, i64 24 + %r173 = load i64, ptr %r172 + %r174 = icmp eq i64 %r173, -1 + br i1 %r174, label %ss.done.36, label %ss.chk_len.34 + +ss.chk_len.34: + %r175 = add i64 %r173, 4 + %r176 = getelementptr inbounds i8, ptr %r170, i64 8 + %r177 = load i64, ptr %r176 + %r178 = icmp ult i64 %r175, %r177 + br i1 %r178, label %ss.store.35, label %ss.done.36 + +ss.store.35: + %r179 = load ptr, ptr %r170 + %r180 = shl i64 %r175, 4 + %r181 = getelementptr inbounds i8, ptr %r179, i64 %r180 + %r182 = getelementptr inbounds i8, ptr %r181, i64 8 + %r183 = load i64, ptr %r168 + %r184 = ptrtoint ptr %r168 to i64 + %r185 = and i64 %r184, 1 + %r186 = icmp eq i64 %r185, 0 + %r187 = select i1 %r186, i64 %r184, i64 0 + %r188 = or i64 %r187, 1 + store i64 %r183, ptr %r181 + store i64 %r188, ptr %r182 + %r189 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r190 = icmp ne i32 %r189, 0 + br i1 %r190, label %ss.barrier.37, label %ss.done.36 + +ss.done.36: + %r191 = load ptr, ptr %r2 + %r192 = icmp eq ptr %r191, null + br i1 %r192, label %ss.slow.38, label %ss.chk_top.39 + +ss.barrier.37: + call void @js_write_barrier_root_nanbox(i64 %r183) + br label %ss.done.36 + +ss.slow.38: + call void @js_shadow_slot_set(i32 3, i64 0) + br label %ss.done.42 + +ss.chk_top.39: + %r193 = getelementptr inbounds i8, ptr %r191, i64 24 + %r194 = load i64, ptr %r193 + %r195 = icmp eq i64 %r194, -1 + br i1 %r195, label %ss.done.42, label %ss.chk_len.40 + +ss.chk_len.40: + %r196 = add i64 %r194, 3 + %r197 = getelementptr inbounds i8, ptr %r191, i64 8 + %r198 = load i64, ptr %r197 + %r199 = icmp ult i64 %r196, %r198 + br i1 %r199, label %ss.store.41, label %ss.done.42 + +ss.store.41: + %r200 = load ptr, ptr %r191 + %r201 = shl i64 %r196, 4 + %r202 = getelementptr inbounds i8, ptr %r200, i64 %r201 + %r203 = getelementptr inbounds i8, ptr %r202, i64 8 + %r204 = load i64, ptr %r203 + %r205 = and i64 %r204, -2 + store i64 0, ptr %r202 + store i64 %r205, ptr %r203 + br label %ss.done.42 + +ss.done.42: + %r207 = load double, ptr %r54 + %r208 = call double @perry_fn_batch_ts__summarize(double %r207) + store double %r208, ptr %r206 + %r209 = load ptr, ptr %r2 + %r210 = icmp eq ptr %r209, null + br i1 %r210, label %ss.slow.43, label %ss.chk_top.44 + +ss.slow.43: + call void @js_shadow_slot_bind(i32 5, ptr %r206) + br label %ss.done.47 + +ss.chk_top.44: + %r211 = getelementptr inbounds i8, ptr %r209, i64 24 + %r212 = load i64, ptr %r211 + %r213 = icmp eq i64 %r212, -1 + br i1 %r213, label %ss.done.47, label %ss.chk_len.45 + +ss.chk_len.45: + %r214 = add i64 %r212, 5 + %r215 = getelementptr inbounds i8, ptr %r209, i64 8 + %r216 = load i64, ptr %r215 + %r217 = icmp ult i64 %r214, %r216 + br i1 %r217, label %ss.store.46, label %ss.done.47 + +ss.store.46: + %r218 = load ptr, ptr %r209 + %r219 = shl i64 %r214, 4 + %r220 = getelementptr inbounds i8, ptr %r218, i64 %r219 + %r221 = getelementptr inbounds i8, ptr %r220, i64 8 + %r222 = load i64, ptr %r206 + %r223 = ptrtoint ptr %r206 to i64 + %r224 = and i64 %r223, 1 + %r225 = icmp eq i64 %r224, 0 + %r226 = select i1 %r225, i64 %r223, i64 0 + %r227 = or i64 %r226, 1 + store i64 %r222, ptr %r220 + store i64 %r227, ptr %r221 + %r228 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r229 = icmp ne i32 %r228, 0 + br i1 %r229, label %ss.barrier.48, label %ss.done.47 + +ss.done.47: + %r230 = load ptr, ptr %r2 + %r231 = icmp eq ptr %r230, null + br i1 %r231, label %ss.slow.49, label %ss.chk_top.50 + +ss.barrier.48: + call void @js_write_barrier_root_nanbox(i64 %r222) + br label %ss.done.47 + +ss.slow.49: + call void @js_shadow_slot_set(i32 1, i64 0) + br label %ss.done.53 + +ss.chk_top.50: + %r232 = getelementptr inbounds i8, ptr %r230, i64 24 + %r233 = load i64, ptr %r232 + %r234 = icmp eq i64 %r233, -1 + br i1 %r234, label %ss.done.53, label %ss.chk_len.51 + +ss.chk_len.51: + %r235 = add i64 %r233, 1 + %r236 = getelementptr inbounds i8, ptr %r230, i64 8 + %r237 = load i64, ptr %r236 + %r238 = icmp ult i64 %r235, %r237 + br i1 %r238, label %ss.store.52, label %ss.done.53 + +ss.store.52: + %r239 = load ptr, ptr %r230 + %r240 = shl i64 %r235, 4 + %r241 = getelementptr inbounds i8, ptr %r239, i64 %r240 + %r242 = getelementptr inbounds i8, ptr %r241, i64 8 + %r243 = load i64, ptr %r242 + %r244 = and i64 %r243, -2 + store i64 0, ptr %r241 + store i64 %r244, ptr %r242 + br label %ss.done.53 + +ss.done.53: + store double 0.0, ptr %r245 + store i32 0, ptr %r246 + br label %for.cond.54 + +for.cond.54: + %r247 = load i32, ptr %r246 + %r248 = sitofp i32 %r247 to double + %r249 = fcmp olt double %r248, 16.0 + %r250 = select i1 %r249, i64 9222246136947933188, i64 9222246136947933187 + %r251 = bitcast i64 %r250 to double + %r252 = icmp eq i64 %r250, 9222246136947933188 + br i1 %r252, label %for.body.55, label %for.exit.57 + +for.body.55: + %r253 = load double, ptr %r245 + %r254 = load double, ptr %r168 + %r255 = load i32, ptr %r246 + %r256 = bitcast double %r254 to i64 + %r257 = and i64 %r256, 281474976710655 + %r258 = lshr i64 %r256, 48 + %r259 = icmp eq i64 %r258, 32765 + %r260 = icmp ugt i64 %r257, 1048575 + %r261 = and i1 %r259, %r260 + br i1 %r261, label %arr.guard.deref.61, label %arr.fallback.59 + +for.update.56: + %r389 = load i32, ptr %r246 + %r390 = add i32 %r389, 1 + store i32 %r390, ptr %r246 + %r391 = sitofp i32 %r389 to double + %r392 = sitofp i32 %r390 to double + br label %for.cond.54 + +for.exit.57: + %r393 = load ptr, ptr %r2 + %r394 = icmp eq ptr %r393, null + br i1 %r394, label %ss.slow.75, label %ss.chk_top.76 + +arr.fast.58: + %r300 = bitcast double %r254 to i64 + %r301 = and i64 %r300, 281474976710655 + %r302 = zext i32 %r255 to i64 + %r303 = shl i64 %r302, 3 + %r304 = add i64 %r303, 8 + %r305 = add i64 %r301, %r304 + %r306 = inttoptr i64 %r305 to ptr + %r307 = load double, ptr %r306 + %r308 = bitcast double %r307 to i64 + %r309 = icmp eq i64 %r308, 9222246136947933200 + %r310 = bitcast i64 9222246136947933185 to double + %r311 = select i1 %r309, double %r310, double %r307 + br label %arr.merge.60 + +arr.fallback.59: + %r298 = sitofp i32 %r255 to double + %r299 = call double @js_typed_feedback_array_index_get_fallback_boxed(i64 8450987250308612165, double %r254, double %r298) + br label %arr.merge.60 + +arr.merge.60: + %r312 = phi double [ %r311, %arr.fast.58 ], [ %r299, %arr.fallback.59 ] + %r313 = bitcast double %r312 to i64 + %r314 = and i64 %r313, 281474976710655 + %r315 = load double, ptr @batch_ts_.str.11.handle + %r316 = bitcast double %r315 to i64 + %r317 = and i64 %r316, 281474976710655 + %r318 = lshr i64 %r313, 48 + %r319 = icmp eq i64 %r318, 32761 + %r320 = icmp eq i64 %r318, 32766 + %r321 = and i64 %r318, 65533 + %r322 = icmp eq i64 %r321, 32765 + br i1 %r319, label %pget.recv_sso.62, label %pget.check_class_ref.68 + +arr.guard.deref.61: + %r262 = bitcast double %r254 to i64 + %r263 = and i64 %r262, 281474976710655 + %r264 = sub i64 %r263, 8 + %r265 = inttoptr i64 %r264 to ptr + %r266 = load i8, ptr %r265 + %r267 = icmp eq i8 %r266, 1 + %r268 = sub i64 %r263, 7 + %r269 = inttoptr i64 %r268 to ptr + %r270 = load i8, ptr %r269 + %r271 = and i8 %r270, 128 + %r272 = icmp eq i8 %r271, 0 + %r273 = sub i64 %r263, 6 + %r274 = inttoptr i64 %r273 to ptr + %r275 = load i16, ptr %r274 + %r276 = and i16 %r275, 1024 + %r277 = icmp eq i16 %r276, 0 + %r278 = load volatile i8, ptr @PERRY_ARRAY_INDEX_FAST_PATH_INVALIDATED + %r279 = icmp eq i8 %r278, 0 + %r280 = inttoptr i64 %r263 to ptr + %r281 = load i32, ptr %r280 + %r282 = getelementptr i8, ptr %r280, i64 4 + %r283 = load i32, ptr %r282 + %r284 = icmp slt i32 %r255, 0 + %r285 = icmp eq i1 %r284, false + %r286 = icmp ult i32 %r255, %r281 + %r287 = icmp ule i32 %r281, 16000000 + %r288 = icmp ule i32 %r283, 16000000 + %r289 = icmp ule i32 %r281, %r283 + %r290 = and i1 %r267, %r272 + %r291 = and i1 %r290, %r277 + %r292 = and i1 %r291, %r279 + %r293 = and i1 %r292, %r285 + %r294 = and i1 %r293, %r286 + %r295 = and i1 %r294, %r287 + %r296 = and i1 %r295, %r288 + %r297 = and i1 %r296, %r289 + br i1 %r297, label %arr.fast.58, label %arr.fallback.59 + +pget.recv_sso.62: + %r386 = call double @js_object_get_field_by_name_f64(i64 %r313, i64 %r317) + br label %pget.recv_merge.66 + +pget.recv_ok.63: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612166, i64 %r314, i64 %r317) + %r324 = icmp ugt i64 %r314, 1048575 + %r325 = ptrtoint ptr @perry_ic_71 to i64 + %r326 = select i1 %r324, i64 %r314, i64 %r325 + %r327 = sub i64 %r326, 8 + %r328 = inttoptr i64 %r327 to ptr + %r329 = load i8, ptr %r328 + %r330 = icmp eq i8 %r329, 2 + %r331 = and i1 %r324, %r330 + %r332 = add i64 %r326, 12 + %r333 = inttoptr i64 %r332 to ptr + %r334 = load i32, ptr %r333 + %r335 = icmp eq i32 %r334, 1129268819 + %r336 = xor i1 %r335, true + %r337 = and i1 %r331, %r336 + %r338 = inttoptr i64 %r326 to ptr + %r339 = load i32, ptr %r338 + %r340 = icmp eq i32 %r339, 1 + %r341 = and i1 %r337, %r340 + %r342 = sub i64 %r326, 6 + %r343 = inttoptr i64 %r342 to ptr + %r344 = load i16, ptr %r343 + %r345 = and i16 %r344, 2048 + %r346 = icmp eq i16 %r345, 0 + %r347 = and i1 %r341, %r346 + %r348 = add i64 %r326, 16 + %r349 = inttoptr i64 %r348 to ptr + %r350 = load i64, ptr %r349 + %r351 = add i64 %r326, 8 + %r352 = inttoptr i64 %r351 to ptr + %r353 = load i32, ptr %r352 + %r354 = add i32 %r353, -2147483648 + %r355 = icmp ult i32 %r354, 1073741824 + %r356 = zext i32 %r353 to i64 + %r357 = or i64 %r356, 4611686018427387904 + %r358 = select i1 %r355, i64 %r357, i64 %r350 + %r359 = getelementptr i64, ptr @perry_ic_71, i64 0 + %r360 = load i64, ptr %r359 + %r361 = icmp eq i64 %r358, %r360 + %r362 = icmp ne i64 %r358, 0 + %r363 = and i1 %r347, %r361 + %r364 = and i1 %r363, %r362 + br i1 %r364, label %pic.hit.69, label %pic.miss.70 + +pget.recv_bad.64: + %r381 = icmp eq i64 %r313, 9222246136947933185 + %r382 = icmp eq i64 %r313, 9222246136947933186 + %r383 = or i1 %r381, %r382 + br i1 %r383, label %pget.throw_nullish.73, label %pget.recv_undef_return.74 + +pget.recv_class_ref.65: + %r323 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612166, i64 %r313, i64 %r317) + br label %pget.recv_merge.66 + +pget.recv_merge.66: + %r387 = phi double [ %r380, %pic.merge.71 ], [ %r385, %pget.recv_undef_return.74 ], [ %r386, %pget.recv_sso.62 ], [ %r323, %pget.recv_class_ref.65 ] + %r388 = call double @js_dynamic_string_or_number_add(double %r253, double %r387) + store double %r388, ptr %r245 + br label %for.update.56 + +pget.check_ptr.67: + br i1 %r322, label %pget.recv_ok.63, label %pget.recv_bad.64 + +pget.check_class_ref.68: + br i1 %r320, label %pget.recv_class_ref.65, label %pget.check_ptr.67 + +pic.hit.69: + %r365 = getelementptr i64, ptr @perry_ic_71, i64 1 + %r366 = load i64, ptr %r365 + %r367 = add i64 %r326, 12 + %r368 = inttoptr i64 %r367 to ptr + %r369 = load i32, ptr %r368 + %r370 = zext i32 %r369 to i64 + %r371 = icmp ult i64 %r370, 4 + %r372 = select i1 %r371, i64 4, i64 %r370 + %r373 = icmp ult i64 %r366, %r372 + br i1 %r373, label %pic.hit.load.72, label %pic.miss.70 + +pic.miss.70: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612166) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612166) + %r379 = call double @js_object_get_field_ic_miss(i64 %r314, i64 %r317, ptr @perry_ic_71) + br label %pic.merge.71 + +pic.merge.71: + %r380 = phi double [ %r378, %pic.hit.load.72 ], [ %r379, %pic.miss.70 ] + br label %pget.recv_merge.66 + +pic.hit.load.72: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612166) + %r374 = shl i64 %r366, 3 + %r375 = add i64 %r314, 32 + %r376 = add i64 %r375, %r374 + %r377 = inttoptr i64 %r376 to ptr + %r378 = load double, ptr %r377 + br label %pic.merge.71 + +pget.throw_nullish.73: + %r384 = zext i1 %r382 to i32 + call void @js_throw_type_error_property_access(i32 %r384, ptr @batch_ts_.str.11.bytes, i64 5) + unreachable + +pget.recv_undef_return.74: + %r385 = call double @js_object_get_field_by_name_f64(i64 %r313, i64 %r317) + br label %pget.recv_merge.66 + +ss.slow.75: + call void @js_shadow_slot_set(i32 4, i64 0) + br label %ss.done.79 + +ss.chk_top.76: + %r395 = getelementptr inbounds i8, ptr %r393, i64 24 + %r396 = load i64, ptr %r395 + %r397 = icmp eq i64 %r396, -1 + br i1 %r397, label %ss.done.79, label %ss.chk_len.77 + +ss.chk_len.77: + %r398 = add i64 %r396, 4 + %r399 = getelementptr inbounds i8, ptr %r393, i64 8 + %r400 = load i64, ptr %r399 + %r401 = icmp ult i64 %r398, %r400 + br i1 %r401, label %ss.store.78, label %ss.done.79 + +ss.store.78: + %r402 = load ptr, ptr %r393 + %r403 = shl i64 %r398, 4 + %r404 = getelementptr inbounds i8, ptr %r402, i64 %r403 + %r405 = getelementptr inbounds i8, ptr %r404, i64 8 + %r406 = load i64, ptr %r405 + %r407 = and i64 %r406, -2 + store i64 0, ptr %r404 + store i64 %r407, ptr %r405 + br label %ss.done.79 + +ss.done.79: + store i32 0, ptr %r408 + br label %for.cond.80 + +for.cond.80: + %r409 = load i32, ptr %r408 + %r410 = sitofp i32 %r409 to double + %r411 = load double, ptr %r206 + %r412 = bitcast double %r411 to i64 + %r413 = and i64 %r412, 281474976710655 + %r414 = lshr i64 %r412, 48 + %r415 = and i64 %r414, 65533 + %r416 = icmp eq i64 %r415, 32765 + %r417 = icmp ugt i64 %r413, 1048575 + %r418 = and i1 %r416, %r417 + br i1 %r418, label %plen.check_gc.84, label %plen.slow.86 + +for.body.81: + %r442 = load double, ptr %r245 + %r443 = load double, ptr %r206 + %r444 = load i32, ptr %r408 + %r445 = bitcast double %r443 to i64 + %r446 = and i64 %r445, 281474976710655 + %r447 = lshr i64 %r445, 48 + %r448 = icmp eq i64 %r447, 32765 + %r449 = icmp ugt i64 %r446, 1048575 + %r450 = and i1 %r448, %r449 + br i1 %r450, label %arr.guard.deref.91, label %arr.fallback.89 + +for.update.82: + %r717 = load i32, ptr %r408 + %r718 = add i32 %r717, 1 + store i32 %r718, ptr %r408 + %r719 = sitofp i32 %r717 to double + %r720 = sitofp i32 %r718 to double + br label %for.cond.80 + +for.exit.83: + %r722 = load double, ptr %r206 + %r723 = call double @perry_fn_batch_ts__totalsRow(double %r722) + store double %r723, ptr %r721 + %r724 = load ptr, ptr %r2 + %r725 = icmp eq ptr %r724, null + br i1 %r725, label %ss.slow.122, label %ss.chk_top.123 + +plen.check_gc.84: + %r419 = sub i64 %r413, 8 + %r420 = inttoptr i64 %r419 to ptr + %r421 = load i8, ptr %r420 + %r422 = icmp eq i8 %r421, 1 + %r423 = icmp eq i8 %r421, 3 + %r424 = or i1 %r422, %r423 + %r425 = sub i64 %r413, 7 + %r426 = inttoptr i64 %r425 to ptr + %r427 = load i8, ptr %r426 + %r428 = and i8 %r427, 128 + %r429 = icmp eq i8 %r428, 0 + %r430 = and i1 %r424, %r429 + br i1 %r430, label %plen.fast.85, label %plen.slow.86 + +plen.fast.85: + %r431 = icmp ult i64 %r413, 4096 + %r432 = inttoptr i64 %r413 to ptr + %r433 = select i1 %r431, ptr @perry_null_guard_zero, ptr %r432 + %r434 = load i32, ptr %r433 + %r435 = uitofp i32 %r434 to double + br label %plen.merge.87 + +plen.slow.86: + %r436 = call double @js_value_length_f64(double %r411) + br label %plen.merge.87 + +plen.merge.87: + %r437 = phi double [ %r435, %plen.fast.85 ], [ %r436, %plen.slow.86 ] + %r438 = fcmp olt double %r410, %r437 + %r439 = select i1 %r438, i64 9222246136947933188, i64 9222246136947933187 + %r440 = bitcast i64 %r439 to double + %r441 = icmp eq i64 %r439, 9222246136947933188 + br i1 %r441, label %for.body.81, label %for.exit.83 + +arr.fast.88: + %r489 = bitcast double %r443 to i64 + %r490 = and i64 %r489, 281474976710655 + %r491 = zext i32 %r444 to i64 + %r492 = shl i64 %r491, 3 + %r493 = add i64 %r492, 8 + %r494 = add i64 %r490, %r493 + %r495 = inttoptr i64 %r494 to ptr + %r496 = load double, ptr %r495 + %r497 = bitcast double %r496 to i64 + %r498 = icmp eq i64 %r497, 9222246136947933200 + %r499 = bitcast i64 9222246136947933185 to double + %r500 = select i1 %r498, double %r499, double %r496 + br label %arr.merge.90 + +arr.fallback.89: + %r487 = sitofp i32 %r444 to double + %r488 = call double @js_typed_feedback_array_index_get_fallback_boxed(i64 8450987250308612168, double %r443, double %r487) + br label %arr.merge.90 + +arr.merge.90: + %r501 = phi double [ %r500, %arr.fast.88 ], [ %r488, %arr.fallback.89 ] + %r502 = bitcast double %r501 to i64 + %r503 = and i64 %r502, 281474976710655 + %r504 = load double, ptr @batch_ts_.str.13.handle + %r505 = bitcast double %r504 to i64 + %r506 = and i64 %r505, 281474976710655 + %r507 = lshr i64 %r502, 48 + %r508 = icmp eq i64 %r507, 32761 + %r509 = icmp eq i64 %r507, 32766 + %r510 = and i64 %r507, 65533 + %r511 = icmp eq i64 %r510, 32765 + br i1 %r508, label %pget.recv_sso.92, label %pget.check_class_ref.98 + +arr.guard.deref.91: + %r451 = bitcast double %r443 to i64 + %r452 = and i64 %r451, 281474976710655 + %r453 = sub i64 %r452, 8 + %r454 = inttoptr i64 %r453 to ptr + %r455 = load i8, ptr %r454 + %r456 = icmp eq i8 %r455, 1 + %r457 = sub i64 %r452, 7 + %r458 = inttoptr i64 %r457 to ptr + %r459 = load i8, ptr %r458 + %r460 = and i8 %r459, 128 + %r461 = icmp eq i8 %r460, 0 + %r462 = sub i64 %r452, 6 + %r463 = inttoptr i64 %r462 to ptr + %r464 = load i16, ptr %r463 + %r465 = and i16 %r464, 1024 + %r466 = icmp eq i16 %r465, 0 + %r467 = load volatile i8, ptr @PERRY_ARRAY_INDEX_FAST_PATH_INVALIDATED + %r468 = icmp eq i8 %r467, 0 + %r469 = inttoptr i64 %r452 to ptr + %r470 = load i32, ptr %r469 + %r471 = getelementptr i8, ptr %r469, i64 4 + %r472 = load i32, ptr %r471 + %r473 = icmp slt i32 %r444, 0 + %r474 = icmp eq i1 %r473, false + %r475 = icmp ult i32 %r444, %r470 + %r476 = icmp ule i32 %r470, 16000000 + %r477 = icmp ule i32 %r472, 16000000 + %r478 = icmp ule i32 %r470, %r472 + %r479 = and i1 %r456, %r461 + %r480 = and i1 %r479, %r466 + %r481 = and i1 %r480, %r468 + %r482 = and i1 %r481, %r474 + %r483 = and i1 %r482, %r475 + %r484 = and i1 %r483, %r476 + %r485 = and i1 %r484, %r477 + %r486 = and i1 %r485, %r478 + br i1 %r486, label %arr.fast.88, label %arr.fallback.89 + +pget.recv_sso.92: + %r575 = call double @js_object_get_field_by_name_f64(i64 %r502, i64 %r506) + br label %pget.recv_merge.96 + +pget.recv_ok.93: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612169, i64 %r503, i64 %r506) + %r513 = icmp ugt i64 %r503, 1048575 + %r514 = ptrtoint ptr @perry_ic_74 to i64 + %r515 = select i1 %r513, i64 %r503, i64 %r514 + %r516 = sub i64 %r515, 8 + %r517 = inttoptr i64 %r516 to ptr + %r518 = load i8, ptr %r517 + %r519 = icmp eq i8 %r518, 2 + %r520 = and i1 %r513, %r519 + %r521 = add i64 %r515, 12 + %r522 = inttoptr i64 %r521 to ptr + %r523 = load i32, ptr %r522 + %r524 = icmp eq i32 %r523, 1129268819 + %r525 = xor i1 %r524, true + %r526 = and i1 %r520, %r525 + %r527 = inttoptr i64 %r515 to ptr + %r528 = load i32, ptr %r527 + %r529 = icmp eq i32 %r528, 1 + %r530 = and i1 %r526, %r529 + %r531 = sub i64 %r515, 6 + %r532 = inttoptr i64 %r531 to ptr + %r533 = load i16, ptr %r532 + %r534 = and i16 %r533, 2048 + %r535 = icmp eq i16 %r534, 0 + %r536 = and i1 %r530, %r535 + %r537 = add i64 %r515, 16 + %r538 = inttoptr i64 %r537 to ptr + %r539 = load i64, ptr %r538 + %r540 = add i64 %r515, 8 + %r541 = inttoptr i64 %r540 to ptr + %r542 = load i32, ptr %r541 + %r543 = add i32 %r542, -2147483648 + %r544 = icmp ult i32 %r543, 1073741824 + %r545 = zext i32 %r542 to i64 + %r546 = or i64 %r545, 4611686018427387904 + %r547 = select i1 %r544, i64 %r546, i64 %r539 + %r548 = getelementptr i64, ptr @perry_ic_74, i64 0 + %r549 = load i64, ptr %r548 + %r550 = icmp eq i64 %r547, %r549 + %r551 = icmp ne i64 %r547, 0 + %r552 = and i1 %r536, %r550 + %r553 = and i1 %r552, %r551 + br i1 %r553, label %pic.hit.99, label %pic.miss.100 + +pget.recv_bad.94: + %r570 = icmp eq i64 %r502, 9222246136947933185 + %r571 = icmp eq i64 %r502, 9222246136947933186 + %r572 = or i1 %r570, %r571 + br i1 %r572, label %pget.throw_nullish.103, label %pget.recv_undef_return.104 + +pget.recv_class_ref.95: + %r512 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612169, i64 %r502, i64 %r506) + br label %pget.recv_merge.96 + +pget.recv_merge.96: + %r576 = phi double [ %r569, %pic.merge.101 ], [ %r574, %pget.recv_undef_return.104 ], [ %r575, %pget.recv_sso.92 ], [ %r512, %pget.recv_class_ref.95 ] + %r577 = call double @js_dynamic_string_or_number_add(double %r442, double %r576) + %r578 = bitcast double %r577 to i64 + %r579 = call i32 @js_gc_temp_root_push(i64 %r578) + %r580 = load double, ptr %r206 + %r581 = load i32, ptr %r408 + %r582 = bitcast double %r580 to i64 + %r583 = and i64 %r582, 281474976710655 + %r584 = lshr i64 %r582, 48 + %r585 = icmp eq i64 %r584, 32765 + %r586 = icmp ugt i64 %r583, 1048575 + %r587 = and i1 %r585, %r586 + br i1 %r587, label %arr.guard.deref.108, label %arr.fallback.106 + +pget.check_ptr.97: + br i1 %r511, label %pget.recv_ok.93, label %pget.recv_bad.94 + +pget.check_class_ref.98: + br i1 %r509, label %pget.recv_class_ref.95, label %pget.check_ptr.97 + +pic.hit.99: + %r554 = getelementptr i64, ptr @perry_ic_74, i64 1 + %r555 = load i64, ptr %r554 + %r556 = add i64 %r515, 12 + %r557 = inttoptr i64 %r556 to ptr + %r558 = load i32, ptr %r557 + %r559 = zext i32 %r558 to i64 + %r560 = icmp ult i64 %r559, 4 + %r561 = select i1 %r560, i64 4, i64 %r559 + %r562 = icmp ult i64 %r555, %r561 + br i1 %r562, label %pic.hit.load.102, label %pic.miss.100 + +pic.miss.100: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612169) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612169) + %r568 = call double @js_object_get_field_ic_miss(i64 %r503, i64 %r506, ptr @perry_ic_74) + br label %pic.merge.101 + +pic.merge.101: + %r569 = phi double [ %r567, %pic.hit.load.102 ], [ %r568, %pic.miss.100 ] + br label %pget.recv_merge.96 + +pic.hit.load.102: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612169) + %r563 = shl i64 %r555, 3 + %r564 = add i64 %r503, 32 + %r565 = add i64 %r564, %r563 + %r566 = inttoptr i64 %r565 to ptr + %r567 = load double, ptr %r566 + br label %pic.merge.101 + +pget.throw_nullish.103: + %r573 = zext i1 %r571 to i32 + call void @js_throw_type_error_property_access(i32 %r573, ptr @batch_ts_.str.13.bytes, i64 5) + unreachable + +pget.recv_undef_return.104: + %r574 = call double @js_object_get_field_by_name_f64(i64 %r502, i64 %r506) + br label %pget.recv_merge.96 + +arr.fast.105: + %r626 = bitcast double %r580 to i64 + %r627 = and i64 %r626, 281474976710655 + %r628 = zext i32 %r581 to i64 + %r629 = shl i64 %r628, 3 + %r630 = add i64 %r629, 8 + %r631 = add i64 %r627, %r630 + %r632 = inttoptr i64 %r631 to ptr + %r633 = load double, ptr %r632 + %r634 = bitcast double %r633 to i64 + %r635 = icmp eq i64 %r634, 9222246136947933200 + %r636 = bitcast i64 9222246136947933185 to double + %r637 = select i1 %r635, double %r636, double %r633 + br label %arr.merge.107 + +arr.fallback.106: + %r624 = sitofp i32 %r581 to double + %r625 = call double @js_typed_feedback_array_index_get_fallback_boxed(i64 8450987250308612171, double %r580, double %r624) + br label %arr.merge.107 + +arr.merge.107: + %r638 = phi double [ %r637, %arr.fast.105 ], [ %r625, %arr.fallback.106 ] + %r639 = bitcast double %r638 to i64 + %r640 = and i64 %r639, 281474976710655 + %r641 = load double, ptr @batch_ts_.str.3.handle + %r642 = bitcast double %r641 to i64 + %r643 = and i64 %r642, 281474976710655 + %r644 = lshr i64 %r639, 48 + %r645 = icmp eq i64 %r644, 32761 + %r646 = icmp eq i64 %r644, 32766 + %r647 = and i64 %r644, 65533 + %r648 = icmp eq i64 %r647, 32765 + br i1 %r645, label %pget.recv_sso.109, label %pget.check_class_ref.115 + +arr.guard.deref.108: + %r588 = bitcast double %r580 to i64 + %r589 = and i64 %r588, 281474976710655 + %r590 = sub i64 %r589, 8 + %r591 = inttoptr i64 %r590 to ptr + %r592 = load i8, ptr %r591 + %r593 = icmp eq i8 %r592, 1 + %r594 = sub i64 %r589, 7 + %r595 = inttoptr i64 %r594 to ptr + %r596 = load i8, ptr %r595 + %r597 = and i8 %r596, 128 + %r598 = icmp eq i8 %r597, 0 + %r599 = sub i64 %r589, 6 + %r600 = inttoptr i64 %r599 to ptr + %r601 = load i16, ptr %r600 + %r602 = and i16 %r601, 1024 + %r603 = icmp eq i16 %r602, 0 + %r604 = load volatile i8, ptr @PERRY_ARRAY_INDEX_FAST_PATH_INVALIDATED + %r605 = icmp eq i8 %r604, 0 + %r606 = inttoptr i64 %r589 to ptr + %r607 = load i32, ptr %r606 + %r608 = getelementptr i8, ptr %r606, i64 4 + %r609 = load i32, ptr %r608 + %r610 = icmp slt i32 %r581, 0 + %r611 = icmp eq i1 %r610, false + %r612 = icmp ult i32 %r581, %r607 + %r613 = icmp ule i32 %r607, 16000000 + %r614 = icmp ule i32 %r609, 16000000 + %r615 = icmp ule i32 %r607, %r609 + %r616 = and i1 %r593, %r598 + %r617 = and i1 %r616, %r603 + %r618 = and i1 %r617, %r605 + %r619 = and i1 %r618, %r611 + %r620 = and i1 %r619, %r612 + %r621 = and i1 %r620, %r613 + %r622 = and i1 %r621, %r614 + %r623 = and i1 %r622, %r615 + br i1 %r623, label %arr.fast.105, label %arr.fallback.106 + +pget.recv_sso.109: + %r712 = call double @js_object_get_field_by_name_f64(i64 %r639, i64 %r643) + br label %pget.recv_merge.113 + +pget.recv_ok.110: + call void @js_typed_feedback_observe_property_get(i64 8450987250308612172, i64 %r640, i64 %r643) + %r650 = icmp ugt i64 %r640, 1048575 + %r651 = ptrtoint ptr @perry_ic_77 to i64 + %r652 = select i1 %r650, i64 %r640, i64 %r651 + %r653 = sub i64 %r652, 8 + %r654 = inttoptr i64 %r653 to ptr + %r655 = load i8, ptr %r654 + %r656 = icmp eq i8 %r655, 2 + %r657 = and i1 %r650, %r656 + %r658 = add i64 %r652, 12 + %r659 = inttoptr i64 %r658 to ptr + %r660 = load i32, ptr %r659 + %r661 = icmp eq i32 %r660, 1129268819 + %r662 = xor i1 %r661, true + %r663 = and i1 %r657, %r662 + %r664 = inttoptr i64 %r652 to ptr + %r665 = load i32, ptr %r664 + %r666 = icmp eq i32 %r665, 1 + %r667 = and i1 %r663, %r666 + %r668 = sub i64 %r652, 6 + %r669 = inttoptr i64 %r668 to ptr + %r670 = load i16, ptr %r669 + %r671 = and i16 %r670, 2048 + %r672 = icmp eq i16 %r671, 0 + %r673 = and i1 %r667, %r672 + %r674 = add i64 %r652, 16 + %r675 = inttoptr i64 %r674 to ptr + %r676 = load i64, ptr %r675 + %r677 = add i64 %r652, 8 + %r678 = inttoptr i64 %r677 to ptr + %r679 = load i32, ptr %r678 + %r680 = add i32 %r679, -2147483648 + %r681 = icmp ult i32 %r680, 1073741824 + %r682 = zext i32 %r679 to i64 + %r683 = or i64 %r682, 4611686018427387904 + %r684 = select i1 %r681, i64 %r683, i64 %r676 + %r685 = getelementptr i64, ptr @perry_ic_77, i64 0 + %r686 = load i64, ptr %r685 + %r687 = icmp eq i64 %r684, %r686 + %r688 = icmp ne i64 %r684, 0 + %r689 = and i1 %r673, %r687 + %r690 = and i1 %r689, %r688 + br i1 %r690, label %pic.hit.116, label %pic.miss.117 + +pget.recv_bad.111: + %r707 = icmp eq i64 %r639, 9222246136947933185 + %r708 = icmp eq i64 %r639, 9222246136947933186 + %r709 = or i1 %r707, %r708 + br i1 %r709, label %pget.throw_nullish.120, label %pget.recv_undef_return.121 + +pget.recv_class_ref.112: + %r649 = call double @js_typed_feedback_object_get_field_by_name_f64(i64 8450987250308612172, i64 %r639, i64 %r643) + br label %pget.recv_merge.113 + +pget.recv_merge.113: + %r713 = phi double [ %r706, %pic.merge.118 ], [ %r711, %pget.recv_undef_return.121 ], [ %r712, %pget.recv_sso.109 ], [ %r649, %pget.recv_class_ref.112 ] + %r714 = call i64 @js_gc_temp_root_get(i32 %r579) + %r715 = bitcast i64 %r714 to double + %r716 = call double @js_dynamic_string_or_number_add(double %r715, double %r713) + call void @js_gc_temp_root_truncate(i32 %r579) + store double %r716, ptr %r245 + br label %for.update.82 + +pget.check_ptr.114: + br i1 %r648, label %pget.recv_ok.110, label %pget.recv_bad.111 + +pget.check_class_ref.115: + br i1 %r646, label %pget.recv_class_ref.112, label %pget.check_ptr.114 + +pic.hit.116: + %r691 = getelementptr i64, ptr @perry_ic_77, i64 1 + %r692 = load i64, ptr %r691 + %r693 = add i64 %r652, 12 + %r694 = inttoptr i64 %r693 to ptr + %r695 = load i32, ptr %r694 + %r696 = zext i32 %r695 to i64 + %r697 = icmp ult i64 %r696, 4 + %r698 = select i1 %r697, i64 4, i64 %r696 + %r699 = icmp ult i64 %r692, %r698 + br i1 %r699, label %pic.hit.load.119, label %pic.miss.117 + +pic.miss.117: + call void @js_typed_feedback_record_guard_fail(i64 8450987250308612172) + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612172) + %r705 = call double @js_object_get_field_ic_miss(i64 %r640, i64 %r643, ptr @perry_ic_77) + br label %pic.merge.118 + +pic.merge.118: + %r706 = phi double [ %r704, %pic.hit.load.119 ], [ %r705, %pic.miss.117 ] + br label %pget.recv_merge.113 + +pic.hit.load.119: + call void @js_typed_feedback_record_guard_pass(i64 8450987250308612172) + %r700 = shl i64 %r692, 3 + %r701 = add i64 %r640, 32 + %r702 = add i64 %r701, %r700 + %r703 = inttoptr i64 %r702 to ptr + %r704 = load double, ptr %r703 + br label %pic.merge.118 + +pget.throw_nullish.120: + %r710 = zext i1 %r708 to i32 + call void @js_throw_type_error_property_access(i32 %r710, ptr @batch_ts_.str.3.bytes, i64 4) + unreachable + +pget.recv_undef_return.121: + %r711 = call double @js_object_get_field_by_name_f64(i64 %r639, i64 %r643) + br label %pget.recv_merge.113 + +ss.slow.122: + call void @js_shadow_slot_bind(i32 6, ptr %r721) + br label %ss.done.126 + +ss.chk_top.123: + %r726 = getelementptr inbounds i8, ptr %r724, i64 24 + %r727 = load i64, ptr %r726 + %r728 = icmp eq i64 %r727, -1 + br i1 %r728, label %ss.done.126, label %ss.chk_len.124 + +ss.chk_len.124: + %r729 = add i64 %r727, 6 + %r730 = getelementptr inbounds i8, ptr %r724, i64 8 + %r731 = load i64, ptr %r730 + %r732 = icmp ult i64 %r729, %r731 + br i1 %r732, label %ss.store.125, label %ss.done.126 + +ss.store.125: + %r733 = load ptr, ptr %r724 + %r734 = shl i64 %r729, 4 + %r735 = getelementptr inbounds i8, ptr %r733, i64 %r734 + %r736 = getelementptr inbounds i8, ptr %r735, i64 8 + %r737 = load i64, ptr %r721 + %r738 = ptrtoint ptr %r721 to i64 + %r739 = and i64 %r738, 1 + %r740 = icmp eq i64 %r739, 0 + %r741 = select i1 %r740, i64 %r738, i64 0 + %r742 = or i64 %r741, 1 + store i64 %r737, ptr %r735 + store i64 %r742, ptr %r736 + %r743 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r744 = icmp ne i32 %r743, 0 + br i1 %r744, label %ss.barrier.127, label %ss.done.126 + +ss.done.126: + %r745 = load ptr, ptr %r2 + %r746 = icmp eq ptr %r745, null + br i1 %r746, label %ss.slow.128, label %ss.chk_top.129 + +ss.barrier.127: + call void @js_write_barrier_root_nanbox(i64 %r737) + br label %ss.done.126 + +ss.slow.128: + call void @js_shadow_slot_set(i32 5, i64 0) + br label %ss.done.132 + +ss.chk_top.129: + %r747 = getelementptr inbounds i8, ptr %r745, i64 24 + %r748 = load i64, ptr %r747 + %r749 = icmp eq i64 %r748, -1 + br i1 %r749, label %ss.done.132, label %ss.chk_len.130 + +ss.chk_len.130: + %r750 = add i64 %r748, 5 + %r751 = getelementptr inbounds i8, ptr %r745, i64 8 + %r752 = load i64, ptr %r751 + %r753 = icmp ult i64 %r750, %r752 + br i1 %r753, label %ss.store.131, label %ss.done.132 + +ss.store.131: + %r754 = load ptr, ptr %r745 + %r755 = shl i64 %r750, 4 + %r756 = getelementptr inbounds i8, ptr %r754, i64 %r755 + %r757 = getelementptr inbounds i8, ptr %r756, i64 8 + %r758 = load i64, ptr %r757 + %r759 = and i64 %r758, -2 + store i64 0, ptr %r756 + store i64 %r759, ptr %r757 + br label %ss.done.132 + +ss.done.132: + %r760 = load double, ptr %r245 + %r761 = load double, ptr %r245 + %r762 = load double, ptr %r245 + %r763 = load double, ptr %r245 + %r764 = load double, ptr %r721 + %r765 = bitcast double %r764 to i64 + %r766 = and i64 %r765, 281474976710655 + %r767 = load double, ptr @batch_ts_.str.2.handle + %r768 = bitcast double %r767 to i64 + %r769 = and i64 %r768, 281474976710655 + %r770 = load i64, ptr @perry_class_keys_batch_ts__Row + %r771 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r772 = icmp eq i8 %r771, 0 + %r773 = lshr i64 %r765, 48 + %r774 = icmp eq i64 %r773, 32765 + %r775 = icmp ugt i64 %r766, 1048575 + %r776 = and i1 %r774, %r775 + %r777 = and i1 %r776, %r772 + br i1 %r777, label %class_field_inline.deref.136, label %class_field_inline.guardcall.137 + +class_field_get_number.fast.133: + %r812 = inttoptr i64 %r766 to ptr + %r813 = getelementptr i8, ptr %r812, i64 32 + %r814 = getelementptr double, ptr %r813, i64 2 + %r815 = load double, ptr %r814 + br label %class_field_get_number.merge.135 + +class_field_get_number.fallback.134: + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612174) + %r816 = call double @js_object_get_field_by_name_f64(i64 %r765, i64 %r769) + %r817 = call double @js_number_coerce(double %r816) + br label %class_field_get_number.merge.135 + +class_field_get_number.merge.135: + %r818 = phi double [ %r815, %class_field_get_number.fast.133 ], [ %r817, %class_field_get_number.fallback.134 ] + %r819 = fadd double %r763, %r818 + %r820 = load double, ptr %r721 + %r821 = bitcast double %r820 to i64 + %r822 = and i64 %r821, 281474976710655 + %r823 = load double, ptr @batch_ts_.str.4.handle + %r824 = bitcast double %r823 to i64 + %r825 = and i64 %r824, 281474976710655 + %r826 = load i64, ptr @perry_class_keys_batch_ts__Row + %r827 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r828 = icmp eq i8 %r827, 0 + %r829 = lshr i64 %r821, 48 + %r830 = icmp eq i64 %r829, 32765 + %r831 = icmp ugt i64 %r822, 1048575 + %r832 = and i1 %r830, %r831 + %r833 = and i1 %r832, %r828 + br i1 %r833, label %class_field_inline.deref.141, label %class_field_inline.guardcall.142 + +class_field_inline.deref.136: + %r778 = inttoptr i64 %r766 to ptr + %r779 = getelementptr i8, ptr %r778, i64 -8 + %r780 = load i8, ptr %r779 + %r781 = icmp eq i8 %r780, 2 + %r782 = getelementptr i8, ptr %r778, i64 -7 + %r783 = load i8, ptr %r782 + %r784 = and i8 %r783, -128 + %r785 = icmp eq i8 %r784, 0 + %r786 = getelementptr i8, ptr %r778, i64 -6 + %r787 = load i16, ptr %r786 + %r788 = load i32, ptr %r778 + %r789 = icmp eq i32 %r788, 1 + %r790 = getelementptr i8, ptr %r778, i64 4 + %r791 = load i32, ptr %r790 + %r792 = icmp eq i32 %r791, 1 + %r793 = getelementptr i8, ptr %r778, i64 12 + %r794 = load i32, ptr %r793 + %r795 = icmp ugt i32 %r794, 2 + %r796 = getelementptr i8, ptr %r778, i64 16 + %r797 = load i64, ptr %r796 + %r798 = icmp eq i64 %r797, %r770 + %r799 = and i1 %r781, %r785 + %r800 = and i1 %r799, %r789 + %r801 = and i1 %r800, %r792 + %r802 = and i1 %r801, %r795 + %r803 = and i1 %r802, %r798 + %r804 = and i16 %r787, 2048 + %r805 = icmp eq i16 %r804, 0 + %r806 = and i1 %r803, %r805 + %r807 = and i16 %r787, 4096 + %r808 = icmp ne i16 %r807, 0 + %r809 = and i1 %r806, %r808 + br i1 %r809, label %class_field_get_number.fast.133, label %class_field_inline.guardcall.137 + +class_field_inline.guardcall.137: + %r810 = call i32 @js_typed_feedback_class_field_get_guard(i64 8450987250308612174, double %r764, i32 1, i64 %r770, i64 %r769, i32 2, i32 1) + %r811 = icmp ne i32 %r810, 0 + br i1 %r811, label %class_field_get_number.fast.133, label %class_field_get_number.fallback.134 + +class_field_get_number.fast.138: + %r868 = inttoptr i64 %r822 to ptr + %r869 = getelementptr i8, ptr %r868, i64 32 + %r870 = getelementptr double, ptr %r869, i64 3 + %r871 = load double, ptr %r870 + br label %class_field_get_number.merge.140 + +class_field_get_number.fallback.139: + call void @js_typed_feedback_record_fallback_call(i64 8450987250308612175) + %r872 = call double @js_object_get_field_by_name_f64(i64 %r821, i64 %r825) + %r873 = call double @js_number_coerce(double %r872) + br label %class_field_get_number.merge.140 + +class_field_get_number.merge.140: + %r874 = phi double [ %r871, %class_field_get_number.fast.138 ], [ %r873, %class_field_get_number.fallback.139 ] + %r875 = fadd double %r819, %r874 + store double %r875, ptr %r245 + %r876 = load ptr, ptr %r2 + %r877 = icmp eq ptr %r876, null + br i1 %r877, label %ss.slow.143, label %ss.chk_top.144 + +class_field_inline.deref.141: + %r834 = inttoptr i64 %r822 to ptr + %r835 = getelementptr i8, ptr %r834, i64 -8 + %r836 = load i8, ptr %r835 + %r837 = icmp eq i8 %r836, 2 + %r838 = getelementptr i8, ptr %r834, i64 -7 + %r839 = load i8, ptr %r838 + %r840 = and i8 %r839, -128 + %r841 = icmp eq i8 %r840, 0 + %r842 = getelementptr i8, ptr %r834, i64 -6 + %r843 = load i16, ptr %r842 + %r844 = load i32, ptr %r834 + %r845 = icmp eq i32 %r844, 1 + %r846 = getelementptr i8, ptr %r834, i64 4 + %r847 = load i32, ptr %r846 + %r848 = icmp eq i32 %r847, 1 + %r849 = getelementptr i8, ptr %r834, i64 12 + %r850 = load i32, ptr %r849 + %r851 = icmp ugt i32 %r850, 3 + %r852 = getelementptr i8, ptr %r834, i64 16 + %r853 = load i64, ptr %r852 + %r854 = icmp eq i64 %r853, %r826 + %r855 = and i1 %r837, %r841 + %r856 = and i1 %r855, %r845 + %r857 = and i1 %r856, %r848 + %r858 = and i1 %r857, %r851 + %r859 = and i1 %r858, %r854 + %r860 = and i16 %r843, 2048 + %r861 = icmp eq i16 %r860, 0 + %r862 = and i1 %r859, %r861 + %r863 = and i16 %r843, 4096 + %r864 = icmp ne i16 %r863, 0 + %r865 = and i1 %r862, %r864 + br i1 %r865, label %class_field_get_number.fast.138, label %class_field_inline.guardcall.142 + +class_field_inline.guardcall.142: + %r866 = call i32 @js_typed_feedback_class_field_get_guard(i64 8450987250308612175, double %r820, i32 1, i64 %r826, i64 %r825, i32 3, i32 1) + %r867 = icmp ne i32 %r866, 0 + br i1 %r867, label %class_field_get_number.fast.138, label %class_field_get_number.fallback.139 + +ss.slow.143: + call void @js_shadow_slot_set(i32 6, i64 0) + br label %ss.done.147 + +ss.chk_top.144: + %r878 = getelementptr inbounds i8, ptr %r876, i64 24 + %r879 = load i64, ptr %r878 + %r880 = icmp eq i64 %r879, -1 + br i1 %r880, label %ss.done.147, label %ss.chk_len.145 + +ss.chk_len.145: + %r881 = add i64 %r879, 6 + %r882 = getelementptr inbounds i8, ptr %r876, i64 8 + %r883 = load i64, ptr %r882 + %r884 = icmp ult i64 %r881, %r883 + br i1 %r884, label %ss.store.146, label %ss.done.147 + +ss.store.146: + %r885 = load ptr, ptr %r876 + %r886 = shl i64 %r881, 4 + %r887 = getelementptr inbounds i8, ptr %r885, i64 %r886 + %r888 = getelementptr inbounds i8, ptr %r887, i64 8 + %r889 = load i64, ptr %r888 + %r890 = and i64 %r889, -2 + store i64 0, ptr %r887 + store i64 %r890, ptr %r888 + br label %ss.done.147 + +ss.done.147: + %r891 = load double, ptr @batch_ts_.str.19.handle + %r892 = load double, ptr %r245 + %r893 = call i64 @js_number_to_fixed(double %r892, double 4.0) + %r894 = or i64 %r893, 9223090561878065152 + %r895 = bitcast i64 %r894 to double + %r896 = load double, ptr @batch_ts_.str.19.handle + %r897 = call double @js_string_concat_box(double %r896, double %r895) + %r898 = bitcast double %r897 to i64 + %r899 = call i32 @js_gc_temp_root_push(i64 %r898) + %r900 = call i64 @js_array_alloc(i32 1) + %r901 = call i32 @js_gc_temp_root_push(i64 %r900) + %r902 = call i64 @js_gc_temp_root_get(i32 %r899) + %r903 = bitcast i64 %r902 to double + call void @js_array_push_f64_temp_rooted(i32 %r901, double %r903) + %r904 = call i64 @js_gc_temp_root_get(i32 %r901) + call void @js_console_log_spread(i64 %r904) + call void @js_gc_temp_root_truncate(i32 %r899) + %r905 = call i32 @js_promise_run_microtasks_event_loop() + %r906 = call i32 @js_timer_tick_if_refed() + %r907 = call i32 @js_callback_timer_tick() + %r908 = call i32 @js_interval_timer_tick() + %r909 = call i32 @js_promise_run_microtasks_event_loop() + %r910 = call i32 @js_timer_tick_if_refed() + %r911 = call i32 @js_callback_timer_tick() + %r912 = call i32 @js_interval_timer_tick() + %r913 = call i32 @js_promise_run_microtasks_event_loop() + %r914 = call i32 @js_timer_tick_if_refed() + %r915 = call i32 @js_callback_timer_tick() + %r916 = call i32 @js_interval_timer_tick() + %r917 = call i32 @js_promise_run_microtasks_event_loop() + %r918 = call i32 @js_timer_tick_if_refed() + %r919 = call i32 @js_callback_timer_tick() + %r920 = call i32 @js_interval_timer_tick() + call void @js_run_stdlib_pump() + br label %event_loop.header.148 + +event_loop.header.148: + %r921 = call i32 @js_event_loop_host_driven() + %r922 = icmp ne i32 %r921, 0 + br i1 %r922, label %event_loop.host_return.150, label %event_loop.check_pending.149 + +event_loop.check_pending.149: + %r923 = call i32 @js_timer_has_pending() + %r924 = call i32 @js_callback_timer_has_pending() + %r925 = call i32 @js_interval_timer_has_pending() + %r926 = call i32 @js_stdlib_has_active_handles() + %r927 = call i32 @js_microtasks_pending() + %r928 = or i32 %r923, %r924 + %r929 = or i32 %r925, %r926 + %r930 = or i32 %r928, %r929 + %r931 = or i32 %r930, 0 + %r932 = or i32 %r931, %r927 + %r933 = icmp ne i32 %r932, 0 + br i1 %r933, label %event_loop.body.151, label %event_loop.exit.152 + +event_loop.host_return.150: + call void @js_typed_feedback_maybe_dump_trace() + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret i32 0 + +event_loop.body.151: + %r934 = call i32 @js_promise_run_microtasks_event_loop() + %r935 = call i32 @js_timer_tick() + %r936 = call i32 @js_callback_timer_tick() + %r937 = call i32 @js_interval_timer_tick() + call void @js_run_stdlib_pump() + call void @js_wait_for_event() + br label %event_loop.header.148 + +event_loop.exit.152: + call void @js_process_emit_before_exit(double 0x0) + %r938 = call i32 @js_promise_run_microtasks_event_loop() + %r939 = call i32 @js_timer_tick_if_refed() + %r940 = call i32 @js_callback_timer_tick() + %r941 = call i32 @js_interval_timer_tick() + call void @js_process_run_finalization_exit() + call void @js_trace_events_flush_output() + call void @js_promise_report_unhandled_rejections() + call void @js_gc_release_current_thread_collection_side_allocations() + %r942 = call i32 @js_process_pending_exit_code() + call void @js_typed_feedback_maybe_dump_trace() + %shadow_pop_l_1 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_1) + ret i32 %r942 +} + +define void @__perry_init_strings_batch_ts_chunk0() { +entry.0: + %r1 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.0.bytes, i32 3) + %r2 = call double @js_nanbox_string(i64 %r1) + store double %r2, ptr @batch_ts_.str.0.handle + %r3 = ptrtoint ptr @batch_ts_.str.0.handle to i64 + call void @js_gc_register_global_root(i64 %r3) + %r4 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.1.bytes, i32 5) + %r5 = call double @js_nanbox_string(i64 %r4) + store double %r5, ptr @batch_ts_.str.1.handle + %r6 = ptrtoint ptr @batch_ts_.str.1.handle to i64 + call void @js_gc_register_global_root(i64 %r6) + %r7 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.2.bytes, i32 6) + %r8 = call double @js_nanbox_string(i64 %r7) + store double %r8, ptr @batch_ts_.str.2.handle + %r9 = ptrtoint ptr @batch_ts_.str.2.handle to i64 + call void @js_gc_register_global_root(i64 %r9) + %r10 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.3.bytes, i32 4) + %r11 = call double @js_nanbox_string(i64 %r10) + store double %r11, ptr @batch_ts_.str.3.handle + %r12 = ptrtoint ptr @batch_ts_.str.3.handle to i64 + call void @js_gc_register_global_root(i64 %r12) + %r13 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.4.bytes, i32 5) + %r14 = call double @js_nanbox_string(i64 %r13) + store double %r14, ptr @batch_ts_.str.4.handle + %r15 = ptrtoint ptr @batch_ts_.str.4.handle to i64 + call void @js_gc_register_global_root(i64 %r15) + %r16 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.5.bytes, i32 6) + %r17 = call double @js_nanbox_string(i64 %r16) + store double %r17, ptr @batch_ts_.str.5.handle + %r18 = ptrtoint ptr @batch_ts_.str.5.handle to i64 + call void @js_gc_register_global_root(i64 %r18) + %r19 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.6.bytes, i32 1) + %r20 = call double @js_nanbox_string(i64 %r19) + store double %r20, ptr @batch_ts_.str.6.handle + %r21 = ptrtoint ptr @batch_ts_.str.6.handle to i64 + call void @js_gc_register_global_root(i64 %r21) + %r22 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.7.bytes, i32 2) + %r23 = call double @js_nanbox_string(i64 %r22) + store double %r23, ptr @batch_ts_.str.7.handle + %r24 = ptrtoint ptr @batch_ts_.str.7.handle to i64 + call void @js_gc_register_global_root(i64 %r24) + %r25 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.8.bytes, i32 7) + %r26 = call double @js_nanbox_string(i64 %r25) + store double %r26, ptr @batch_ts_.str.8.handle + %r27 = ptrtoint ptr @batch_ts_.str.8.handle to i64 + call void @js_gc_register_global_root(i64 %r27) + %r28 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.9.bytes, i32 4) + %r29 = call double @js_nanbox_string(i64 %r28) + store double %r29, ptr @batch_ts_.str.9.handle + %r30 = ptrtoint ptr @batch_ts_.str.9.handle to i64 + call void @js_gc_register_global_root(i64 %r30) + %r31 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.10.bytes, i32 3) + %r32 = call double @js_nanbox_string(i64 %r31) + store double %r32, ptr @batch_ts_.str.10.handle + %r33 = ptrtoint ptr @batch_ts_.str.10.handle to i64 + call void @js_gc_register_global_root(i64 %r33) + %r34 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.11.bytes, i32 5) + %r35 = call double @js_nanbox_string(i64 %r34) + store double %r35, ptr @batch_ts_.str.11.handle + %r36 = ptrtoint ptr @batch_ts_.str.11.handle to i64 + call void @js_gc_register_global_root(i64 %r36) + %r37 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.12.bytes, i32 3) + %r38 = call double @js_nanbox_string(i64 %r37) + store double %r38, ptr @batch_ts_.str.12.handle + %r39 = ptrtoint ptr @batch_ts_.str.12.handle to i64 + call void @js_gc_register_global_root(i64 %r39) + %r40 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.13.bytes, i32 5) + %r41 = call double @js_nanbox_string(i64 %r40) + store double %r41, ptr @batch_ts_.str.13.handle + %r42 = ptrtoint ptr @batch_ts_.str.13.handle to i64 + call void @js_gc_register_global_root(i64 %r42) + %r43 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.14.bytes, i32 3) + %r44 = call double @js_nanbox_string(i64 %r43) + store double %r44, ptr @batch_ts_.str.14.handle + %r45 = ptrtoint ptr @batch_ts_.str.14.handle to i64 + call void @js_gc_register_global_root(i64 %r45) + %r46 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.15.bytes, i32 5) + %r47 = call double @js_nanbox_string(i64 %r46) + store double %r47, ptr @batch_ts_.str.15.handle + %r48 = ptrtoint ptr @batch_ts_.str.15.handle to i64 + call void @js_gc_register_global_root(i64 %r48) + %r49 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.16.bytes, i32 4) + %r50 = call double @js_nanbox_string(i64 %r49) + store double %r50, ptr @batch_ts_.str.16.handle + %r51 = ptrtoint ptr @batch_ts_.str.16.handle to i64 + call void @js_gc_register_global_root(i64 %r51) + %r52 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.17.bytes, i32 5) + %r53 = call double @js_nanbox_string(i64 %r52) + store double %r53, ptr @batch_ts_.str.17.handle + %r54 = ptrtoint ptr @batch_ts_.str.17.handle to i64 + call void @js_gc_register_global_root(i64 %r54) + %r55 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.18.bytes, i32 5) + %r56 = call double @js_nanbox_string(i64 %r55) + store double %r56, ptr @batch_ts_.str.18.handle + %r57 = ptrtoint ptr @batch_ts_.str.18.handle to i64 + call void @js_gc_register_global_root(i64 %r57) + %r58 = call i64 @js_string_from_bytes(ptr @batch_ts_.str.19.bytes, i32 10) + %r59 = call double @js_nanbox_string(i64 %r58) + store double %r59, ptr @batch_ts_.str.19.handle + %r60 = ptrtoint ptr @batch_ts_.str.19.handle to i64 + call void @js_gc_register_global_root(i64 %r60) + call void @js_register_function_name(ptr @__perry_wrap_perry_fn_batch_ts__buildRows, ptr @.str.0, i32 9) + call void @js_register_function_name(ptr @__perry_wrap_perry_fn_batch_ts__shape, ptr @.str.1, i32 5) + call void @js_register_function_name(ptr @__perry_wrap_perry_fn_batch_ts__ranked, ptr @.str.2, i32 6) + call void @js_register_function_name(ptr @__perry_wrap_perry_fn_batch_ts__summarize, ptr @.str.3, i32 9) + call void @js_register_function_name(ptr @__perry_wrap_perry_fn_batch_ts__totalsRow, ptr @.str.4, i32 9) + call void @js_register_function_source(ptr @__perry_wrap_perry_fn_batch_ts__buildRows, ptr @.str.5, i32 213) + call void @js_register_function_source(ptr @__perry_wrap_perry_fn_batch_ts__shape, ptr @.str.6, i32 193) + call void @js_register_function_source(ptr @__perry_wrap_perry_fn_batch_ts__ranked, ptr @.str.7, i32 271) + call void @js_register_function_source(ptr @__perry_wrap_perry_fn_batch_ts__summarize, ptr @.str.8, i32 639) + call void @js_register_function_source(ptr @__perry_wrap_perry_fn_batch_ts__totalsRow, ptr @.str.9, i32 263) + call void @js_register_function_source(ptr @perry_closure_batch_ts__7, ptr @.str.10, i32 129) + call void @js_register_function_source(ptr @perry_closure_batch_ts__9, ptr @.str.11, i32 159) + call void @js_register_function_source(ptr @perry_closure_batch_ts__11, ptr @.str.12, i32 291) + %r61 = call i64 @js_build_class_keys_array(i32 1, i32 4, ptr @perry_class_keys_packed_batch_ts__0, i32 23) + store i64 %r61, ptr @perry_class_keys_batch_ts__Row + call void @js_write_barrier_root_heap_word(i64 %r61) + %r62 = ptrtoint ptr @perry_class_keys_batch_ts__Row to i64 + call void @js_gc_register_global_root(i64 %r62) + %r63 = call i64 @js_build_class_keys_array(i32 2, i32 3, ptr @perry_class_keys_packed_batch_ts__1, i32 14) + store i64 %r63, ptr @perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 + call void @js_write_barrier_root_heap_word(i64 %r63) + %r64 = ptrtoint ptr @perry_class_keys_batch_ts____AnonShape_e75d7e32e87dc826 to i64 + call void @js_gc_register_global_root(i64 %r64) + %r65 = call i64 @js_build_class_keys_array(i32 3, i32 4, ptr @perry_class_keys_packed_batch_ts__2, i32 24) + store i64 %r65, ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 + call void @js_write_barrier_root_heap_word(i64 %r65) + %r66 = ptrtoint ptr @perry_class_keys_batch_ts____AnonShape_c33c4204c28b9430 to i64 + call void @js_gc_register_global_root(i64 %r66) + %r67 = ptrtoint ptr @perry_method_batch_ts__Row__rescore to i64 + %r68 = ptrtoint ptr @batch_ts_.str.8.bytes to i64 + call void @js_register_class_method(i64 1, i64 %r68, i64 7, i64 %r67, i64 1, i64 0, i64 0) + call void @js_register_class_method_bind_length(i64 1, i64 %r68, i64 7, i64 1) + %r69 = ptrtoint ptr @batch_ts__Row_constructor to i64 + call void @js_register_class_constructor(i64 1, i64 %r69, i64 3, i64 0) + %r70 = ptrtoint ptr @batch_ts____AnonShape_e75d7e32e87dc826_constructor to i64 + call void @js_register_class_constructor(i64 2, i64 %r70, i64 3, i64 0) + %r71 = ptrtoint ptr @batch_ts____AnonShape_c33c4204c28b9430_constructor to i64 + call void @js_register_class_constructor(i64 3, i64 %r71, i64 4, i64 0) + call void @js_register_class_id(i32 1) + call void @js_register_class_id(i32 2) + call void @js_register_class_id(i32 3) + call void @js_register_anon_shape_class_id(i32 2) + call void @js_register_anon_shape_class_id(i32 3) + call void @js_register_class_name(i32 1, ptr @.str.13, i32 3) + call void @js_register_closure_arity(ptr @perry_closure_batch_ts__7, i32 1) + call void @js_register_closure_arity(ptr @perry_closure_batch_ts__9, i32 2) + call void @js_register_closure_arity(ptr @perry_closure_batch_ts__11, i32 2) + call void @js_register_closure_length(ptr @perry_closure_batch_ts__7, i32 1) + call void @js_register_closure_length(ptr @perry_closure_batch_ts__9, i32 2) + call void @js_register_closure_length(ptr @perry_closure_batch_ts__11, i32 2) + call void @js_register_closure_arrow_function(ptr @perry_closure_batch_ts__7) + call void @js_register_closure_arrow_function(ptr @perry_closure_batch_ts__9) + call void @js_register_closure_arrow_function(ptr @perry_closure_batch_ts__11) + call void @js_register_closure_arity(ptr @__perry_wrap_perry_fn_batch_ts__buildRows, i32 2) + call void @js_register_closure_arity(ptr @__perry_wrap_perry_fn_batch_ts__ranked, i32 1) + call void @js_register_closure_arity(ptr @__perry_wrap_perry_fn_batch_ts__shape, i32 1) + call void @js_register_closure_arity(ptr @__perry_wrap_perry_fn_batch_ts__summarize, i32 1) + call void @js_register_closure_arity(ptr @__perry_wrap_perry_fn_batch_ts__totalsRow, i32 1) + call void @js_register_closure_length(ptr @__perry_wrap_perry_fn_batch_ts__buildRows, i32 2) + call void @js_register_closure_length(ptr @__perry_wrap_perry_fn_batch_ts__ranked, i32 1) + call void @js_register_closure_length(ptr @__perry_wrap_perry_fn_batch_ts__shape, i32 1) + call void @js_register_closure_length(ptr @__perry_wrap_perry_fn_batch_ts__summarize, i32 1) + call void @js_register_closure_length(ptr @__perry_wrap_perry_fn_batch_ts__totalsRow, i32 1) + call void @js_register_closure_strict_function(ptr @__perry_wrap_perry_fn_batch_ts__buildRows) + call void @js_register_closure_strict_function(ptr @__perry_wrap_perry_fn_batch_ts__ranked) + call void @js_register_closure_strict_function(ptr @__perry_wrap_perry_fn_batch_ts__shape) + call void @js_register_closure_strict_function(ptr @__perry_wrap_perry_fn_batch_ts__summarize) + call void @js_register_closure_strict_function(ptr @__perry_wrap_perry_fn_batch_ts__totalsRow) + call void @js_register_closure_strict_function(ptr @perry_closure_batch_ts__11) + call void @js_register_closure_strict_function(ptr @perry_closure_batch_ts__7) + call void @js_register_closure_strict_function(ptr @perry_closure_batch_ts__9) + ret void +} + +define void @__perry_init_strings_batch_ts() { +entry.0: + call void @__perry_init_strings_batch_ts_chunk0() + ret void +} + + +attributes #0 = { returns_twice } +attributes #1 = { noinline } + +attributes #2 = { nounwind willreturn readnone } + +attributes #3 = { nounwind willreturn readonly } + +attributes #4 = { nounwind willreturn } + +!0 = !{} diff --git a/experiments/llvm-inprocess-spike/spike_text.ll b/experiments/llvm-inprocess-spike/spike_text.ll new file mode 100644 index 0000000000..759ce25fcf --- /dev/null +++ b/experiments/llvm-inprocess-spike/spike_text.ll @@ -0,0 +1,5625 @@ +; Generated by perry-codegen +target triple = "arm64-apple-macosx15.0.0" + +@spike_ts_.str.0.bytes = private unnamed_addr constant [8 x i8] c"hello, \00" +@spike_ts_.str.1.bytes = private unnamed_addr constant [2 x i8] c"!\00" +@spike_ts_.str.2.bytes = private unnamed_addr constant [7 x i8] c"async:\00" +@spike_ts_.str.3.bytes = private unnamed_addr constant [2 x i8] c"x\00" +@spike_ts_.str.4.bytes = private unnamed_addr constant [2 x i8] c"y\00" +@spike_ts_.str.5.bytes = private unnamed_addr constant [10 x i8] c"fib(20) =\00" +@spike_ts_.str.6.bytes = private unnamed_addr constant [8 x i8] c"sorted:\00" +@spike_ts_.str.7.bytes = private unnamed_addr constant [2 x i8] c",\00" +@spike_ts_.str.8.bytes = private unnamed_addr constant [6 x i8] c"alpha\00" +@spike_ts_.str.9.bytes = private unnamed_addr constant [5 x i8] c"beta\00" +@spike_ts_.str.10.bytes = private unnamed_addr constant [3 x i8] c"->\00" +@spike_ts_.str.11.bytes = private unnamed_addr constant [6 x i8] c"norm:\00" +@spike_ts_.str.12.bytes = private unnamed_addr constant [5 x i8] c"norm\00" +@spike_ts_.str.13.bytes = private unnamed_addr constant [6 x i8] c"perry\00" +@perry_class_keys_packed_spike_ts__0 = private unnamed_addr constant [5 x i8] c"x\00y\00\00" +@.str.0 = private unnamed_addr constant [4 x i8] c"fib\00" +@.str.1 = private unnamed_addr constant [6 x i8] c"greet\00" +@.str.2 = private unnamed_addr constant [82 x i8] c"function fib(n: number): number {\0A return n < 2 ? n : fib(n - 1) + fib(n - 2);\0A}\00" +@.str.3 = private unnamed_addr constant [16 x i8] c"(a, b) => a - b\00" +@.str.4 = private unnamed_addr constant [36 x i8] c"(name: string) => `hello, ${name}!`\00" +@.str.5 = private unnamed_addr constant [83 x i8] c"async () => {\0A const v = await Promise.resolve(42);\0A console.log(\22async:\22, v);\0A}\00" +@.str.6 = private unnamed_addr constant [6 x i8] c"Point\00" + +@perry_null_guard_zero = internal global i32 0 +@PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED = external global i8 +@PERRY_ARRAY_INDEX_FAST_PATH_INVALIDATED = external global i8 +@PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT = external global i32 +@PERRY_TA_KIND_CACHE = external global [64 x i64] +@PERRY_TA_VIEW_GUARD = external global i64 +@perry_class_keys_spike_ts__Point = internal global i64 0 +@spike_ts_.str.0.handle = internal global double 0.0 +@spike_ts_.str.1.handle = internal global double 0.0 +@spike_ts_.str.2.handle = internal global double 0.0 +@spike_ts_.str.3.handle = internal global double 0.0 +@spike_ts_.str.4.handle = internal global double 0.0 +@spike_ts_.str.5.handle = internal global double 0.0 +@spike_ts_.str.6.handle = internal global double 0.0 +@spike_ts_.str.7.handle = internal global double 0.0 +@spike_ts_.str.8.handle = internal global double 0.0 +@spike_ts_.str.9.handle = internal global double 0.0 +@spike_ts_.str.10.handle = internal global double 0.0 +@spike_ts_.str.11.handle = internal global double 0.0 +@spike_ts_.str.12.dispatch = private unnamed_addr constant { i32, i32, i64, ptr } { i32 4, i32 0, i64 4315873112953976271, ptr @spike_ts_.str.12.bytes } +@spike_ts_.str.12.handle = internal global double 0.0 +@spike_ts_.str.13.handle = internal global double 0.0 +@perry_typed_shape_raw_f64_mask_spike_ts__Point = private unnamed_addr constant [1 x i64] [i64 3] + +declare void @js_gc_init() +declare void @js_typed_feedback_maybe_dump_trace() +declare void @js_stdlib_init_dispatch() +declare void @perry_app_group_init(ptr, i32) +declare void @perry_macos_bundle_chdir() +declare i32 @perry_i18n_locale_index_for(i64, i32) +declare void @perry_i18n_init(ptr, ptr, i32, i32) +declare void @perry_i18n_set_currencies(ptr, i32) +declare i32 @perry_i18n_plural_category(i32, double) +declare void @js_register_function_name(ptr, ptr, i32) +declare void @js_register_function_source(ptr, ptr, i32) +declare void @js_console_log_dynamic(double) +declare void @js_console_log_number(double) +declare void @js_console_error_dynamic(double) +declare void @js_console_error_number(double) +declare void @js_console_warn_dynamic(double) +declare void @js_console_warn_number(double) +declare void @js_console_dir_with_options(double, double) +declare double @js_console_method_by_value(double) +declare double @js_nanbox_string(i64) +declare double @js_nanbox_pointer(i64) #2 +declare i64 @js_nanbox_get_pointer(double) #2 +declare double @js_native_handle_new_owned(i64, i64, i32, i32, ptr, ptr, i64) +declare double @js_native_handle_new_borrowed(i64, i64, i32, i32, ptr, i64) +declare i64 @js_native_handle_unwrap(double, i64, i32, i32, i32) +declare i64 @js_string_from_bytes(ptr, i32) +declare i64 @js_string_from_wtf8_bytes(ptr, i32) +declare i32 @js_is_truthy(double) #3 +declare double @js_native_abi_check_f64(double) +declare i32 @js_typed_f64_arg_guard(double) #2 +declare double @js_typed_f64_arg_to_raw(double) +declare i32 @js_typed_i32_arg_guard(double) #2 +declare i32 @js_typed_i32_arg_to_raw(double) #2 +declare i32 @js_typed_i1_arg_guard(double) #2 +declare i32 @js_typed_i1_arg_to_raw(double) #2 +declare i32 @js_typed_string_arg_guard(double) #2 +declare i64 @js_typed_string_arg_to_raw(double) +declare float @js_native_abi_check_f32(double) +declare i32 @js_native_abi_check_i32(double) +declare i64 @js_native_abi_check_i64(double) +declare i32 @js_native_abi_check_u32(double) +declare i64 @js_native_abi_check_u64(double) +declare i64 @js_native_abi_check_usize(double) +declare i64 @js_native_abi_check_string_ptr(double) +declare i64 @js_native_abi_check_ptr(double) +declare ptr @js_native_abi_check_buffer_data_ptr(double) +declare i64 @js_native_abi_check_buffer_byte_len(double) +declare i64 @js_native_abi_check_promise(double) +declare i64 @js_native_abi_check_pod_object(double) +declare double @js_date_now() +declare void @js_gc_register_global_root(i64) +declare i64 @js_string_concat(i64, i64) +declare double @js_string_concat_box(double, double) +declare i64 @js_jsvalue_to_string(double) +declare i64 @js_jsvalue_to_string_method(double) +declare i64 @js_jsvalue_to_string_coerce(double) +declare i64 @js_string_concat_value(i64, double) +declare i64 @js_value_concat_string(double, i64) +declare i64 @js_string_concat_chain(i64, i32) +declare i64 @js_string_append(i64, i64) +declare i32 @js_string_index_of(i64, i64) +declare i32 @js_string_index_of_from(i64, i64, i32) +declare i32 @js_string_position_to_index(double) +declare i64 @js_string_slice(i64, i32, i32) +declare i64 @js_string_substring(i64, i32, i32) +declare i64 @js_string_substr(i64, double, double) +declare i64 @js_string_split(i64, i64) +declare i64 @js_string_split_n(i64, i64, i32) +declare double @js_string_split_part_value(i64, i64, i32) +declare double @js_string_split_part_utf16_length(i64, i64, i32) +declare double @js_string_to_upper_case_split_part_utf16_length(i64, i64, i32) +declare i32 @js_string_to_upper_case_index_of(i64, i64) +declare i64 @js_string_split_value(i64, double, double) +declare double @js_math_trunc(double) +declare double @js_math_round(double) +declare double @js_math_sign(double) +declare double @js_math_imul(double, double) +declare double @js_math_pow(double, double) +declare double @llvm.sqrt.f64(double) +declare double @llvm.floor.f64(double) +declare double @llvm.ceil.f64(double) +declare double @llvm.fabs.f64(double) +declare double @llvm.copysign.f64(double, double) +declare void @llvm.assume(i1) +declare i16 @llvm.bswap.i16(i16) +declare i32 @llvm.bswap.i32(i32) +declare i64 @llvm.bswap.i64(i64) +declare i32 @llvm.aarch64.fjcvtzs(double) +declare void @llvm.memset.p0.i64(ptr, i8, i64, i1) +declare void @llvm.memmove.p0.p0.i64(ptr, ptr, i64, i1) +declare i64 @js_json_stringify(double, i32) +declare i64 @js_map_alloc(i32) +declare i64 @js_text_encoder_encode_into_llvm(double, double) +declare i64 @js_value_typeof(double) +declare i32 @js_string_starts_with(i64, i64) +declare i32 @js_string_ends_with(i64, i64) +declare i64 @js_string_search_value_to_string(double, i32) +declare i32 @js_string_starts_with_at(i64, i64, i32) +declare i32 @js_string_ends_with_at(i64, i64, i32) +declare i64 @js_closure_alloc(ptr, i32) +declare i64 @js_closure_alloc_singleton(ptr) +declare i64 @js_closure_alloc_with_captures_singleton(ptr, i32, ptr) +declare void @js_closure_set_capture_bits(i64, i32, i64) +declare i64 @js_closure_get_capture_bits(i64, i32) +declare void @js_closure_set_capture_f64(i64, i32, double) +declare double @js_closure_get_capture_f64(i64, i32) +declare void @js_register_closure_rest(ptr, i32) +declare void @js_register_closure_synthetic_arguments(ptr, i32) +declare void @js_register_closure_rest_and_arguments(ptr, i32) +declare void @js_register_closure_arity(ptr, i32) +declare void @js_register_closure_length(ptr, i32) +declare void @js_register_closure_arrow_function(ptr) +declare void @js_register_closure_strict_function(ptr) +declare void @js_register_closure_async_function(ptr) +declare void @js_register_closure_generator_function(ptr) +declare void @js_register_closure_async_generator_function(ptr) +declare i64 @js_closure_unbox_callee_checked(double) +declare i64 @js_closure_unbox_callee_checked_rebind(double, double) +declare double @js_closure_call0(i64) +declare double @js_closure_call1(i64, double) +declare double @js_closure_call2(i64, double, double) +declare double @js_closure_call3(i64, double, double, double) +declare double @js_closure_call4(i64, double, double, double, double) +declare double @js_closure_call5(i64, double, double, double, double, double) +declare double @js_closure_call6(i64, double, double, double, double, double, double) +declare double @js_closure_call7(i64, double, double, double, double, double, double, double) +declare double @js_closure_call8(i64, double, double, double, double, double, double, double, double) +declare double @js_closure_call9(i64, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call10(i64, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call11(i64, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call12(i64, double, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call13(i64, double, double, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call14(i64, double, double, double, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call15(i64, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) +declare double @js_closure_call16(i64, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) +declare i64 @js_array_map(i64, i64) +declare void @js_array_map_discard(i64, i64) +declare i64 @js_array_filter(i64, i64) +declare i64 @js_array_concat(i64, i64) +declare i64 @js_array_concat_new(i64, i64) +declare i64 @js_error_new() +declare i64 @js_error_new_with_message(i64) +declare i64 @js_error_new_from_value(double) +declare i64 @js_error_new_kind_from_value(i32, double) +declare i64 @js_error_new_with_cause_from_value(double, double) +declare i64 @js_error_new_kind_with_options_from_value(i32, double, double) +declare double @js_assert_assertion_error_ctor(double) +declare double @js_assert_assert_ctor(double) +declare void @js_throw_type_error_property_access(i32, ptr, i64) +declare void @js_throw_type_error_not_a_function(ptr, i64, ptr, i64) +declare void @js_throw_error_with_code(ptr, i64, ptr, i64, i32) +declare i64 @js_map_set(i64, double, double) +declare i64 @js_map_set_string_number(i64, i64, double) +declare i64 @js_map_set_string_key(i64, i64, double) +declare i64 @js_map_set_string_i32(i64, i64, i32) +declare i64 @js_map_set_string_u32(i64, i64, i32) +declare i64 @js_map_set_string_f32(i64, i64, float) +declare i64 @js_map_set_string_bool(i64, i64, i32) +declare i64 @js_map_set_string_string(i64, i64, i64) +declare i64 @js_map_set_number_key(i64, double, double) +declare double @js_map_get(i64, double) +declare double @js_map_get_string_key(i64, i64) +declare double @js_map_get_number_key(i64, double) +declare i32 @js_map_has(i64, double) +declare i32 @js_map_has_string_key(i64, i64) +declare i32 @js_map_has_number_key(i64, double) +declare i32 @js_map_delete(i64, double) +declare i32 @js_map_delete_string_key(i64, i64) +declare i32 @js_map_delete_number_key(i64, double) +declare i64 @js_object_keys(i64) +declare i64 @js_object_keys_value(double) +declare i64 @js_for_in_keys_value(double) +declare double @js_is_finite(double) +declare i32 @js_is_undefined_or_bare_nan(double) +declare double @js_math_min_array(i64) +declare double @js_math_max_array(i64) +declare double @js_math_min2(double, double) +declare double @js_math_max2(double, double) +declare i64 @js_string_coerce(double) +declare i64 @js_string_coerce_method_this(double, ptr, i64) +declare i64 @js_array_slice(i64, i32, i32) +declare i64 @js_array_slice_values(i64, double, double) +declare double @js_array_shift_f64(i64) +declare i64 @js_set_alloc(i32) +declare i64 @js_set_from_array(i64) +declare i64 @js_set_from_iterable(double) +declare i64 @js_map_from_array(i64) +declare i64 @js_map_from_iterable(double) +declare double @js_object_has_property(double, double) +declare double @js_in_operator(double, double) +declare double @js_private_brand_check(double, i32, ptr, i32) +declare double @js_private_guard(double, i32, ptr, i32, i32, i32) +declare double @js_fs_to_unix_timestamp(double) +declare i32 @js_fs_write_file_sync(double, double) +declare i32 @js_fs_write_file_sync_options(double, double, double) +declare i32 @js_fs_append_file_sync(double, double) +declare i32 @js_fs_append_file_sync_options(double, double, double) +declare i32 @js_fs_exists_sync(double) +declare i64 @js_fs_read_file_sync(double) +declare double @js_fs_read_file_dispatch(double, double) +declare double @js_fs_open_as_blob(double, double) +declare double @js_fs_promises_read_file(double, double) +declare double @js_fs_promises_write_file(double, double, double) +declare double @js_fs_promises_append_file(double, double, double) +declare double @js_fs_promises_mkdir(double, double) +declare double @js_fs_promises_rmdir(double, double) +declare i32 @js_fs_mkdir_sync(double) +declare i32 @js_fs_mkdir_sync_options(double, double) +declare i32 @js_fs_unlink_sync(double) +declare double @js_fs_readdir_sync(double, double) +declare double @js_fs_stat_sync(double) +declare double @js_fs_stat_sync_options(double, double) +declare double @js_fs_lstat_sync(double) +declare double @js_fs_lstat_sync_options(double, double) +declare i32 @js_fs_rename_sync(double, double) +declare i32 @js_fs_copy_file_sync(double, double) +declare i32 @js_fs_copy_file_sync_flags(double, double, double) +declare i32 @js_fs_cp_sync(double, double) +declare i32 @js_fs_cp_sync_options(double, double, double) +declare i32 @js_fs_chmod_sync(double, double) +declare i32 @js_fs_chown_sync(double, double, double) +declare i32 @js_fs_lchown_sync(double, double, double) +declare i32 @js_fs_lchmod_sync(double, double) +declare i32 @js_fs_truncate_sync(double, double) +declare i32 @js_fs_ftruncate_sync(double, double) +declare i32 @js_fs_fsync_sync(double) +declare i32 @js_fs_fdatasync_sync(double) +declare i32 @js_fs_fchmod_sync(double, double) +declare i32 @js_fs_fchown_sync(double, double, double) +declare double @js_fs_fstat_sync(double) +declare double @js_fs_fstat_sync_options(double, double) +declare i32 @js_fs_utimes_sync(double, double, double) +declare i32 @js_fs_lutimes_sync(double, double, double) +declare i32 @js_fs_futimes_sync(double, double, double) +declare double @js_fs_readv_sync(double, double, double) +declare double @js_fs_writev_sync(double, double, double) +declare double @js_fs_statfs_sync(double) +declare double @js_fs_statfs_sync_options(double, double) +declare double @js_fs_opendir_sync(double) +declare double @js_fs_glob_sync(double) +declare double @js_fs_glob_sync_options(double, double) +declare i32 @js_fs_link_sync(double, double) +declare i32 @js_fs_symlink_sync(double, double) +declare double @js_fs_symlink_callback(double, double, double, double) +declare i64 @js_fs_readlink_sync(double) +declare i64 @js_fs_readlink_sync_options(double, double) +declare double @js_fs_readlink_dispatch(double, double) +declare double @js_fs_open_sync(double, double) +declare i32 @js_fs_close_sync(double) +declare double @js_fs_read_sync(double, double, double, double, double) +declare double @js_fs_read_sync_options(double, double, double) +declare double @js_fs_write_sync(double, double) +declare double @js_fs_write_string_sync_options(double, double, double) +declare double @js_fs_write_buffer_sync(double, double, double, double, double) +declare double @js_fs_write_sync_options_dispatch(double, double, double) +declare i32 @js_fs_access_sync(double) +declare i32 @js_fs_access_sync_mode(double, double) +declare double @js_fs_access_sync_throw(double) +declare double @js_fs_access_sync_throw_mode(double, double) +declare i64 @js_fs_realpath_sync(double) +declare double @js_fs_realpath_dispatch(double, double) +declare i64 @js_fs_mkdtemp_sync(double) +declare i64 @js_fs_mkdtemp_sync_options(double, double) +declare double @js_fs_mkdtemp_dispatch(double, double) +declare double @js_fs_mkdtemp_disposable_sync(double, double) +declare i32 @js_fs_rmdir_sync(double) +declare i32 @js_fs_rmdir_sync_options(double, double) +declare i32 @js_fs_rm_recursive(double) +declare i32 @js_fs_rm_recursive_options(double, double) +declare double @js_fs_create_write_stream(double, double) +declare double @js_fs_create_read_stream(double, double) +declare double @js_fs_utf8_stream_new(double) +declare double @js_fs_utf8_stream_call_without_new(double) +declare double @js_fs_utf8_stream_write(double, double) +declare double @js_fs_utf8_stream_flush(double, double) +declare double @js_fs_utf8_stream_flush_sync(double) +declare double @js_fs_utf8_stream_end(double, double) +declare double @js_fs_utf8_stream_destroy(double) +declare double @js_fs_utf8_stream_reopen(double, double) +declare double @js_fs_utf8_stream_on(double, double, double) +declare double @js_fs_utf8_stream_once(double, double, double) +declare double @js_fs_utf8_stream_off(double, double, double) +declare double @js_fs_utf8_stream_remove_all(double, double) +declare double @js_fs_utf8_stream_listener_count(double, double) +declare double @js_fs_utf8_stream_emit(double, double, double) +declare double @js_fs_read_file_callback(double, double, double) +declare double @js_fs_stats_is_file(double) +declare double @js_fs_stats_is_directory(double) +declare i64 @js_fs_read_file_binary(double) +declare double @js_number_coerce(double) +declare double @js_math_to_number(double) +declare i64 @js_set_add(i64, double) +declare i64 @js_set_add_string(i64, i64) +declare i64 @js_set_add_number(i64, double) +declare i64 @js_set_add_i32(i64, i32) +declare i64 @js_set_add_u32(i64, i32) +declare i64 @js_set_add_f32(i64, float) +declare i64 @js_set_add_bool(i64, i32) +declare i32 @js_set_has(i64, double) +declare i32 @js_set_has_string(i64, i64) +declare i32 @js_set_has_number(i64, double) +declare i32 @js_set_has_i32(i64, i32) +declare i32 @js_set_has_u32(i64, i32) +declare i32 @js_set_has_f32(i64, float) +declare i32 @js_set_has_bool(i64, i32) +declare i32 @js_set_delete(i64, double) +declare i32 @js_set_delete_string(i64, i64) +declare i32 @js_set_delete_number(i64, double) +declare i32 @js_set_delete_i32(i64, i32) +declare i32 @js_set_delete_u32(i64, i32) +declare i32 @js_set_delete_f32(i64, float) +declare i32 @js_set_delete_bool(i64, i32) +declare i32 @js_set_size(i64) +declare i64 @js_set_union(i64, double) +declare i64 @js_set_intersection(i64, double) +declare i64 @js_set_difference(i64, double) +declare i64 @js_set_symmetric_difference(i64, double) +declare i32 @js_set_is_subset_of(i64, double) +declare i32 @js_set_is_superset_of(i64, double) +declare i32 @js_set_is_disjoint_from(i64, double) +declare i64 @js_string_to_lower_case(i64) +declare i64 @js_string_to_upper_case(i64) +declare i64 @js_string_to_locale_lower_case(i64, double) +declare i64 @js_string_to_locale_upper_case(i64, double) +declare void @js_string_validate_collator_args(double, double) +declare i64 @js_string_trim(i64) +declare i64 @js_string_trim_start(i64) +declare i64 @js_string_trim_end(i64) +declare i64 @js_string_big(i64) +declare i64 @js_string_blink(i64) +declare i64 @js_string_bold(i64) +declare i64 @js_string_fixed(i64) +declare i64 @js_string_italics(i64) +declare i64 @js_string_small(i64) +declare i64 @js_string_strike(i64) +declare i64 @js_string_sub(i64) +declare i64 @js_string_sup(i64) +declare i64 @js_string_anchor(i64, i64) +declare i64 @js_string_link(i64, i64) +declare i64 @js_string_fontcolor(i64, i64) +declare i64 @js_string_fontsize(i64, i64) +declare i64 @js_string_char_at(i64, i32) +declare double @js_string_index_get(i64, double) +declare double @js_string_index_get_boxed(double, double) +declare i32 @js_string_index_to_i32(double) +declare i32 @js_string_end_index_to_i32(double, i32) +declare double @js_dyn_index_get(double, double) +declare double @js_dyn_index_set(double, double, double) +declare i64 @js_string_to_char_array(i64) +declare i64 @js_string_repeat(i64, double) +declare i64 @js_string_replace_string(i64, i64, i64) +declare i64 @js_string_replace_all_string(i64, i64, i64) +declare i32 @js_string_equals(i64, i64) +declare i32 @js_string_compare(i64, i64) +declare i32 @js_jsvalue_equals(double, double) +declare i32 @js_string_compare_value(double, double) +declare i64 @js_jsvalue_to_string_radix(double, double) +declare double @js_math_random() +declare double @js_webassembly_validate(double) +declare double @js_webassembly_compile(double) +declare double @js_webassembly_module_new(double) +declare double @js_webassembly_module_exports(double) +declare double @js_webassembly_module_imports(double) +declare double @js_webassembly_module_custom_sections(double, double) +declare double @js_webassembly_instantiate(double, double) +declare double @js_wasi_emit_warning() +declare double @js_webassembly_call_export_0(double, double) +declare double @js_webassembly_call_export_1(double, double, double) +declare double @js_webassembly_call_export_2(double, double, double, double) +declare double @js_webassembly_call_export_3(double, double, double, double, double) +declare double @js_webassembly_call_export_4(double, double, double, double, double, double) +declare void @js_console_log_spread(i64) +declare void @js_console_info_spread(i64) +declare void @js_console_debug_spread(i64) +declare void @js_console_error_spread(i64) +declare void @js_console_warn_spread(i64) +declare double @js_util_format(i64) +declare double @js_util_format_with_options(double, i64) +declare double @js_util_inspect(double, double) +declare double @js_util_debuglog(double, double) +declare double @js_util_diff(double, double) +declare double @js_util_inherits(double, double) +declare double @js_util_is_deep_strict_equal(double, double) +declare double @js_util_strip_vt_control_characters(double) +declare double @js_util_style_text(double, double, double) +declare double @js_util_get_call_sites(double, double) +declare double @js_util_promisify(double) +declare double @js_util_callbackify(double) +declare double @js_util_deprecate(double, double, double) +declare double @js_util_aborted(double, double) +declare double @js_util_transferable_abort_controller() +declare double @js_util_transferable_abort_signal(double) +declare double @js_util_parse_args(double) +declare double @js_boxed_number_new(double) +declare double @js_boxed_string_new(double, i32) +declare double @js_boxed_boolean_new(double) +declare double @js_util_types_is_arguments_object(double) +declare double @js_util_types_is_promise(double) +declare double @js_util_types_is_big_int_object(double) +declare double @js_util_types_is_symbol_object(double) +declare double @js_util_types_is_array_buffer(double) +declare double @js_util_types_is_shared_array_buffer(double) +declare double @js_util_types_is_any_array_buffer(double) +declare double @js_util_types_is_array_buffer_view(double) +declare double @js_util_types_is_data_view(double) +declare double @js_util_types_is_typed_array(double) +declare double @js_util_types_is_uint8_array(double) +declare double @js_util_types_is_int8_array(double) +declare double @js_util_types_is_int16_array(double) +declare double @js_util_types_is_uint16_array(double) +declare double @js_util_types_is_int32_array(double) +declare double @js_util_types_is_uint32_array(double) +declare double @js_util_types_is_float16_array(double) +declare double @js_util_types_is_float32_array(double) +declare double @js_util_types_is_float64_array(double) +declare double @js_util_types_is_uint8_clamped_array(double) +declare double @js_util_types_is_big_int64_array(double) +declare double @js_util_types_is_big_uint64_array(double) +declare double @js_util_types_is_map(double) +declare double @js_util_types_is_weak_map(double) +declare double @js_util_types_is_set(double) +declare double @js_util_types_is_weak_set(double) +declare double @js_util_types_is_date(double) +declare double @js_util_types_is_reg_exp(double) +declare double @js_util_types_is_async_function(double) +declare double @js_util_types_is_generator_function(double) +declare double @js_util_types_is_generator_object(double) +declare double @js_util_types_is_native_error(double) +declare double @js_util_types_is_number_object(double) +declare double @js_util_types_is_string_object(double) +declare double @js_util_types_is_boolean_object(double) +declare double @js_util_types_is_boxed_primitive(double) +declare double @js_util_types_is_external(double) +declare double @js_util_types_is_module_namespace_object(double) +declare double @js_util_types_is_key_object(double) +declare double @js_util_types_is_crypto_key(double) +declare double @js_util_types_is_proxy(double) +declare double @js_util_types_is_map_iterator(double) +declare double @js_util_types_is_set_iterator(double) +declare double @js_data_view_new(double, double, double) +declare double @js_data_view_get_direct(double, double, double, i32, i32) +declare double @js_data_view_set_direct(double, double, double, double, i32, i32) +declare i64 @js_getenv(i64) +declare double @js_getenv_value(i64) +declare void @js_setenv(i64, double) +declare void @js_removeenv(i64) +declare double @js_process_exit_code_get() +declare double @js_process_exit_code_set(double) +declare void @js_console_table(double) +declare void @js_console_table_with_properties(double, double) +declare void @js_console_trace(double) +declare void @js_console_trace_spread(i64) +declare i64 @js_process_cwd() +declare i64 @js_process_argv() +declare double @js_process_pid() +declare double @js_process_ppid() +declare double @js_process_uptime() +declare i64 @js_process_version() +declare double @js_process_versions() +declare double @js_process_memory_usage() +declare double @js_bigint_as_int_n_call(double, double) +declare double @js_bigint_as_uint_n_call(double, double) +declare double @js_v8_serialize(double) +declare double @js_v8_deserialize(double) +declare double @js_v8_get_heap_statistics() +declare double @js_v8_get_heap_code_statistics() +declare double @js_v8_get_heap_space_statistics() +declare double @js_v8_cached_data_version_tag() +declare double @js_v8_get_heap_snapshot(double) +declare double @js_v8_write_heap_snapshot(double, double) +declare double @js_v8_gc_profiler_new() +declare double @js_v8_gc_profiler_start(double) +declare double @js_v8_gc_profiler_stop(double) +declare double @js_v8_gc_profiler_report() +declare double @js_v8_serializer_new(double) +declare double @js_v8_deserializer_new(double) +declare double @js_v8_noop_undefined() +declare double @js_v8_is_building_snapshot() +declare double @js_v8_namespace(ptr, i64) +declare double @js_v8_throw_not_building_snapshot() +declare double @js_v8_promise_hook_register() +declare double @js_v8_promise_hooks_on_init(double) +declare double @js_v8_promise_hooks_on_before(double) +declare double @js_v8_promise_hooks_on_after(double) +declare double @js_v8_promise_hooks_on_settled(double) +declare double @js_v8_promise_hooks_create_hook(double) +declare double @js_process_thread_cpu_usage(double) +declare double @js_process_available_memory() +declare double @js_process_constrained_memory() +declare double @js_process_source_maps_enabled() +declare double @js_process_set_source_maps_enabled(double) +declare double @js_process_has_uncaught_exception_capture_callback() +declare double @js_process_set_uncaught_exception_capture_callback(double) +declare double @js_process_add_uncaught_exception_capture_callback(double) +declare double @js_process_getuid() +declare double @js_process_geteuid() +declare double @js_process_getgid() +declare double @js_process_getegid() +declare void @js_process_emit_warning(double, double, double) +declare double @js_process_cpu_usage(double) +declare double @js_process_resource_usage() +declare double @js_process_active_resources_info() +declare double @js_process_env() +declare double @js_process_hrtime_bigint() +declare double @js_process_hrtime(double) +declare double @js_process_title() +declare void @js_process_set_title(double) +declare void @js_process_chdir(i64) +declare void @js_process_chdir_jsv(double) +declare double @js_process_kill(double, double) +declare void @js_process_exit(double) +declare void @js_process_abort() +declare double @js_process_umask() +declare double @js_process_umask_set(double) +declare double @js_process_on(i64, i64) +declare double @js_process_add_listener(i64, i64) +declare double @js_process_once(i64, i64) +declare double @js_process_prepend_listener(i64, i64) +declare double @js_process_prepend_once_listener(i64, i64) +declare double @js_process_emit(i64, i64) +declare void @js_process_emit_before_exit(double) +declare void @js_process_run_finalization_exit() +declare void @js_trace_events_flush_output() +declare void @js_promise_report_unhandled_rejections() +declare i32 @js_process_pending_exit_code() +declare void @js_gc_release_current_thread_collection_side_allocations() +declare double @js_process_remove_listener(i64, i64) +declare double @js_process_off(i64, i64) +declare double @js_process_remove_all_listeners(i64) +declare double @js_process_listener_count(i64, i64) +declare i64 @js_process_listeners(i64) +declare i64 @js_process_raw_listeners(i64) +declare i64 @js_process_event_names() +declare double @js_process_set_max_listeners(double) +declare double @js_process_get_max_listeners() +declare double @js_process_get_builtin_module(double) +declare double @js_process_get_builtin_module_devirt(double) +declare double @js_process_execve(double, double, double) +declare double @js_module_is_builtin(double) +declare double @js_module_find_package_json(double, double) +declare double @js_module_register(double, double, double) +declare double @js_module_register_hooks(double) +declare void @js_process_next_tick(i64, i64) +declare double @js_process_stdin() +declare double @js_process_stdout() +declare double @js_process_stderr() +declare double @js_readline_set_raw_mode(double) +declare void @js_readline_stdin_on(i64, i64) +declare double @js_readline_stdin_remove_listener(i64, i64) +declare double @js_readline_stdin_pause() +declare double @js_readline_stdin_resume() +declare double @js_readline_stdin_unref() +declare double @js_readline_stdin_ref() +declare double @js_readline_stdin_destroy() +declare double @js_tty_isatty(double) +declare double @js_tty_read_stream_new(double) +declare double @js_tty_write_stream_new(double) +declare double @js_wasi_constructor_call(double) +declare double @js_process_stdin_isatty() +declare double @js_process_stdout_isatty() +declare double @js_process_stderr_isatty() +declare double @js_process_stdout_columns() +declare double @js_process_stdout_rows() +declare double @js_process_stdout_on(i64, i64) +declare i64 @js_os_platform() +declare i64 @js_os_arch() +declare i64 @js_os_type() +declare i64 @js_os_release() +declare i64 @js_os_hostname() +declare i64 @js_os_eol() +declare double @js_os_available_parallelism() +declare i64 @js_os_endianness() +declare i64 @js_os_dev_null() +declare i64 @js_os_machine() +declare i64 @js_os_loadavg() +declare i64 @js_os_version() +declare i64 @js_box_alloc_bits(i64) +declare i64 @js_box_get_bits(i64) +declare void @js_box_set_bits(i64, i64) +declare i64 @js_box_alloc(double) +declare double @js_box_get(i64) +declare void @js_box_set(i64, double) +declare i64 @js_i32_box_alloc(i32) +declare i32 @js_i32_box_get(i64) +declare void @js_i32_box_set(i64, i32) +declare i64 @js_bool_box_alloc(i32) +declare i32 @js_bool_box_get(i64) +declare void @js_bool_box_set(i64, i32) +declare i64 @js_arguments_object_alloc(double, double, i32) +declare void @js_arguments_object_map_index(i64, i32, i64) +declare i64 @js_array_like_to_array(double) +declare i32 @js_object_get_class_id(i64) +declare i64 @js_object_alloc_with_parent(i32, i32, i32) +declare i64 @js_object_alloc_class_with_keys(i32, i32, i32, ptr, i32) +declare i64 @js_object_alloc_class_dynamic_parent(i32, i32, ptr, i32) +declare i64 @js_object_alloc_class_inline_keys(i32, i32, i32, i64) +declare i64 @js_build_class_keys_array(i32, i32, ptr, i32) +declare ptr @js_inline_arena_state() +declare ptr @js_inline_arena_slow_alloc(ptr, i64, i64) +declare i32 @js_object_delete_field(i64, i64) +declare i32 @js_object_delete_field_value(double, i64) +declare i32 @js_object_delete_dynamic_value(double, double) +declare double @js_delete_result(i32, i32) +declare i64 @js_eq(i64, i64) +declare i64 @js_loose_eq(i64, i64) +declare i64 @js_number_to_fixed(double, double) +declare i64 @js_string_replace_regex(i64, i64, i64) +declare i64 @js_string_replace_all_regex(i64, i64, i64) +declare double @js_array_at(i64, double) +declare double @js_date_get_time(double) +declare double @js_date_get_full_year(double) +declare double @js_date_get_month(double) +declare double @js_date_get_date(double) +declare double @js_date_get_day(double) +declare double @js_date_get_hours(double) +declare double @js_date_get_minutes(double) +declare double @js_date_get_seconds(double) +declare double @js_date_get_milliseconds(double) +declare double @js_date_get_utc_day(double) +declare double @js_date_get_utc_full_year(double) +declare double @js_date_get_utc_month(double) +declare double @js_date_get_utc_date(double) +declare double @js_date_get_utc_hours(double) +declare double @js_date_get_utc_minutes(double) +declare double @js_date_get_utc_seconds(double) +declare double @js_date_get_utc_milliseconds(double) +declare double @js_date_value_of(double) +declare double @js_date_get_timezone_offset(double) +declare double @js_date_coerce_number(double) +declare double @js_rel_lt(double, double) +declare double @js_rel_le(double, double) +declare double @js_rel_gt(double, double) +declare double @js_rel_ge(double, double) +declare i64 @js_date_to_string(double) +declare i64 @js_date_to_iso_string(double) +declare i64 @js_date_to_iso_string_or_throw(double) +declare double @js_date_new_from_timestamp(double) +declare double @js_date_new_from_value(double) +declare i32 @js_array_indexOf_f64(i64, double) +declare i64 @js_array_indexOf_jsvalue(i64, double, double, i32) +declare i64 @js_array_last_index_of_jsvalue(i64, double, double, i32) +declare i32 @js_array_includes_f64(i64, double) +declare i32 @js_array_includes_jsvalue(i64, double, double, i32) +declare i32 @js_map_size(i64) +declare void @js_map_clear(i64) +declare void @js_set_clear(i64) +declare i64 @js_map_entries(i64) +declare i64 @js_map_keys(i64) +declare i64 @js_map_values(i64) +declare double @js_map_entry_key_at(i64, i32) +declare double @js_map_entry_value_at(i64, i32) +declare double @js_map_find_key_index(double, double) +declare double @js_set_find_value_index(double, double) +declare void @js_map_foreach(i64, double, double) +declare void @js_set_foreach(i64, double, double) +declare i64 @js_map_entries_iter_obj(i64) +declare i64 @js_map_keys_iter_obj(i64) +declare i64 @js_map_values_iter_obj(i64) +declare i64 @js_set_values_iter_obj(i64) +declare i64 @js_set_keys_iter_obj(i64) +declare i64 @js_set_entries_iter_obj(i64) +declare i64 @js_set_to_array(i64) +declare double @js_set_value_at(i64, i32) +declare i64 @js_array_splice(i64, i32, i32, ptr, i32, ptr) +declare i32 @js_array_splice_delete_count(double) +declare double @js_parse_int(i64, double) +declare double @js_parse_float(i64) +declare double @js_array_reduce(i64, i64, i32, double) +declare double @js_array_reduce_right(i64, i64, i32, double) +declare i64 @js_array_sort_default(i64) +declare i64 @js_array_reverse(i64) +declare double @js_array_reverse_value(double) +declare i64 @js_array_flat(i64) +declare i64 @js_array_flat_depth(i64, double) +declare i64 @js_array_flatMap(i64, i64) +declare i64 @js_array_sort_with_comparator(i64, i64) +declare i64 @js_validate_array_comparator(double) +declare i64 @js_validate_array_callback(double) +declare i64 @js_validate_array_map_callback(i64, double) +declare i64 @js_array_to_reversed(i64) +declare i64 @js_array_to_sorted_default(i64) +declare i64 @js_array_to_sorted_with_comparator(i64, i64) +declare i64 @js_array_to_spliced(i64, double, double, ptr, i32) +declare i64 @js_array_with(i64, double, double) +declare i64 @js_array_copy_within(i64, double, double, i32, double) +declare double @js_array_copy_within_value(double, double, double, i32, double) +declare i64 @js_regexp_new(i64, i64) +declare i64 @js_regexp_construct(double, double) +declare i64 @js_regexp_construct_call(double, double) +declare i32 @js_regexp_test(i64, i64) +declare double @js_regexp_escape(double) +declare i64 @js_get_string_pointer_unified(double) +declare i32 @js_switch_strict_equals(double, double) +declare i64 @js_value_to_str_ptr_for_ffi(double) +declare void @js_string_addref(i64) +declare void @js_string_addref_if_heap_string(double) +declare i64 @js_bigint_from_string(ptr, i32) +declare i64 @js_bigint_from_f64(double) +declare i64 @js_bigint_from_i128_parts(i64, i64) +declare i32 @js_bigint_cmp(i64, i64) +declare double @js_dynamic_add(double, double) +declare double @js_to_numeric(double) +declare double @js_numeric_step(double, i32) +declare double @js_dynamic_string_or_number_add(double, double) +declare double @js_dynamic_sub(double, double) +declare double @js_dynamic_mul(double, double) +declare double @js_dynamic_div(double, double) +declare double @js_dynamic_mod(double, double) +declare double @js_dynamic_bitand(double, double) +declare double @js_dynamic_bitor(double, double) +declare double @js_dynamic_bitxor(double, double) +declare double @js_dynamic_shl(double, double) +declare double @js_dynamic_shr(double, double) +declare double @js_dynamic_bitnot(double) +declare double @js_dynamic_pow(double, double) +declare double @js_dynamic_ushr(double, double) +declare double @js_instanceof(double, i32) +declare double @js_instanceof_dynamic(double, double) +declare double @js_instanceof_noncallable_rhs() +declare void @js_register_class_extends_error(i32) +declare void @js_register_class_extends_data_view(i32) +declare void @js_register_class_id(i32) +declare void @js_register_class_name(i32, ptr, i32) +declare void @js_register_anon_shape_class_id(i32) +declare double @js_get_global_this_builtin_value(ptr, i64) +declare double @js_promise_static_function_value(ptr, i64) +declare double @js_builtin_prototype_method_value(ptr, i64, ptr, i64) +declare void @js_register_class_parent(i32, i32) +declare void @js_register_class_parent_dynamic(i32, double) +declare double @js_get_dynamic_parent_value(i32) +declare void @js_class_register_capture_values(i32, ptr, i64) +declare void @js_class_object_refresh_capture_values(double, i64, double) +declare void @js_tdz_suppress_begin() +declare void @js_tdz_suppress_end() +declare double @js_class_capture_value(i32, i32) +declare double @js_class_capture_value_for_receiver(double, i32, i32) +declare double @js_class_capture_value_or(i32, i32, double) +declare double @js_param_or_class_capture_value(double, i32, i32) +declare void @js_super_construct_apply(i32, double, double) +declare double @js_super_method_call_dynamic(i32, ptr, i64, double, ptr, i64) +declare double @js_super_method_call_dynamic_apply(i32, ptr, i64, double, double) +declare i64 @js_array_push_spread_any(i64, double) +declare i32 @js_set_function_prototype(double, double) +declare void @js_register_prototype_method(i32, ptr, i64, double) +declare i32 @js_register_function_prototype_method(double, ptr, i64, double) +declare double @js_new_function_construct(double, ptr, i64) +declare double @js_function_ctor_from_strings(ptr, i64) +declare double @js_new_function_construct_apply(double, double) +declare double @js_throw_not_a_constructor() +declare double @js_new_target_value() +declare double @js_get_function_prototype_method(double, ptr, i64) +declare double @js_function_prototype_value_for_read(double) +declare i64 @js_typeerror_new(i64) +declare i64 @js_rangeerror_new(i64) +declare i64 @js_syntaxerror_new(i64) +declare i64 @js_referenceerror_new(i64) +declare double @js_throw_symbol_constructor_type_error() +declare double @js_throw_bigint_constructor_type_error() +declare double @js_throw_strict_eval_arguments_syntax_error() +declare double @js_throw_eval_syntax_error(double) +declare double @js_throw_restricted_function_property_assignment() +declare double @js_throw_math_constructor_type_error() +declare double @js_throw_json_constructor_type_error() +declare double @js_webcrypto_illegal_constructor() +declare double @js_throw_type_error_const_assignment(double) +declare double @js_throw_reference_error_unresolvable_assignment(double) +declare double @js_throw_reference_error_unresolved_get() +declare double @js_with_implicit_unset() +declare double @js_with_implicit_read(double, double) +declare double @js_iterator_result_validate(double) +declare double @js_global_get_or_throw_unresolved(double) +declare double @js_module_ambient_require() +declare double @js_module_ambient_require_apply(double) +declare double @js_module_dynamic_import_fallback(double) +declare double @js_module_dynamic_import_deferred(double, double) +declare double @js_module_create_require_devirt(double) +declare double @js_global_get_optional(double) +declare double @js_global_update(double, double, double) +declare double @js_global_assign_existing_or_throw(double, double) +declare double @js_throw_reference_error_this_before_super() +declare double @js_throw_reference_error_super_delete() +declare double @js_throw_reference_error_unresolved_assignment() +declare i64 @js_evalerror_new(i64) +declare i64 @js_urierror_new(i64) +declare i64 @js_weakmap_new() +declare i64 @js_weakset_new() +declare double @js_weakmap_init_iterable(double, double) +declare double @js_weakset_init_iterable(double, double) +declare double @js_weakmap_set(double, double, double) +declare double @js_weakmap_get(double, double) +declare double @js_weakmap_has(double, double) +declare double @js_weakmap_delete(double, double) +declare double @js_weakset_add(double, double) +declare double @js_weakset_has(double, double) +declare double @js_weakset_delete(double, double) +declare double @js_weak_throw_primitive() +declare i64 @js_buffer_from_string(i64, i32) +declare i32 @js_encoding_tag_from_value(double) +declare i64 @js_value_to_string_with_encoding(double, i32) +declare i64 @js_value_to_string_with_encoding_or_radix(double, i32, double) +declare i64 @js_object_values(i64) +declare i64 @js_object_values_value(double) +declare i64 @js_object_entries(i64) +declare i64 @js_object_entries_value(double) +declare i64 @js_path_join(i64, i64) +declare i64 @js_path_win32_join(i64, i64) +declare i64 @js_path_win32_dirname(i64) +declare i64 @js_path_win32_basename(i64) +declare i64 @js_path_win32_basename_ext(i64, i64) +declare i64 @js_path_win32_extname(i64) +declare i32 @js_path_win32_is_absolute(i64) +declare i64 @js_path_win32_normalize(i64) +declare i64 @js_path_win32_parse(i64) +declare i64 @js_path_win32_format(double) +declare i64 @js_path_win32_relative(i64, i64) +declare i64 @js_path_win32_relative_checked(double, double) +declare i64 @js_path_win32_resolve(i64) +declare i64 @js_path_win32_resolve_join(i64, i64) +declare i64 @js_path_win32_to_namespaced_path(i64) +declare double @js_path_win32_to_namespaced_path_value(double) +declare i32 @js_path_win32_matches_glob(i64, i64) +declare i64 @js_path_win32_sep_get() +declare i64 @js_path_win32_delimiter_get() +declare i64 @js_path_dirname(i64) +declare i64 @js_path_resolve(i64) +declare i64 @js_path_relative(i64, i64) +declare i64 @js_path_relative_checked(double, double) +declare i64 @js_path_to_namespaced_path(i64) +declare double @js_path_to_namespaced_path_value(double) +declare i32 @js_path_matches_glob(i64, i64) +declare i64 @js_path_resolve_join(i64, i64) +declare double @js_object_from_entries(double) +declare i64 @js_string_match(i64, i64) +declare i64 @js_string_match_all(i64, i64) +declare i64 @js_string_match_all_value(i64, double) +declare double @llvm.log.f64(double) +declare double @llvm.log2.f64(double) +declare double @llvm.log10.f64(double) +declare double @llvm.exp.f64(double) +declare double @llvm.sin.f64(double) +declare double @llvm.cos.f64(double) +declare i64 @js_path_basename(i64) +declare i64 @js_path_basename_ext(i64, i64) +declare i64 @js_path_extname(i64) +declare i64 @js_path_sep_get() +declare i64 @js_path_delimiter_get() +declare i64 @js_path_parse(i64) +declare i64 @js_json_parse(i64) +declare i64 @js_json_text_to_string(double) +declare double @js_json_raw_json(double) +declare double @js_json_is_raw_json(double) +declare i64 @js_json_parse_or_null(i64) +declare i64 @js_json_parse_typed_array(i64, i64, i32, i32) +declare i64 @js_date_to_date_string(double) +declare i64 @js_date_to_time_string(double) +declare i64 @js_date_to_utc_string(double) +declare i64 @js_date_to_locale_date_string(double) +declare i64 @js_date_to_locale_time_string(double) +declare i64 @js_date_to_json(double) +declare i64 @js_regexp_exec(i64, i64) +declare i64 @js_number_to_precision(double, double) +declare i64 @js_number_to_exponential(double, double) +declare double @js_date_new() +declare double @js_number_is_integer(double) +declare double @js_number_is_nan(double) +declare double @js_number_is_safe_integer(double) +declare double @js_date_parse(i64) +declare double @js_date_utc(ptr, i32) +declare double @js_date_new_local_components(double, double, double, double, double, double, double) +declare double @js_date_apply_setter(double, i32, i32, ptr, i32) +declare double @js_math_clz32(double) +declare double @js_math_cbrt(double) +declare double @js_math_fround(double) +declare double @js_math_f16round(double) +declare double @js_math_sinh(double) +declare double @js_math_cosh(double) +declare double @js_math_tanh(double) +declare double @js_math_asinh(double) +declare double @js_math_acosh(double) +declare double @js_math_atanh(double) +declare double @js_math_hypot(double, double) +declare double @js_object_is(double, double) +declare i64 @js_path_normalize(i64) +declare i64 @js_path_format(double) +declare i32 @js_path_is_absolute(i64) +declare i64 @js_encode_uri(double) +declare i64 @js_decode_uri(double) +declare i64 @js_encode_uri_component(double) +declare i64 @js_decode_uri_component(double) +declare i64 @js_text_encoder_new() +declare i64 @js_text_decoder_new(double, double, double) +declare i64 @js_text_encoder_encode_llvm(double) +declare i64 @js_text_decoder_decode_llvm(double, double) +declare i64 @js_text_decoder_encoding(double) +declare double @js_text_decoder_fatal(double) +declare double @js_text_decoder_ignore_bom(double) +declare void @js_queue_microtask(i64) +declare void @js_queue_next_tick(i64) +declare void @js_queue_next_tick_args(i64, ptr, i32) +declare void @js_drain_queued_microtasks() +declare i64 @js_uint8array_from_array(i64) +declare i64 @js_uint8array_alloc(i32) +declare i64 @js_uint8array_new(double) +declare i64 @js_uint8array_view(double, double, double) +declare i64 @js_typed_array_new_empty(i32, i32) +declare i64 @js_typed_array_new_from_array(i32, i64) +declare i64 @js_typed_array_new(i32, double) +declare i64 @js_typed_array_view(i32, double, double, double) +declare i32 @js_typed_array_length(i64) +declare double @js_typed_array_get(i64, i32) +declare i32 @js_typed_array_read_int32(i64, i32) +declare double @js_typed_array_read_f64(i64, i32) +declare double @js_typed_array_index_get_dynamic(i64, double) +declare double @js_typed_array_at(i64, double) +declare void @js_typed_array_set(i64, i32, double) +declare double @js_typed_array_index_set_dynamic(i64, double, double) +declare i32 @js_uint8array_get(i64, i32) +declare double @js_uint8array_index_get_value(i64, i32) +declare void @js_uint8array_set(i64, i32, i32) +declare i64 @js_native_arena_alloc(i64) +declare i64 @js_native_arena_view(i64, i32, i64, i64) +declare i64 @js_native_pod_view(i64, i64, i64, i64, i64, i64) +declare ptr @js_native_abi_check_pod_view_data_ptr(double, i64) +declare i64 @js_native_abi_check_pod_view_record_count(double, i64) +declare void @js_native_arena_dispose(i64) +declare void @js_native_memory_fill_u32(i64, double) +declare void @js_native_memory_copy(i64, i64) +declare i64 @js_typed_array_to_reversed(i64) +declare i64 @js_typed_array_to_sorted_default(i64) +declare i64 @js_typed_array_to_sorted_with_comparator(i64, i64) +declare i64 @js_typed_array_with(i64, double, double) +declare double @js_typed_array_find_last(i64, i64) +declare double @js_typed_array_find_last_index(i64, i64) +declare double @js_typed_array_set_from(i64, double, double) +declare i64 @js_typed_array_subarray(i64, i32, double, i32, double) +declare double @js_object_has_own(double, double) +declare double @js_object_property_is_enumerable(double, double) +declare double @js_object_define_getter(double, double, double) +declare double @js_object_define_setter(double, double, double) +declare double @js_object_lookup_getter(double, double) +declare double @js_object_lookup_setter(double, double) +declare double @js_object_get_own_field_or_undef(double, ptr, i64) +declare double @js_unresolved_namespace_stub() +declare double @js_node_submodule_export_as_function(ptr, i32, ptr, i32) +declare double @js_node_submodule_namespace_member(ptr, i32, ptr, i32) +declare double @js_node_submodule_namespace(ptr, i32) +declare void @js_node_submod_install_vm() +declare void @js_node_submod_install_timers() +declare void @js_node_submod_install_timers_promises() +declare void @js_node_submod_install_fs_promises() +declare void @js_node_submod_install_readline_promises() +declare void @js_node_submod_install_stream_promises() +declare void @js_node_submod_install_stream_consumers() +declare void @js_node_submod_install_stream_web() +declare void @js_node_submod_install_hono_jsx_server() +declare void @js_node_submod_install_hono_jsx_streaming() +declare void @js_node_submod_install_sys() +declare void @js_node_submod_install_diagnostics_channel() +declare void @js_node_submod_install_trace_events() +declare void @js_node_submod_install_test() +declare void @js_node_submod_install_test_reporters() +declare void @js_node_submod_install_all() +declare void @js_node_submod_enable_install_all() +declare double @js_unresolved_default_call() +declare double @js_get_global_this() +declare double @js_module_top_this() +declare double @js_global_or_console_property_by_name(i64) +declare void @js_class_register_static_symbol(i32, double, double) +declare void @js_register_class_computed_method(i64, double, i64, i64, i64, i64) +declare void @js_register_class_computed_accessor(i64, double, i64, i64, i64) +declare void @js_class_register_static_field(i32, ptr, i64, double) +declare double @js_object_define_property(double, double, double) +declare double @js_object_get_own_property_descriptor(double, double) +declare double @js_object_get_own_property_descriptors(double) +declare double @js_object_get_own_property_names(double) +declare double @js_symbol_new(double) +declare double @js_symbol_new_empty() +declare double @js_symbol_for(double) +declare double @js_symbol_computed_member(double, double) +declare double @js_symbol_key_for(double) +declare double @js_symbol_description(double) +declare i64 @js_symbol_to_string(double) +declare i32 @js_symbol_equals(double, double) +declare i32 @js_is_symbol(double) +declare i64 @js_object_get_own_property_symbols(double) +declare double @js_object_set_symbol_property(double, double, double) +declare double @js_to_property_key(double) +declare double @js_object_set_property_key(double, double, double) +declare double @js_object_get_property_key(double, double) +declare double @js_object_set_property_key_method(double, double, double) +declare double @js_object_super_get(double, double, double) +declare double @js_object_super_put_value_set(double, double, double, double, i32) +declare double @js_object_super_call(double, double, double, ptr, i64) +declare double @js_object_literal_infer_computed_function_name(double, double) +declare double @js_object_get_symbol_property(double, double) +declare double @js_object_create(double) +declare double @js_object_create_with_props(double, double) +declare double @js_object_freeze(double) +declare double @js_object_seal(double) +declare double @js_object_prevent_extensions(double) +declare void @js_object_copy_own_fields(i64, double) +declare double @js_object_assign_validate_target(double) +declare double @js_object_assign_one(double, double) +declare double @js_string_at(i64, i32) +declare double @js_string_code_point_at(i64, i32) +declare i64 @js_string_from_code_point(double) +declare i64 @js_string_raw(double, double) +declare i64 @js_string_from_char_code(double) +declare i64 @js_string_from_char_code_array(double) +declare double @js_string_char_code_at(i64, i32) +declare i32 @js_string_last_index_of(i64, i64) +declare i32 @js_string_last_index_of_from(i64, i64, double, i32) +declare double @js_string_locale_compare(i64, i64) +declare double @js_string_locale_compare_opts(i64, i64, double) +declare i64 @js_string_normalize(i64, double) +declare i64 @js_string_pad_start(i64, double, i64) +declare i64 @js_string_pad_end(i64, double, i64) +declare i64 @js_string_pad_fill(double) +declare double @js_string_is_well_formed(i64) +declare i64 @js_string_to_well_formed(i64) +declare i32 @js_string_search_regex(i64, i64) +declare i32 @js_string_search_value(i64, double) +declare i64 @js_string_match_value(i64, double) +declare double @js_regexp_exec_get_index() +declare i64 @js_regexp_exec_get_groups() +declare double @js_regexp_get_last_index(i64) +declare void @js_regexp_set_last_index(i64, double) +declare i64 @js_regexp_get_source(i64) +declare i64 @js_regexp_get_flags(i64) +declare i64 @js_string_replace_regex_named(i64, i64, i64) +declare i64 @js_string_replace_all_regex_named(i64, i64, i64) +declare i64 @js_string_replace_string_fn(i64, i64, double) +declare i64 @js_string_replace_string_dyn(i64, i64, double) +declare i64 @js_string_replace_all_string_dyn(i64, i64, double) +declare i64 @js_string_replace_regex_dyn(i64, i64, double) +declare i64 @js_string_replace_all_regex_dyn(i64, i64, double) +declare i64 @js_string_replace_search_dyn(i64, double, double) +declare i64 @js_string_replace_all_search_dyn(i64, double, double) +declare i64 @js_string_replace_all_string_fn(i64, i64, double) +declare i64 @js_string_replace_regex_fn(i64, i64, double) +declare i64 @js_string_replace_all_regex_fn(i64, i64, double) +declare double @js_structured_clone(double) +declare double @js_structured_clone_with_options(double, double) +declare double @js_generator_attach_prototype(double, i32) +declare double @js_generator_attach_closure_prototype(double, i64) +declare i64 @js_weakref_new(double) +declare double @js_weakref_deref(double) +declare i64 @js_finreg_new(double) +declare double @js_finreg_register(double, double, double, double) +declare double @js_finreg_unregister(double, double) +declare i64 @js_atob(double) +declare i64 @js_btoa(double) +declare double @js_object_is_frozen(double) +declare double @js_object_is_sealed(double) +declare double @js_object_is_extensible(double) +declare i64 @js_aggregateerror_new(i64, i64) +declare i64 @js_error_new_with_cause(i64, double) +declare i64 @js_aggregateerror_new_full(double, i64, double) +declare i64 @js_error_new_kind_with_options(i32, i64, double) +declare double @js_error_is_error(double) +declare i64 @js_error_get_errors(i64) +declare i64 @js_crypto_sha256(i64) +declare i64 @js_crypto_sha256_bytes(i64) +declare i64 @js_crypto_md5(i64) +declare i64 @js_crypto_hmac_sha256(i64, i64) +declare i64 @js_crypto_hmac_sha256_bytes(i64, i64) +declare void @js_runtime_validate_string_arg(double, ptr, i32) +declare void @js_set_call_location(ptr, i64, i32) +declare void @js_runtime_validate_crypto_key_arg(double, ptr, i32) +declare void @js_runtime_validate_integer_arg(double, ptr, i32, double, double) +declare i64 @js_crypto_pbkdf2_bytes(i64, i64, double, double, i64) +declare double @js_crypto_pbkdf2_async_alg(i64, i64, double, double, i64, double) +declare i64 @js_crypto_argon2_sync(i64, double) +declare double @js_crypto_argon2_async(i64, double, double) +declare i64 @js_crypto_encapsulate(double) +declare double @js_crypto_encapsulate_async(double, double) +declare i64 @js_crypto_decapsulate(double, double) +declare double @js_crypto_decapsulate_async(double, double, double) +declare i64 @js_crypto_hkdf_bytes_alg(i64, i64, i64, i64, double) +declare double @js_crypto_hkdf_async_alg(i64, i64, i64, i64, double, double) +declare i64 @js_crypto_scrypt_bytes(i64, i64, double, i64) +declare double @js_crypto_scrypt_async(i64, i64, double, double) +declare i64 @js_crypto_sign_rsa_sha256(i64, i64, double) +declare double @js_crypto_sign_async(i64, i64, double, double) +declare double @js_crypto_verify_rsa_sha256(i64, i64, double, i64) +declare double @js_crypto_verify_async(i64, i64, double, i64, double) +declare i64 @js_crypto_public_encrypt(i64, i64) +declare i64 @js_crypto_private_decrypt(i64, i64) +declare i64 @js_crypto_private_encrypt(i64, i64) +declare i64 @js_crypto_public_decrypt(i64, i64) +declare i64 @js_crypto_create_public_key(i64) +declare i64 @js_crypto_create_private_key_value(double) +declare i64 @js_crypto_create_public_key_value(double) +declare i64 @js_crypto_generate_key_pair_sync_rsa(double) +declare i64 @js_crypto_generate_key_pair_sync_ec_p256(double) +declare i64 @js_crypto_generate_key_pair_sync_ed25519(double) +declare i64 @js_crypto_generate_key_pair_sync_x25519(double) +declare double @js_crypto_generate_key_pair_async(i64, double, double) +declare i64 @js_crypto_diffie_hellman(double) +declare double @js_crypto_get_cipher_info(double, double) +declare i64 @js_crypto_get_curves() +declare i64 @js_crypto_secure_heap_used() +declare i64 @js_crypto_random_bytes_buffer(double) +declare double @js_crypto_random_bytes_async(double, double) +declare i64 @js_crypto_random_uuid(double) +declare i64 @js_crypto_random_uuidv7() +declare double @js_crypto_random_int(double, double) +declare double @js_crypto_random_int_async(double, double, double) +declare double @js_crypto_timing_safe_equal(double, double) +declare i64 @js_crypto_get_hashes() +declare i64 @js_crypto_get_ciphers() +declare double @js_crypto_generate_prime_sync(double, double) +declare double @js_crypto_generate_prime_async(double, double, double) +declare double @js_crypto_check_prime_sync(double, double) +declare double @js_crypto_check_prime_async(double, double, double) +declare i64 @js_crypto_create_secret_key(i64, i64) +declare i64 @js_crypto_generate_key_sync(i64, double) +declare double @js_crypto_generate_key_async(i64, double, double) +declare i64 @js_webcrypto_digest(double, double) +declare i64 @js_webcrypto_import_key(double, double, double, double, double) +declare i64 @js_webcrypto_export_key(double, double) +declare i64 @js_webcrypto_sign(double, double, double) +declare i64 @js_webcrypto_verify(double, double, double, double) +declare i64 @js_webcrypto_derive_bits(double, double, double) +declare i64 @js_webcrypto_derive_key(double, double, double, double, double) +declare i64 @js_webcrypto_encrypt(double, double, double) +declare i64 @js_webcrypto_decrypt(double, double, double) +declare i64 @js_webcrypto_generate_key(double, double, double) +declare i64 @js_webcrypto_wrap_key(double, double, double, double) +declare i64 @js_webcrypto_unwrap_key(double, double, double, double, double, double, double) +declare i64 @js_zlib_create_brotli_decompress(double) +declare double @js_crypto_random_fill_sync(double, double, double) +declare double @js_crypto_random_fill_async(double, double, double, double) +declare double @js_crypto_create_hash(i64) +declare double @js_crypto_create_hash_options(i64, double) +declare double @js_crypto_x509_new(i64) +declare double @js_crypto_certificate_verify_spkac(double) +declare double @js_crypto_certificate_export_public_key(double) +declare double @js_crypto_certificate_export_challenge(double) +declare double @js_crypto_create_sign(i64) +declare double @js_crypto_create_verify(i64) +declare double @js_crypto_create_ecdh(i64) +declare double @js_crypto_create_diffie_hellman(double, double, double) +declare double @js_crypto_get_diffie_hellman(double) +declare double @js_crypto_ecdh_convert_key(double, double, double, double, double) +declare double @js_crypto_create_hmac(i64, i64) +declare i64 @js_buffer_alloc(i32, i32) +declare i64 @js_buffer_alloc_fill_value(i32, double, i32) +declare i64 @js_array_buffer_new(i32) +declare i64 @js_shared_array_buffer_new(i32) +declare i64 @js_array_buffer_new_value(double) +declare i64 @js_shared_array_buffer_new_value(double) +declare i64 @js_json_stringify_full(double, double, double) +declare i64 @js_json_parse_with_reviver(i64, i64) +declare double @js_array_find(i64, i64) +declare i32 @js_array_findIndex(i64, i64) +declare double @js_array_find_last(i64, i64) +declare i32 @js_array_find_last_index(i64, i64) +declare double @js_array_some(i64, i64) +declare double @js_array_every(i64, i64) +declare i32 @js_promise_state(i64) +declare double @js_promise_value(i64) +declare double @js_promise_reason(i64) +declare i32 @js_value_is_promise(double) +declare double @js_assimilate_thenable(double) +declare i32 @js_promise_run_microtasks() +declare i32 @js_promise_run_microtasks_event_loop() +declare i32 @js_promise_run_microtasks_await_loop() +declare i32 @js_await_loop_tick_timers() +declare void @js_mark_entry_module_esm() +declare i32 @js_promise_run_promise_jobs() +declare void @js_run_stdlib_pump() +declare void @js_sleep_ms(double) +declare void @js_wait_for_event() +declare i32 @js_event_loop_host_driven() +declare void @js_unsettled_top_level_await_exit() +declare void @js_throw(double) +declare ptr @js_try_push() +declare i32 @_setjmp(ptr) #0 +declare void @js_try_end() +declare double @js_get_exception() +declare void @js_clear_exception() +declare i32 @js_has_exception() +declare void @js_enter_finally() +declare void @js_leave_finally() +declare double @js_await_any_promise(double) +declare i64 @js_promise_new() +declare i64 @js_promise_new_with_executor(i64) +declare i32 @js_timer_tick() +declare i32 @js_timer_tick_if_refed() +declare i32 @js_callback_timer_tick() +declare i32 @js_interval_timer_tick() +declare i32 @js_timer_has_pending() +declare i32 @js_callback_timer_has_pending() +declare i32 @js_interval_timer_has_pending() +declare i32 @js_stdlib_has_active_handles() +declare i32 @js_microtasks_pending() +declare i64 @js_timer_validate_callback(double, i32) +declare i64 @js_set_timeout_callback(i64, double) +declare i64 @js_set_timeout_callback_args(i64, double, ptr, i32) +declare i64 @js_set_immediate_callback(i64) +declare i64 @js_set_immediate_callback_args(i64, ptr, i32) +declare i64 @setInterval(i64, double) +declare i64 @js_set_interval_callback_args(i64, double, ptr, i32) +declare void @clearTimeout(i64) +declare void @clearInterval(i64) +declare void @clearImmediate(i64) +declare void @js_clear_timeout_value(double) +declare void @js_clear_interval_value(double) +declare void @js_clear_immediate_value(double) +declare i64 @js_buffer_from_array(i64) +declare i64 @js_buffer_from_arraybuffer_slice(i64, i32, i32) +declare i32 @js_buffer_length(i64) +declare i32 @js_buffer_get(i64, i32) +declare double @js_buffer_index_get_value(i64, i32) +declare ptr @js_native_buffer_data_ptr(double) +declare i64 @js_native_buffer_byte_len(double) +declare void @js_console_time(i64) +declare void @js_console_time_end(i64) +declare void @js_console_time_log(i64) +declare void @js_console_time_value(double) +declare void @js_console_time_end_value(double) +declare void @js_console_time_log_value(double) +declare void @js_console_time_log_spread(double, i64) +declare void @js_console_count(i64) +declare void @js_console_count_reset(i64) +declare void @js_console_count_value(double) +declare void @js_console_count_reset_value(double) +declare double @js_console_new(double) +declare double @js_console_new2(double, double) +declare void @js_console_group_begin() +declare void @js_console_group_end() +declare void @js_console_clear() +declare void @js_console_noop() +declare double @js_native_call_method(double, ptr, i64, ptr, i64) +declare double @js_native_call_method_by_id(double, i64, ptr, i64) +declare double @js_native_call_method_apply(double, ptr, i64, i64) +declare double @js_native_call_method_apply_by_id(double, i64, i64) +declare double @js_native_call_method_str_key(double, i64, ptr, i64) +declare double @js_native_call_method_value(double, double, ptr, i64) +declare double @js_native_call_method_value_apply(double, double, i64) +declare void @js_promise_resolve(i64, double) +declare void @js_promise_reject(i64, double) +declare void @js_promise_mark_internally_handled(i64) +declare i64 @js_promise_resolved(double) +declare i64 @js_async_fn_result(double) +declare i64 @js_promise_rejected(double) +declare double @js_create_namespace(i32, ptr, ptr, ptr) +declare i64 @js_promise_then(i64, i64, i64) +declare i64 @js_promise_resolved_then(double, i64, i64) +declare i64 @js_promise_finally(i64, i64) +declare double @js_promise_then_checked(double, double, double) +declare double @js_promise_catch_checked(double, double) +declare double @js_promise_finally_checked(double, double) +declare i64 @js_promise_closure_arg(double) +declare i64 @js_promise_all(i64) +declare i64 @js_promise_race(i64) +declare i64 @js_promise_any(i64) +declare i64 @js_promise_all_settled(i64) +declare i64 @js_promise_all_iterable(double) +declare i64 @js_promise_race_iterable(double) +declare i64 @js_promise_any_iterable(double) +declare i64 @js_promise_all_settled_iterable(double) +declare i64 @js_promise_with_resolvers() +declare i64 @js_promise_try(double, i64) +declare i64 @js_array_unshift_f64(i64, double) +declare i64 @js_array_unshift_variadic(i64, ptr, i32) +declare i64 @js_array_entries(i64) +declare i64 @js_array_keys(i64) +declare i64 @js_array_values(i64) +declare i64 @js_array_entries_iter_obj(i64) +declare i64 @js_array_keys_iter_obj(i64) +declare i64 @js_array_values_iter_obj(i64) +declare double @js_response_new(i64, double, i64, double) +declare i64 @js_response_body_init_ptr(double) +declare double @js_headers_new() +declare double @js_headers_set(double, i64, i64) +declare double @js_headers_append(double, i64, i64) +declare i64 @js_headers_get(double, i64) +declare double @js_headers_get_set_cookie(double) +declare double @js_headers_has(double, i64) +declare double @js_headers_delete(double, i64) +declare double @js_headers_for_each(double, double) +declare double @js_headers_keys(double) +declare double @js_headers_values(double) +declare double @js_headers_entries(double) +declare double @js_headers_init_from_value(double, double) +declare double @js_headers_method_value(double, i64, i64) +declare double @js_request_new(i64, i64, i64, double, i64, i64, i64, i64, i64, i64, i64, double, i64, double) +declare double @js_request_new_from_init(i64, double) +declare i64 @js_request_get_url(double) +declare i64 @js_request_input_to_url(double) +declare i64 @js_request_get_method(double) +declare double @js_request_get_body(double) +declare double @js_request_body_used(double) +declare i64 @js_request_get_destination(double) +declare i64 @js_request_get_referrer(double) +declare i64 @js_request_get_referrer_policy(double) +declare i64 @js_request_get_mode(double) +declare i64 @js_request_get_credentials(double) +declare i64 @js_request_get_cache(double) +declare i64 @js_request_get_redirect(double) +declare i64 @js_request_get_integrity(double) +declare double @js_request_get_keepalive(double) +declare i64 @js_request_get_duplex(double) +declare double @js_request_get_signal(double) +declare double @js_request_get_headers(double) +declare i64 @js_request_text(double) +declare i64 @js_request_json(double) +declare i64 @js_request_array_buffer(double) +declare i64 @js_request_blob(double) +declare i64 @js_request_bytes(double) +declare i64 @js_request_form_data(double) +declare double @js_request_clone(double) +declare double @js_fetch_response_status(double) +declare i64 @js_fetch_response_status_text(double) +declare double @js_fetch_response_ok(double) +declare i64 @js_fetch_response_type(double) +declare i64 @js_fetch_response_url(double) +declare double @js_fetch_response_redirected(double) +declare double @js_response_body_used(double) +declare i64 @js_fetch_response_text(double) +declare i64 @js_fetch_response_json(double) +declare double @js_response_get_headers(double) +declare double @js_response_clone(double) +declare i64 @js_response_array_buffer(double) +declare i64 @js_response_blob(double) +declare i64 @js_response_bytes(double) +declare i64 @js_response_form_data(double) +declare double @js_form_data_new() +declare double @js_form_data_append(double, double, double) +declare double @js_form_data_set(double, double, double) +declare double @js_form_data_delete(double, i64) +declare double @js_form_data_get(double, i64) +declare double @js_form_data_get_all(double, i64) +declare double @js_form_data_has(double, i64) +declare double @js_form_data_entries(double) +declare double @js_form_data_keys(double) +declare double @js_form_data_values(double) +declare double @js_form_data_for_each(double, double) +declare double @js_blob_size(double) +declare i64 @js_blob_type(double) +declare i64 @js_blob_array_buffer(double) +declare i64 @js_blob_bytes(double) +declare i64 @js_blob_text(double) +declare double @js_blob_slice(double, double, double, i64) +declare double @js_blob_new(double, double) +declare double @js_file_new(double, double, double, double) +declare i64 @js_file_name(double) +declare double @js_file_last_modified(double) +declare i64 @js_url_create_object_url(double) +declare void @js_url_revoke_object_url(double) +declare double @js_buffer_resolve_object_url(double) +declare double @js_response_static_json(double, double, i64, double) +declare double @js_response_static_redirect(i64, double) +declare double @js_response_static_error() +declare double @js_blob_stream(double) +declare double @js_response_body(double) +declare double @js_readable_stream_new(double, double, double, double) +declare double @js_readable_stream_new_with_source_type(double, double, double, double, double) +declare double @js_readable_stream_new_with_strategy_and_source_type(double, double, double, double, double) +declare double @js_readable_stream_new_from_source_object(double, double) +declare double @js_readable_stream_get_reader(double) +declare double @js_readable_stream_get_reader_with_options(double, double) +declare double @js_readable_stream_get_byob_reader(double) +declare double @js_readable_stream_controller_byob_request(double) +declare double @js_readable_stream_from_iterable(double) +declare double @js_readable_stream_locked(double) +declare i64 @js_readable_stream_cancel(double, double) +declare double @js_readable_stream_tee(double) +declare i64 @js_readable_stream_pipe_to(double, double, double) +declare double @js_readable_stream_pipe_through(double, double, double) +declare double @js_readable_stream_pipe_through_validate(double, double, double, double) +declare double @js_readable_stream_controller_enqueue(double, double) +declare double @js_readable_stream_controller_close(double) +declare double @js_readable_stream_controller_error(double, double) +declare double @js_readable_stream_controller_desired_size(double) +declare i64 @js_reader_read(double) +declare i64 @js_reader_read_with_view(double, double) +declare double @js_reader_release_lock(double) +declare i64 @js_reader_closed(double) +declare i64 @js_reader_cancel(double, double) +declare double @js_writable_stream_new(double, double, double, double, double) +declare double @js_writable_stream_new_with_sink_type(double, double, double, double, double, double) +declare double @js_writable_stream_new_from_sink_object(double, double) +declare double @js_writable_stream_throw_invalid_sink() +declare double @js_writable_stream_get_writer(double) +declare double @js_writable_stream_locked(double) +declare i64 @js_writable_stream_close(double) +declare i64 @js_writable_stream_abort(double, double) +declare i64 @js_writer_write(double, double) +declare i64 @js_writer_close(double) +declare i64 @js_writer_abort(double, double) +declare double @js_writer_release_lock(double) +declare i64 @js_writer_closed(double) +declare i64 @js_writer_ready(double) +declare double @js_writer_desired_size(double) +declare double @js_transform_stream_new(double, double, double, double, double) +declare double @js_transform_stream_new_from_transformer_object(double, double, double) +declare double @js_transform_stream_readable(double) +declare double @js_transform_stream_writable(double) +declare double @js_text_encoding_stream_new() +declare double @js_text_encoder_stream_new() +declare double @js_text_decoder_stream_new() +declare double @js_stream_web_text_encoder_stream_new() +declare double @js_stream_web_text_decoder_stream_new(double, double) +declare double @js_stream_web_compression_stream_new(double) +declare double @js_stream_web_decompression_stream_new(double) +declare double @js_streams_strategy_high_water_mark(double) +declare double @js_count_queuing_strategy_new(double) +declare double @js_byte_length_queuing_strategy_new(double) +declare double @js_stream_unwrap_handle(double) +declare double @js_readable_stream_subclass_init(double, double, double, double, double) +declare double @js_writable_stream_subclass_init(double, double, double, double, double) +declare double @js_transform_stream_subclass_init(double, double, double, double) +declare double @js_request_subclass_init(double, double, double) +declare double @js_response_subclass_init(double, double, double) +declare double @js_fetch_or_value_super(double, double, ptr, i64) +declare i64 @js_abort_controller_new() +declare i64 @js_abort_controller_signal(i64) +declare void @js_abort_controller_abort(i64) +declare void @js_abort_controller_abort_reason(i64, double) +declare void @js_abort_signal_add_listener(i64, double, double) +declare i64 @js_abort_signal_timeout(double) +declare i64 @js_abort_signal_abort(double) +declare i64 @js_abort_signal_any(i64) +declare double @js_abort_signal_throw_if_aborted(i64) +declare i64 @js_event_target_new() +declare i64 @js_event_new(double, double, i32) +declare double @js_event_subclass_init(double, double, double, i32, i32) +declare i64 @js_custom_event_new(double, double, i32) +declare i64 @js_dom_exception_new(double, double) +declare double @js_dom_exception_subclass_init(double, double, double) +declare void @js_event_target_add_event_listener(i64, i64, i64) +declare void @js_event_target_add_event_listener_with_options(i64, i64, i64, double) +declare void @js_event_target_remove_event_listener(i64, i64, i64) +declare void @js_event_target_remove_event_listener_with_options(i64, i64, i64, double) +declare double @js_event_target_dispatch_event(i64, double) +declare i32 @js_event_target_is_event_target(i64) +declare i64 @js_event_target_get_event_listeners(i64, i64) +declare double @js_event_target_get_max_listeners(i64) +declare i32 @js_event_target_set_max_listeners(i64, double) +declare double @js_message_channel_new() +declare double @js_message_port_constructor_error() +declare double @js_broadcast_channel_new(double) +declare i64 @js_array_alloc(i32) +declare i64 @js_tagged_template_register_raw(i64, i64) +declare i64 @js_tagged_template_get_or_init(i64, i64, i64) +declare i64 @js_template_raw(i64) +declare i64 @js_array_create() +declare i64 @js_array_constructor_single(double) +declare i64 @js_array_alloc_literal(i32) +declare i64 @js_array_from_values(ptr, i32) +declare i64 @js_array_push_f64(i64, double) +declare void @js_array_push_guard(i64) +declare i64 @js_array_push_hole(i64) +declare i64 @js_array_numeric_push_f64_unboxed(i64, double) +declare i64 @js_array_push_spread_f64(i64, i64) +declare double @js_array_get_f64(i64, i32) +declare double @js_array_get_index_or_string(i64, double) +declare double @js_array_numeric_get_f64_unboxed(i64, i32) +declare void @js_array_set_f64(i64, i32, double) +declare i32 @js_array_numeric_set_f64_unboxed(i64, i32, double) +declare i64 @js_array_set_f64_extend(i64, i32, double) +declare i64 @js_array_set_f64_extend_strict(i64, i32, double) +declare i64 @js_array_fill_f64_const_extend(i64, i32, double) +declare i64 @js_array_fill_f64_iota_extend(i64, i32) +declare i64 @js_array_fill_f64_const_len_extend(i64, double) +declare i64 @js_array_fill_f64_iota_len_extend(i64) +declare i64 @js_array_numeric_range_add(double, double, double, double) +declare i64 @js_array_numeric_range_add_len(double, double, double) +declare i64 @js_array_set_string_key(i64, i64, double) +declare i64 @js_array_set_index_or_string(i64, double, double) +declare i64 @js_array_mark_arguments_object(i64) +declare i32 @js_array_mark_numeric_f64_layout(i64) +declare i32 @js_array_is_numeric_f64_layout(i64) +declare void @js_array_clear_numeric_layout(i64) +declare double @js_array_numeric_value_to_raw_f64(double) #4 +declare double @js_array_refresh_local_head(double) +declare void @js_array_note_numeric_write(i64, i64) +declare i32 @js_array_length(i64) +declare double @js_array_is_array(double) +declare double @js_value_length_f64(double) +declare nonnull ptr @js_shadow_frame_enter(i32) +declare i64 @js_shadow_frame_push(i32) +declare void @js_shadow_frame_pop(i64) +declare void @js_shadow_slot_set(i32, i64) +declare void @js_shadow_slot_bind(i32, ptr) +declare void @js_gc_write_barriers_emitted(i32) +declare i32 @js_gc_temp_root_push(i64) +declare i64 @js_gc_temp_root_get(i32) +declare void @js_gc_temp_root_set(i32, i64) +declare void @js_gc_temp_root_truncate(i32) +declare void @js_array_push_f64_temp_rooted(i32, double) +declare void @js_gc_loop_safepoint() +declare void @js_write_barrier(i64, i64) +declare void @js_write_barrier_slot(i64, i64, i64) +declare void @js_write_barrier_root_nanbox(i64) +declare void @js_write_barrier_root_heap_word(i64) +declare void @js_gc_note_slot_layout(i64, i32, i64) +declare void @js_gc_note_slot_layout_aware(i64, i32, i64, i64) +declare void @js_gc_init_typed_shape_layout(i64, i32, ptr, i32, ptr, i32) +declare void @js_gc_init_unboxed_object_layout(i64, i32, i64, i64) +declare double @js_array_pop_f64(i64) +declare i64 @js_array_join(i64, i64) +declare i64 @js_array_join_value(i64, double) +declare void @js_array_forEach(i64, i64) +declare i64 @js_array_fill(i64, double) +declare i64 @js_array_fill_range(i64, double, double, double) +declare double @js_array_fill_generic(double, double, i32, double, i32, double) +declare i32 @js_array_delete(i64, i32) +declare void @js_array_set_length(i64, double) +declare void @js_array_set_length_strict(i64, double) +declare i64 @js_array_clone(i64) +declare i64 @js_array_from_value(double) +declare i64 @js_array_from_arraylike_holey_value(double) +declare double @js_iterator_from(double) +declare i64 @js_array_from_mapped(double, double, double) +declare i64 @js_array_concat_variadic(i64, ptr, i32) +declare double @js_arraylike_forEach(double, double, double) +declare double @js_arraylike_map(double, double, double) +declare double @js_arraylike_filter(double, double, double) +declare double @js_arraylike_some(double, double, double) +declare double @js_arraylike_every(double, double, double) +declare double @js_arraylike_find(double, double, double) +declare double @js_arraylike_findIndex(double, double, double) +declare double @js_arraylike_findLast(double, double, double) +declare double @js_arraylike_findLastIndex(double, double, double) +declare double @js_arraylike_reduce(double, double, i32, double) +declare double @js_arraylike_reduceRight(double, double, i32, double) +declare double @js_arraylike_indexOf(double, double, double, i32) +declare double @js_arraylike_lastIndexOf(double, double, double, i32) +declare double @js_arraylike_includes(double, double, double, i32) +declare double @js_arraylike_at(double, double) +declare double @js_arraylike_join(double, double) +declare double @js_arraylike_slice(double, double, i32, double, i32) +declare double @js_arraylike_sort(double, double) +declare double @js_arraylike_splice(double, ptr, i32) +declare double @js_arraylike_concat(double, ptr, i32) +declare double @js_arraylike_pop(double) +declare double @js_arraylike_shift(double) +declare double @js_arraylike_push(double, ptr, i32) +declare double @js_arraylike_unshift(double, ptr, i32) +declare i64 @js_array_clone_for_spread(double) +declare i64 @js_array_spread_append(i64, double) +declare i64 @js_iterator_to_array(double) +declare double @js_iterator_next_result(double) +declare double @js_iterator_close_if_not_done(double, double) +declare double @js_iterator_rest_to_array(double, double) +declare double @js_get_iterator(double) +declare double @js_get_async_iterator(double) +declare double @js_for_of_to_array(double) +declare i64 @js_object_alloc(i32, i32) +declare double @js_object_coerce(double) +declare void @js_object_mark_class(i64) +declare void @js_class_object_pin_parent(i64, i32) +declare i64 @js_object_alloc_with_shape(i32, i32, ptr, i32) +declare void @js_object_set_field(i64, i32, i64) +declare void @js_object_set_unboxed_f64_field(i64, i32, double) +declare double @js_object_get_unboxed_f64_field(i64, i32) +declare void @js_object_set_field_by_name(i64, i64, double) +declare void @js_object_set_field_by_property_id(i64, i64, double) +declare void @js_object_set_field_by_name_nonenum(i64, i64, double) +declare void @js_error_subclass_default_init(double, double, i64) +declare void @js_object_set_field_by_name_nonconfigurable(i64, i64, double) +declare void @js_error_apply_cause_to_object(i64, double) +declare i32 @js_with_has_binding(double, i64) +declare double @js_with_get_binding(double, i64) +declare double @js_with_set_binding(double, i64, double, i32) +declare i32 @js_with_delete_binding(double, i64) +declare i32 @js_pod_scalar_write_compatible(double, i32) +declare void @js_typed_feedback_register_site(i64, i32, ptr, i64, ptr, i64, ptr, i64, ptr, i64, ptr, i64, ptr, i64) +declare void @js_typed_feedback_record_guard_pass(i64) +declare void @js_typed_feedback_record_guard_fail(i64) +declare void @js_typed_feedback_record_fallback_call(i64) +declare void @js_typed_feedback_observe_property_get(i64, i64, i64) +declare void @js_typed_feedback_observe_property_set(i64, i64, i64) +declare double @js_typed_feedback_object_get_field_by_name_f64(i64, i64, i64) +declare void @js_typed_feedback_object_set_field_by_name(i64, i64, i64, double) +declare void @js_typed_feedback_object_set_field_by_name_fast(i64, i64, i64, double) +declare i32 @js_typed_feedback_class_field_set_guard(i64, double, i32, i64, i64, i32, double, i32) +declare void @js_class_field_set_fallback(i64, i64, i64, double) +declare void @js_class_field_set_ic(i64, double, i32, i64, i64, i32, double, i32) +declare i32 @js_typed_feedback_class_field_get_guard(i64, double, i32, i64, i64, i32, i32) +declare double @js_class_field_get_ic(i64, double, i32, i64, i64, i32, i32) +declare double @js_typed_feedback_native_call_method(i64, double, ptr, i64, ptr, i64) +declare double @js_typed_feedback_native_call_method_by_id(i64, double, i64, ptr, i64) +declare double @js_typed_feedback_native_call_method_apply(i64, double, ptr, i64, i64) +declare double @js_typed_feedback_native_call_method_apply_by_id(i64, double, i64, i64) +declare i32 @js_typed_feedback_method_direct_call_guard(i64, double, i32, i64, ptr, i64, ptr) +declare i32 @js_method_direct_shape_guard(double, i32, i64) +declare i32 @js_typed_feedback_closure_direct_call_guard(i64, double, ptr, i32, i32) +declare void @js_typed_feedback_object_set_unboxed_f64_field(i64, i64, i32, i64, double) +declare double @js_typed_feedback_observe_helper_return(i64, double) +declare void @js_object_set_index_polymorphic(i64, double, double) +declare double @js_object_get_index_polymorphic(i64, double) +declare double @js_object_get_field_by_name_f64(i64, i64) +declare double @js_object_get_field_by_name_boxed(double, i64) +declare double @js_object_get_field_by_property_id_f64(i64, i64) +declare double @js_native_module_property_by_name(ptr, i64, ptr, i64) +declare double @js_create_native_module_namespace(ptr, i64) +declare void @js_nm_install_assert() +declare void @js_nm_install_async_hooks() +declare void @js_nm_install_bigint() +declare void @js_nm_install_buffer() +declare void @js_nm_install_bun() +declare void @js_nm_install_bun_ffi() +declare void @js_nm_install_child_process() +declare void @js_nm_install_cluster() +declare void @js_nm_install_console() +declare void @js_nm_install_crypto() +declare void @js_nm_install_dgram() +declare void @js_nm_install_dns() +declare void @js_nm_install_domain() +declare void @js_nm_install_events() +declare void @js_nm_install_fs() +declare void @js_nm_install_http() +declare void @js_nm_install_inspector() +declare void @js_nm_install_module() +declare void @js_nm_install_net() +declare void @js_nm_install_node_pty() +declare void @js_nm_install_os() +declare void @js_nm_install_path() +declare void @js_nm_install_perf() +declare void @js_nm_install_process() +declare void @js_nm_install_punycode() +declare void @js_nm_install_querystring() +declare void @js_nm_install_readline() +declare void @js_nm_install_repl() +declare void @js_nm_install_sea() +declare void @js_nm_install_sqlite() +declare void @js_nm_install_stream() +declare void @js_nm_install_timers() +declare void @js_nm_install_tls() +declare void @js_nm_install_tty() +declare void @js_nm_install_url() +declare void @js_nm_install_util() +declare void @js_nm_install_v8() +declare void @js_nm_install_vm() +declare void @js_nm_install_wasi() +declare void @js_nm_install_zlib() +declare void @js_nm_install_all() +declare double @js_object_get_field_ic_miss(i64, i64, ptr) +declare double @js_object_get_field_ic(i64, i64, i64, ptr) +declare i64 @js_object_rest(i64, i64) +declare double @js_require_object_coercible(double) +declare double @js_require_json_disk(double) +declare double @js_require_resolve_node_modules(double, double) +declare void @js_globalthis_seed_async_local_storage() +declare void @js_register_path_module(double, double) +declare double @js_require_path_module(double) +declare void @js_register_path_init(ptr, i64, i64) +declare i64 @js_array_alloc_with_length(i32) +declare void @js_array_set_f64_unchecked(i64, i32, double) +declare double @js_typed_feedback_array_get_f64(i64, i64, i32) +declare i32 @js_typed_feedback_plain_array_index_get_guard(i64, double, i32, i32) #4 +declare i32 @js_typed_feedback_numeric_array_index_get_guard(i64, double, i32, i32) #4 +declare i32 @js_typed_feedback_packed_f64_array_loop_guard(i64, double) +declare i32 @js_typed_feedback_packed_f64_range_loop_guard(i64, double, i32, i32) +declare i32 @js_typed_feedback_packed_f64_range_loop_guard_dense(i64, double, i32, i32) +declare i32 @js_typed_feedback_packed_f64_range_loop_guard_dense_i32(i64, double, i32, i32) +declare i32 @js_typed_feedback_masked_window_ta_kind(i64, double, i32, i32) +declare i64 @js_typed_array_masked_window_data_ptr(double) +declare i32 @js_typed_feedback_packed_u32_array_loop_guard(i64, double) +declare double @js_typed_feedback_array_index_get_fallback_boxed(i64, double, double) +declare void @js_typed_feedback_array_set_f64(i64, i64, i32, double) +declare i64 @js_typed_feedback_array_set_f64_extend(i64, i64, i32, double) +declare i32 @js_typed_feedback_plain_array_index_set_guard(i64, double, i32, double, i32) #4 +declare i32 @js_typed_feedback_numeric_array_index_set_guard(i64, double, i32, double, i32) #4 +declare i32 @js_typed_feedback_numeric_array_push_guard(i64, double, double) #4 +declare double @js_typed_feedback_array_index_set_fallback_boxed(i64, double, double, double) +declare void @js_typed_feedback_observe_array_element(i64, i64, i32) +declare i64 @js_typed_feedback_array_set_string_key(i64, i64, i64, double) +declare i64 @js_typed_feedback_array_set_index_or_string(i64, i64, double, double) +declare void @js_typed_feedback_object_set_index_polymorphic(i64, i64, double, double) +declare double @js_proxy_new(double, double) +declare double @js_proxy_revocable(double, double) +declare void @js_proxy_revoke(double) +declare i32 @js_proxy_is_revoked(double) +declare i32 @js_proxy_is_proxy(double) +declare double @js_proxy_target(double) +declare double @js_proxy_get(double, double) +declare double @js_proxy_set(double, double, double) +declare double @js_proxy_has(double, double) +declare double @js_proxy_delete(double, double) +declare double @js_proxy_apply(double, double, double) +declare double @js_proxy_construct(double, double, double) +declare double @js_reflect_construct(double, double, double) +declare double @js_reflect_get(double, double, double) +declare double @js_reflect_set(double, double, double, double) +declare double @js_put_value_set(double, double, double, double, i32) +declare double @js_put_value_set_dyn_ic(ptr, double, double, double, i32) +declare double @js_put_value_set_ic_miss(double, i64, double, i32, ptr) +declare i64 @js_object_array_numeric_write_guard(double, double, double, double, double, i32, i32) +declare double @js_super_put_value_set(i32, double, double, double, i32) +declare double @js_super_accessor_get(i32, double, double) +declare double @js_reflect_has(double, double) +declare double @js_reflect_delete(double, double) +declare double @js_reflect_own_keys(double) +declare double @js_reflect_apply(double, double, double) +declare double @js_reflect_define_property(double, double, double) +declare double @js_reflect_get_own_property_descriptor(double, double) +declare double @js_reflect_get_prototype_of(double) +declare double @js_reflect_set_prototype_of(double, double) +declare double @js_reflect_is_extensible(double) +declare double @js_reflect_prevent_extensions(double) +declare double @js_reflect_define_metadata(double, double, double, double) +declare double @js_reflect_get_metadata(double, double, double) +declare double @js_reflect_get_own_metadata(double, double, double) +declare double @js_reflect_has_metadata(double, double, double) +declare double @js_reflect_has_own_metadata(double, double, double) +declare double @js_reflect_get_metadata_keys(double, double) +declare double @js_reflect_get_own_metadata_keys(double, double) +declare double @js_reflect_delete_metadata(double, double, double) +declare double @js_http_server_construct_with_this(double, double, double) +declare double @js_https_server_construct_with_this(double, double, double) +declare i64 @js_net_socket_set_encoding(i64, i64) +declare double @js_vm_create_context(double) +declare double @js_vm_module_call() +declare double @js_vm_module_constructor_error() +declare double @js_repl_start(double) +declare double @js_repl_repl_server_new(double) +declare double @js_repl_recoverable_new(double) +declare double @js_worker_threads_worker_new(i64, double) +declare double @js_worker_threads_worker_post_message(i64, double) +declare double @js_worker_threads_worker_on(i64, double, i64) +declare double @js_worker_threads_worker_once(i64, double, i64) +declare double @js_worker_threads_worker_off(i64, double, i64) +declare double @js_worker_threads_worker_add_event_listener(i64, double, i64) +declare double @js_worker_threads_worker_remove_event_listener(i64, double, i64) +declare double @js_worker_threads_worker_terminate(i64) +declare double @js_worker_threads_worker_ref(i64) +declare double @js_worker_threads_worker_unref(i64) +declare double @js_worker_threads_worker_get_heap_statistics(i64) +declare double @js_worker_threads_worker_cpu_usage(i64, double) +declare double @js_worker_threads_worker_get_heap_snapshot(i64, double) +declare double @js_worker_threads_worker_start_cpu_profile(i64) +declare double @js_worker_threads_worker_start_heap_profile(i64) +declare i64 @js_http_client_request_end(i64, double) +declare i64 @js_http_client_request_write(i64, double) +declare i64 @js_http_client_request_end_full(i64, double, i64, i64) +declare double @js_http_client_request_write_full(i64, double, i64, i64) +declare i64 @js_http_set_timeout_full(i64, double, i64) +declare i64 @js_http_client_request_method(i64) +declare i64 @js_http_client_request_protocol(i64) +declare i64 @js_http_client_request_host(i64) +declare i64 @js_http_client_request_path(i64) +declare double @js_http_client_request_listener_count(i64, i64) +declare double @js_http_client_request_get_header(i64, i64) +declare double @js_http_client_request_has_header(i64, i64) +declare double @js_http_client_request_remove_header(i64, i64) +declare double @js_http_client_request_get_header_names(i64) +declare double @js_http_client_request_get_headers(i64) +declare double @js_http_client_request_get_raw_header_names(i64) +declare double @js_http_client_request_abort(i64) +declare i64 @js_http_client_request_destroy(i64, double) +declare double @js_http_client_request_noop_undefined(i64, double, double) +declare double @js_http_client_request_aborted(i64) +declare double @js_http_client_request_destroyed(i64) +declare double @js_http_client_request_finished(i64) +declare double @js_http_client_request_reused_socket(i64) +declare double @js_http_client_request_max_headers_count(i64) +declare double @js_http_client_request_writable_ended(i64) +declare double @js_http_client_request_writable_finished(i64) +declare double @js_http_client_request_socket(i64) +declare i64 @js_http_get(double, i64) +declare i64 @js_http_get_overload(i64) +declare i64 @js_http_request_overload(i64) +declare i64 @js_https_get_overload(i64) +declare i64 @js_https_request_overload(i64) +declare i64 @js_http_on(i64, i64, i64) +declare i64 @js_http_request(double, i64) +declare i64 @js_http_request_body(i64) +declare double @js_http_request_body_length(i64) +declare i64 @js_http_request_content_type(i64) +declare double @js_http_request_has_header(i64, i64) +declare i64 @js_http_request_header(i64, i64) +declare i64 @js_http_request_headers_all(i64) +declare double @js_http_request_id(i64) +declare double @js_http_request_is_method(i64, i64) +declare i64 @js_http_request_method(i64) +declare i64 @js_http_request_path(i64) +declare i64 @js_http_request_query(i64) +declare i64 @js_http_request_query_all(i64) +declare i64 @js_http_request_query_param(i64, i64) +declare double @js_http_respond_error(i64, double, i64) +declare double @js_http_respond_html(i64, double, i64) +declare double @js_http_respond_json(i64, double, i64) +declare double @js_http_respond_not_found(i64) +declare double @js_http_respond_redirect(i64, i64, double) +declare i64 @js_http_respond_status_text(double) +declare double @js_http_respond_text(i64, double, i64) +declare double @js_http_respond_with_headers(i64, double, i64, i64) +declare double @js_http_response_headers(i64) +declare double @js_http_response_trailers(i64) +declare i64 @js_http_incoming_message_set_encoding(i64, i64) +declare i64 @js_http_server_accept_v2(i64) +declare double @js_http_server_close(i64) +declare i64 @js_http_server_create(double) +declare i64 @js_http_set_header(i64, i64, i64) +declare i64 @js_http_set_timeout(i64, double) +declare double @js_http_status_code(i64) +declare i64 @js_http_status_message(i64) +declare i64 @js_http_agent_new(double) +declare i64 @js_https_agent_new(double) +declare i64 @js_http_agent_get_name(i64, double) +declare i64 @js_http_agent_noop_self(i64) +declare double @js_http_agent_max_sockets(i64) +declare double @js_http_agent_max_free_sockets(i64) +declare double @js_http_agent_max_total_sockets(i64) +declare double @js_http_agent_keep_alive_msecs(i64) +declare double @js_http_agent_keep_alive(i64) +declare i64 @js_http_agent_protocol(i64) +declare double @js_http_agent_default_port(i64) +declare void @js_http_agent_set_protocol(i64, i64) +declare i64 @js_http_agent_destroy(i64) +declare double @js_http_agent_destroyed(i64) +declare double @js_http_agent_sockets(i64) +declare double @js_http_agent_free_sockets(i64) +declare double @js_http_agent_requests(i64) +declare void @js_http_agent_set_max_sockets(i64, double) +declare void @js_http_agent_set_max_free_sockets(i64, double) +declare void @js_http_agent_set_max_total_sockets(i64, double) +declare void @js_http_agent_set_keep_alive(i64, double) +declare void @js_http_agent_set_keep_alive_msecs(i64, double) +declare void @js_http_agent_set_create_connection(i64, i64) +declare void @js_http_agent_set_create_socket(i64, i64) +declare i64 @js_http_agent_create_connection(i64) +declare i64 @js_http_agent_create_socket(i64) +declare i64 @js_https_get(double, i64) +declare i64 @js_https_request(double, i64) +declare i64 @js_node_http_create_server(i64) +declare i64 @js_node_http_server_listen(i64, i64) +declare void @js_node_http_server_close(i64, i64) +declare void @js_node_http_server_close_all_connections(i64) +declare void @js_node_http_server_close_idle_connections(i64) +declare i64 @js_node_http_server_address_json(i64) +declare i32 @js_node_http_server_listening(i64) +declare double @js_node_http_server_listening_value(i64) +declare double @js_node_http_server_on(i64, i64, i64) +declare i64 @js_node_http_im_method(i64) +declare i64 @js_node_http_im_url(i64) +declare i64 @js_node_http_im_http_version(i64) +declare i64 @js_node_http_im_headers_json(i64) +declare i64 @js_node_http_im_raw_headers_json(i64) +declare i64 @js_node_http_im_headers_distinct_json(i64) +declare i64 @js_node_http_im_trailers_json(i64) +declare i64 @js_node_http_im_raw_trailers_json(i64) +declare i64 @js_node_http_im_trailers_distinct_json(i64) +declare i32 @js_node_http_im_complete(i64) +declare i32 @js_node_http_im_aborted(i64) +declare i32 @js_node_http_im_destroyed(i64) +declare i64 @js_node_http_im_remote_address(i64) +declare double @js_node_http_im_remote_port(i64) +declare void @js_node_http_im_pause(i64) +declare void @js_node_http_im_resume(i64) +declare void @js_node_http_im_destroy(i64) +declare double @js_node_http_im_on(i64, i64, i64) +declare double @js_node_http_im_read(i64) +declare i64 @js_node_http_im_set_timeout(i64, double, i64) +declare void @js_node_http_res_set_status(i64, double) +declare double @js_node_http_res_get_status(i64) +declare void @js_node_http_res_set_status_message(i64, i64) +declare void @js_node_http_res_set_header(i64, i64, double) +declare i64 @js_node_http_res_set_header_self(i64, i64, double) +declare double @js_node_http_res_get_header(i64, i64) +declare void @js_node_http_res_remove_header(i64, i64) +declare i32 @js_node_http_res_has_header(i64, i64) +declare double @js_node_http_res_has_header_value(i64, i64) +declare i64 @js_node_http_res_get_headers_json(i64) +declare i64 @js_node_http_res_get_header_names_json(i64) +declare i64 @js_node_http_res_append_header(i64, i64, i64) +declare i64 @js_node_http_res_set_headers(i64, double) +declare double @js_node_http_res_get_status_message(i64) +declare i32 @js_node_http_res_headers_sent(i64) +declare i32 @js_node_http_res_writable_ended(i64) +declare i32 @js_node_http_res_writable_finished(i64) +declare i32 @js_node_http_res_finished(i64) +declare i32 @js_node_http_res_send_date(i64) +declare void @js_node_http_res_set_send_date(i64, double) +declare i32 @js_node_http_res_strict_content_length(i64) +declare void @js_node_http_res_set_strict_content_length(i64, double) +declare i64 @js_node_http_res_req_handle(i64) +declare void @js_node_http_res_write_head(i64, double, i64, i64) +declare i32 @js_node_http_res_write(i64, double) +declare double @js_node_http_res_write_full(i64, double, i64, i64) +declare void @js_node_http_res_add_trailers(i64, double) +declare void @js_node_http_res_end(i64, double) +declare void @js_node_http_res_end_full(i64, double, i64, i64) +declare void @js_node_http_res_flush_headers(i64) +declare void @js_node_http_res_cork(i64) +declare void @js_node_http_res_uncork(i64) +declare i64 @js_node_http_res_set_timeout(i64, double, i64) +declare void @js_node_http_res_write_early_hints(i64, double, i64) +declare void @js_node_http_res_write_continue(i64) +declare void @js_node_http_res_write_processing(i64) +declare double @js_node_http_res_on(i64, i64, i64) +declare i64 @js_node_https_create_server(double, i64) +declare i64 @js_node_https_server_listen(i64, i64) +declare void @js_node_https_server_close(i64, i64) +declare void @js_node_https_server_close_all_connections(i64) +declare void @js_node_https_server_close_idle_connections(i64) +declare i64 @js_node_https_server_address_json(i64) +declare double @js_node_https_server_on(i64, i64, i64) +declare double @js_node_https_server_listening_value(i64) +declare double @js_node_https_server_headers_timeout(i64) +declare double @js_node_https_server_set_headers_timeout(i64, double) +declare double @js_node_https_server_keep_alive_timeout(i64) +declare double @js_node_https_server_set_keep_alive_timeout(i64, double) +declare double @js_node_https_server_keep_alive_timeout_buffer(i64) +declare double @js_node_https_server_set_keep_alive_timeout_buffer(i64, double) +declare double @js_node_https_server_request_timeout(i64) +declare double @js_node_https_server_set_request_timeout(i64, double) +declare double @js_node_https_server_idle_timeout(i64) +declare double @js_node_https_server_set_idle_timeout(i64, double) +declare double @js_node_https_server_max_headers_count(i64) +declare double @js_node_https_server_set_max_headers_count(i64, double) +declare double @js_node_https_server_max_requests_per_socket(i64) +declare double @js_node_https_server_set_max_requests_per_socket(i64, double) +declare i64 @js_node_https_server_set_timeout_method(i64, double, i64) +declare i64 @js_node_http2_create_server(double, double) +declare i64 @js_node_http2_create_secure_server(double, i64) +declare i64 @js_node_http2_connect(double, double, i64) +declare i64 @js_node_http2_server_listen(i64, i64) +declare void @js_node_http2_server_close(i64, i64) +declare i64 @js_node_http2_server_address_json(i64) +declare double @js_node_http2_server_on(i64, i64, i64) +declare i64 @js_node_http2_get_default_settings() +declare i64 @js_node_http2_get_packed_settings(i64) +declare i64 @js_node_http2_get_unpacked_settings(i64) +declare i64 @js_pg_client_connect(i64) +declare i64 @js_pg_client_end(i64) +declare i64 @js_pg_client_new(i64) +declare i64 @js_pg_client_query(i64, i64) +declare i64 @js_pg_client_query_params(i64, i64, i64) +declare i64 @js_pg_connect(i64) +declare i64 @js_pg_create_pool(i64) +declare i64 @js_pg_pool_end(i64) +declare i64 @js_pg_pool_new(i64) +declare i64 @js_pg_pool_query(i64, i64) +declare i64 @js_ioredis_connect(i64) +declare i64 @js_ioredis_decr(i64, i64) +declare i64 @js_ioredis_del(i64, i64) +declare void @js_ioredis_disconnect(i64) +declare i64 @js_ioredis_exists(i64, i64) +declare i64 @js_ioredis_expire(i64, i64, double) +declare i64 @js_ioredis_get(i64, i64) +declare i64 @js_ioredis_hdel(i64, i64, i64) +declare i64 @js_ioredis_hget(i64, i64, i64) +declare i64 @js_ioredis_hgetall(i64, i64) +declare i64 @js_ioredis_hlen(i64, i64) +declare i64 @js_ioredis_hset(i64, i64, i64, i64) +declare i64 @js_ioredis_incr(i64, i64) +declare i64 @js_ioredis_new(i64) +declare i64 @js_ioredis_ping(i64) +declare i64 @js_ioredis_quit(i64) +declare i64 @js_ioredis_set(i64, i64, i64) +declare i64 @js_ioredis_setex(i64, i64, double, i64) +declare i64 @js_mongodb_client_close(i64) +declare i64 @js_mongodb_client_connect(i64) +declare i64 @js_mongodb_client_db(i64, i64) +declare i64 @js_mongodb_client_list_databases(i64) +declare i64 @js_mongodb_client_new(i64) +declare i64 @js_mongodb_collection_count_value(i64, double) +declare i64 @js_mongodb_collection_delete_many_value(i64, double) +declare i64 @js_mongodb_collection_delete_one_value(i64, double) +declare i64 @js_mongodb_collection_find_one_value(i64, double) +declare i64 @js_mongodb_collection_find_value(i64, double) +declare i64 @js_mongodb_collection_insert_many_value(i64, double) +declare i64 @js_mongodb_collection_insert_one_value(i64, double) +declare i64 @js_mongodb_collection_update_many_value(i64, double, double) +declare i64 @js_mongodb_collection_update_one_value(i64, double, double) +declare i64 @js_mongodb_collection_count(i64, i64) +declare i64 @js_mongodb_collection_delete_many(i64, i64) +declare i64 @js_mongodb_collection_delete_one(i64, i64) +declare i64 @js_mongodb_collection_find(i64, i64) +declare i64 @js_mongodb_collection_find_one(i64, i64) +declare i64 @js_mongodb_collection_insert_many(i64, i64) +declare i64 @js_mongodb_collection_insert_one(i64, i64) +declare i64 @js_mongodb_collection_update_many(i64, i64, i64) +declare i64 @js_mongodb_collection_update_one(i64, i64, i64) +declare i64 @js_mongodb_connect(i64) +declare i64 @js_mongodb_db_collection(i64, i64) +declare i64 @js_mongodb_db_list_collections(i64) +declare void @js_sqlite_close(i64) +declare void @js_sqlite_exec(i64, i64) +declare i64 @js_sqlite_open(i64) +declare i64 @js_sqlite_pragma(i64, i64, i64) +declare i64 @js_sqlite_prepare(i64, i64) +declare i64 @js_sqlite_stmt_all(i64, i64) +declare i64 @js_sqlite_stmt_columns(i64) +declare i64 @js_sqlite_stmt_get(i64, i64) +declare i64 @js_sqlite_stmt_run(i64, i64) +declare i64 @js_sqlite_transaction(i64, i64) +declare void @js_sqlite_transaction_commit(i64) +declare void @js_sqlite_transaction_rollback(i64) +declare i64 @js_node_sqlite_backup(double, double, double) +declare i64 @js_node_sqlite_database_sync_call(double, double) +declare i64 @js_node_sqlite_database_sync_new(double, double) +declare i32 @js_node_sqlite_database_sync_open(i64) +declare i32 @js_node_sqlite_database_sync_close(i64) +declare i32 @js_node_sqlite_database_sync_dispose(i64) +declare i32 @js_node_sqlite_database_sync_exec(i64, double) +declare i64 @js_node_sqlite_database_sync_prepare(i64, double, double) +declare i32 @js_node_sqlite_database_sync_function(i64, double, double, double) +declare i32 @js_node_sqlite_database_sync_aggregate(i64, double, double) +declare i32 @js_node_sqlite_database_sync_enable_defensive(i64, double) +declare i32 @js_node_sqlite_database_sync_set_authorizer(i64, double) +declare i64 @js_node_sqlite_database_sync_create_tag_store(i64, double) +declare i64 @js_node_sqlite_database_sync_create_session(i64, double) +declare double @js_node_sqlite_database_sync_apply_changeset(i64, double, double) +declare i32 @js_node_sqlite_database_sync_enable_load_extension(i64, double) +declare i32 @js_node_sqlite_database_sync_load_extension(i64, double) +declare double @js_node_sqlite_database_sync_location(i64, double) +declare double @js_node_sqlite_database_sync_is_open(i64) +declare double @js_node_sqlite_database_sync_is_transaction(i64) +declare i64 @js_node_sqlite_database_sync_limits(i64) +declare i64 @js_node_sqlite_statement_sync_call(double, double) +declare i64 @js_node_sqlite_statement_sync_new(double, double) +declare i64 @js_node_sqlite_statement_sync_run(i64, i64) +declare double @js_node_sqlite_statement_sync_get(i64, i64) +declare i64 @js_node_sqlite_statement_sync_all(i64, i64) +declare double @js_node_sqlite_statement_sync_iterate(i64, i64) +declare i64 @js_node_sqlite_statement_sync_columns(i64) +declare i32 @js_node_sqlite_statement_sync_set_read_bigints(i64, double) +declare i32 @js_node_sqlite_statement_sync_set_return_arrays(i64, double) +declare i32 @js_node_sqlite_statement_sync_set_allow_bare_named_parameters(i64, double) +declare i32 @js_node_sqlite_statement_sync_set_allow_unknown_named_parameters(i64, double) +declare i64 @js_node_sqlite_statement_sync_source_sql(i64) +declare i64 @js_node_sqlite_statement_sync_expanded_sql(i64) +declare i64 @js_node_sqlite_sql_tag_store_run(i64, i64) +declare double @js_node_sqlite_sql_tag_store_get(i64, i64) +declare i64 @js_node_sqlite_sql_tag_store_all(i64, i64) +declare double @js_node_sqlite_sql_tag_store_iterate(i64, i64) +declare i32 @js_node_sqlite_sql_tag_store_clear(i64) +declare double @js_node_sqlite_sql_tag_store_size(i64) +declare double @js_node_sqlite_sql_tag_store_capacity(i64) +declare i64 @js_node_sqlite_sql_tag_store_db(i64) +declare i64 @js_node_sqlite_session_call(double, double) +declare i64 @js_node_sqlite_session_new(double, double) +declare i64 @js_node_sqlite_session_changeset(i64) +declare i64 @js_node_sqlite_session_patchset(i64) +declare i32 @js_node_sqlite_session_close(i64) +declare i32 @js_node_sqlite_session_dispose(i64) +declare i64 @js_os_cpus() +declare double @js_os_freemem() +declare i64 @js_os_homedir() +declare i64 @js_os_network_interfaces() +declare i64 @js_os_tmpdir() +declare double @js_os_totalmem() +declare double @js_os_uptime() +declare i64 @js_os_user_info() +declare i64 @js_os_user_info_buffer() +declare i64 @js_os_user_info_options(i64) +declare i64 @js_crypto_aes256_decrypt(i64, i64, i64) +declare i64 @js_crypto_aes256_encrypt(i64, i64, i64) +declare i64 @js_crypto_aes256_gcm_decrypt(i64, i64, i64) +declare i64 @js_crypto_aes256_gcm_encrypt(i64, i64, i64) +declare double @js_crypto_create_cipheriv(i64, i64, i64, double) +declare double @js_crypto_create_decipheriv(i64, i64, i64, double) +declare i64 @js_crypto_hkdf_sha256(i64, i64, i64, double) +declare i64 @js_crypto_hkdf_sync(i64, i64, i64, i64, double) +declare i64 @js_crypto_pbkdf2(i64, i64, double, double) +declare i64 @js_crypto_random_bytes_hex(double) +declare i64 @js_crypto_random_nonce() +declare i64 @js_crypto_scrypt(i64, i64, double) +declare double @js_crypto_generate_key_pair_sync(i64, i64) +declare i64 @js_crypto_scrypt_custom(i64, i64, double, double, double, double) +declare i64 @js_crypto_x25519_keypair() +declare i64 @js_crypto_x25519_shared_secret(i64, i64) +declare i64 @js_keccak256_native(i64) +declare i64 @js_keccak256_native_bytes(i64) +declare i64 @js_nanoid(double) +declare i64 @js_nanoid_custom(i64, double) +declare i64 @js_argon2_hash(i64) +declare i64 @js_argon2_hash_options(i64, i64) +declare i64 @js_argon2_verify(i64, i64) +declare i64 @js_bcrypt_compare(i64, i64) +declare double @js_bcrypt_compare_sync(i64, i64) +declare i64 @js_bcrypt_gen_salt(double) +declare i64 @js_bcrypt_hash(i64, double) +declare i64 @js_bcrypt_hash_sync(i64, double) +declare i64 @js_ads_interstitial_load(i64) +declare i64 @js_ads_interstitial_show() +declare i64 @js_ads_rewarded_load(i64) +declare i64 @js_ads_rewarded_show() +declare double @js_ads_banner_create(i64, i64) +declare void @js_ads_banner_destroy(double) +declare i64 @js_ads_request_consent() +declare i64 @js_perry_read_embedded(double) +declare i64 @js_perry_embedded_files() +declare double @js_thread_parallel_map(double, double) +declare double @js_thread_parallel_filter(double, double) +declare double @js_thread_spawn(double) +declare i64 @js_jwt_decode(i64) +declare i64 @js_jwt_sign(i64, i64, double, i64) +declare i64 @js_jwt_sign_es256(i64, i64, double, i64) +declare i64 @js_jwt_sign_rs256(i64, i64, double, i64) +declare i64 @js_jwt_verify(i64, i64) +declare i64 @js_jwt_verify_es256(i64, i64) +declare i64 @js_jwt_verify_rs256(i64, i64) +declare i64 @js_jwt_sign_dyn(i64, i64, i64, double, i64) +declare i64 @js_jwt_verify_dyn(i64, i64, i64) +declare i64 @js_jwt_sign_dyn_opts(i64, i64, double) +declare i64 @js_jwt_verify_dyn_opts(i64, i64, double) +declare double @js_axios_create(i64) +declare i64 @js_axios_delete(i64) +declare i64 @js_axios_get(i64) +declare i64 @js_axios_head(i64) +declare i64 @js_axios_options(i64) +declare i64 @js_axios_post(i64, double) +declare i64 @js_axios_put(i64, double) +declare i64 @js_axios_patch(i64, double) +declare i64 @js_axios_request(i64) +declare double @js_axios_response_status(i64) +declare i64 @js_axios_response_status_text(i64) +declare i64 @js_axios_response_data(i64) +declare double @js_axios_response_data_parsed(i64) +declare i64 @js_sharp_auto_orient(i64) +declare i64 @js_sharp_avif(i64, double) +declare i64 @js_sharp_blur(i64, double) +declare i64 @js_sharp_composite(i64, double) +declare i64 @js_sharp_extend(i64, double) +declare i64 @js_sharp_extract(i64, double) +declare i64 @js_sharp_flip(i64) +declare i64 @js_sharp_flop(i64) +declare i64 @js_sharp_from_buffer(i64, double) +declare i64 @js_sharp_from_file(i64) +declare i64 @js_sharp_from_input(i64) +declare i64 @js_sharp_grayscale(i64) +declare i64 @js_sharp_metadata(i64) +declare i64 @js_sharp_sharpen(i64) +declare i64 @js_sharp_trim(i64) +declare i64 @js_sharp_negate(i64) +declare i64 @js_sharp_quality(i64, double) +declare i64 @js_sharp_resize(i64, double, double) +declare i64 @js_sharp_rotate(i64, double) +declare i64 @js_sharp_to_buffer(i64) +declare i64 @js_sharp_to_file(i64, i64) +declare i64 @js_sharp_to_format(i64, i64) +declare void @js_cron_clear_interval(i64) +declare void @js_cron_clear_timeout(i64) +declare i64 @js_cron_describe(i64) +declare double @js_cron_job_is_running(i64) +declare i64 @js_cron_job_new(i64, i64, double) +declare void @js_cron_job_start(i64) +declare void @js_cron_job_stop(i64) +declare i64 @js_cron_next_date(i64) +declare i64 @js_cron_next_dates(i64, double) +declare i64 @js_cron_schedule(i64, i64) +declare i64 @js_cron_set_interval(double, double) +declare i64 @js_cron_set_timeout(double, double) +declare i32 @js_cron_timer_has_pending() +declare i32 @js_cron_timer_tick() +declare double @js_cron_validate(i64) +declare i64 @js_async_hooks_create_hook(double) +declare double @js_async_hooks_execution_async_id() +declare double @js_async_hooks_trigger_async_id() +declare double @js_async_hooks_execution_async_resource() +declare i64 @js_async_hook_enable(i64) +declare i64 @js_async_hook_disable(i64) +declare i64 @js_async_resource_new(double, double) +declare double @js_async_resource_async_id(i64) +declare double @js_async_resource_trigger_async_id(i64) +declare i64 @js_async_resource_emit_destroy(i64) +declare double @js_async_resource_run_in_async_scope(i64, double, double, i64) +declare i64 @js_async_resource_bind(i64, double, double) +declare i64 @js_async_resource_static_bind(i64, double) +declare void @js_async_local_storage_disable(i64) +declare void @js_async_local_storage_enter_with(i64, double) +declare double @js_async_local_storage_exit(i64, double, i64) +declare double @js_async_local_storage_get_store(i64) +declare i64 @js_async_local_storage_new() +declare double @js_async_local_storage_run(i64, double, double, i64) +declare i64 @js_disposable_stack_new() +declare i64 @js_async_disposable_stack_new() +declare double @js_suppressed_error_new(double, double, double) +declare i64 @js_zlib_deflate_sync(i64, double) +declare void @js_zlib_deflate(double, double) +declare i64 @js_zlib_gunzip_sync(i64) +declare void @js_zlib_gunzip(double, double) +declare i64 @js_zlib_gzip_sync(i64, double) +declare void @js_zlib_gzip(double, double) +declare i64 @js_zlib_inflate_sync(i64) +declare void @js_zlib_inflate(double, double) +declare i64 @js_zlib_deflate_raw_sync(double, double) +declare void @js_zlib_deflate_raw(double, double) +declare i64 @js_zlib_inflate_raw_sync(double) +declare void @js_zlib_inflate_raw(double, double) +declare i64 @js_zlib_unzip_sync(double) +declare void @js_zlib_unzip(double, double) +declare double @js_zlib_crc32(double, double) +declare i64 @js_zlib_brotli_compress_sync(i64) +declare i64 @js_zlib_brotli_decompress_sync(i64) +declare void @js_zlib_brotli_compress(double, double) +declare void @js_zlib_brotli_decompress(double, double) +declare i64 @js_zlib_zstd_compress_sync(double, double) +declare i64 @js_zlib_zstd_decompress_sync(double, double) +declare void @js_zlib_zstd_compress(double, double) +declare void @js_zlib_zstd_decompress(double, double) +declare i64 @js_zlib_create_gzip(double) +declare i64 @js_zlib_create_gunzip(double) +declare i64 @js_zlib_create_deflate(double) +declare i64 @js_zlib_create_inflate(double) +declare i64 @js_zlib_create_deflate_raw(double) +declare i64 @js_zlib_create_inflate_raw(double) +declare i64 @js_zlib_create_unzip(double) +declare i64 @js_zlib_create_brotli_compress(double) +declare i64 @js_zlib_create_zstd_compress(double) +declare i64 @js_zlib_create_zstd_decompress(double) +declare i64 @js_buffer_alloc_unsafe(i32) +declare i32 @js_buffer_byte_length(i64) +declare i32 @js_buffer_byte_length_value(double, double) +declare i64 @js_buffer_concat(i64) +declare i64 @js_buffer_concat_with_length(i64, double) +declare i32 @js_buffer_validate_size(double) +declare i64 @js_buffer_validate_concat_list(double) +declare i32 @js_buffer_copy(i64, i64, i32, i32, i32) +declare i32 @js_buffer_equals(i64, i64) +declare i64 @js_buffer_fill(i64, i32) +declare i64 @js_buffer_from_value(i64, i32) +declare double @js_buffer_is_ascii(double) +declare i32 @js_buffer_is_buffer(i64) +declare i32 @js_buffer_is_encoding(double) +declare double @js_buffer_is_utf8(double) +declare void @js_buffer_print(i64) +declare void @js_buffer_set(i64, i32, i32) +declare void @js_buffer_set_from(i64, i64, i32) +declare i64 @js_buffer_slice(i64, i32, i32) +declare i64 @js_buffer_to_string(i64, i32) +declare i64 @js_buffer_transcode(double, double, double) +declare i32 @js_buffer_write(i64, i64, i32, i32) +declare double @js_child_process_exec_sync(i64, i64) +declare double @js_child_process_exec(i64, double, double) +declare i64 @js_child_process_get_process_status(double) +declare i32 @js_child_process_kill_process(double) +declare i64 @js_child_process_spawn_background(double, i64, double, double) +declare i64 @js_child_process_spawn_sync(i64, i64, i64) +declare double @js_child_process_spawn_streams(i64, i64, i64) +declare double @js_pty_spawn(i64, i64, i64) +declare double @js_child_process_fork(i64, i64, i64) +declare double @js_child_process_exec_file(i64, double, double, double) +declare double @js_child_process_exec_file_sync(i64, double, double) +declare double @js_child_process_validate_command(double, ptr, i32) +declare double @js_child_process_validate_args(double) +declare double @js_child_process_validate_options(double, i32, i32) +declare double @js_child_process_validate_fork_module(double) +declare double @js_child_process_validate_spawn_args(double, i32, i32) +declare double @js_child_process_new() +declare i64 @js_cheerio_load(i64) +declare i64 @js_cheerio_load_fragment(i64) +declare i64 @js_cheerio_select(i64, i64) +declare i64 @js_cheerio_selection_attr(i64, i64) +declare i64 @js_cheerio_selection_attrs(i64, i64) +declare i64 @js_cheerio_selection_children(i64, i64) +declare i64 @js_cheerio_selection_eq(i64, double) +declare i64 @js_cheerio_selection_find(i64, i64) +declare i64 @js_cheerio_selection_first(i64) +declare double @js_cheerio_selection_has_class(i64, i64) +declare i64 @js_cheerio_selection_html(i64) +declare double @js_cheerio_selection_is(i64, i64) +declare i64 @js_cheerio_selection_last(i64) +declare double @js_cheerio_selection_length(i64) +declare i64 @js_cheerio_selection_parent(i64) +declare i64 @js_cheerio_selection_text(i64) +declare i64 @js_cheerio_selection_texts(i64) +declare i64 @js_cheerio_selection_to_array(i64) +declare double @js_url_file_url_to_path(double, double) +declare double @js_url_file_url_to_path_buffer(double, double) +declare double @js_url_get_hash(i64) +declare double @js_url_get_host(i64) +declare double @js_url_get_hostname(i64) +declare double @js_url_get_href(i64) +declare double @js_url_get_origin(i64) +declare double @js_url_get_pathname(i64) +declare double @js_url_get_port(i64) +declare double @js_url_get_protocol(i64) +declare double @js_url_get_search(i64) +declare double @js_url_get_search_params(i64) +declare i64 @js_url_new(i64) +declare i64 @js_url_new_with_base(i64, i64) +declare i64 @js_url_pattern_new(double, double) +declare double @js_url_pattern_constructor_call(double, double) +declare i32 @js_url_can_parse(i64) +declare i32 @js_url_can_parse_with_base(i64, i64) +declare i64 @js_url_parse(i64) +declare i64 @js_url_parse_with_base(i64, i64) +declare void @js_url_set_pathname(i64, double) +declare void @js_url_set_search(i64, double) +declare void @js_url_set_hash(i64, double) +declare void @js_url_set_protocol(i64, double) +declare void @js_url_set_hostname(i64, double) +declare void @js_url_set_port(i64, double) +declare void @js_url_set_username(i64, double) +declare void @js_url_set_password(i64, double) +declare void @js_url_set_href(i64, double) +declare double @js_url_search_params_has2(i64, double, double) +declare void @js_url_search_params_delete2(i64, double, double) +declare double @js_url_search_params_throw_missing_args(i32) +declare void @js_url_search_params_append(i64, double, double) +declare void @js_url_search_params_delete(i64, double) +declare i64 @js_url_search_params_get(i64, double) +declare double @js_url_search_params_get_all(i64, double) +declare double @js_url_search_params_has(i64, double) +declare i64 @js_url_search_params_new(i64) +declare i64 @js_url_search_params_new_any(double) +declare i64 @js_url_search_params_new_empty() +declare double @js_url_search_params_subclass_init(double, double) +declare void @js_url_search_params_set(i64, double, double) +declare i64 @js_url_search_params_to_string(i64) +declare i32 @js_url_search_params_size(i64) +declare double @js_url_search_params_entries_arr(i64) +declare double @js_url_search_params_keys_arr(i64) +declare double @js_url_search_params_values_arr(i64) +declare void @js_url_search_params_sort(i64) +declare void @js_url_search_params_for_each(i64, double, double) +declare i64 @js_url_coerce_string(double) +declare double @js_url_path_to_file_url(double, double) +declare double @js_url_domain_to_ascii(double) +declare double @js_url_domain_to_unicode(double) +declare double @js_url_to_http_options(double) +declare double @js_url_legacy_url_new() +declare double @js_url_format(double, double) +declare double @js_url_legacy_parse(double, double, double) +declare double @js_url_legacy_resolve(double, double) +declare double @js_url_legacy_resolve_object(double, double) +declare void @js_ws_close(i64) +declare i64 @js_ws_connect(i64) +declare double @js_ws_connect_start(double) +declare i64 @js_ws_handle_to_i64(double) +declare double @js_ws_is_open(i64) +declare double @js_ws_message_count(i64) +declare double @js_ws_ready_state(i64) +declare i64 @js_ws_on(i64, i64, i64) +declare i64 @js_ws_receive(i64) +declare void @js_ws_send(i64, i64) +declare void @js_ws_send_to_client(double, i64) +declare void @js_ws_close_client(double) +declare void @js_ws_send_client_i64(i64, i64) +declare void @js_ws_close_client_i64(i64) +declare i64 @js_ws_on_client_i64(i64, i64, i64) +declare void @js_ws_server_close(i64) +declare i64 @js_ws_server_new(double) +declare i64 @js_ws_handle_upgrade(i64, double, double, double, i64) +declare i64 @js_ws_wait_for_message(i64, double) +declare i64 @js_pdf_create_pdf(double) +declare void @js_pdf_add_text(i64, i64, double, double, double) +declare void @js_pdf_add_line(i64, double, double, double, double) +declare void @js_pdf_new_page(i64) +declare void @js_pdf_save(i64) +declare i64 @js_commander_action(i64, i64) +declare i64 @js_commander_command(i64, i64) +declare i64 @js_commander_description(i64, i64) +declare i64 @js_commander_get_option(i64, i64) +declare double @js_commander_get_option_bool(i64, i64) +declare double @js_commander_get_option_number(i64, i64) +declare i64 @js_commander_name(i64, i64) +declare i64 @js_commander_new() +declare i64 @js_commander_option(i64, i64, i64, i64) +declare i64 @js_commander_opts(i64) +declare i64 @js_commander_parse(i64, double) +declare i64 @js_commander_required_option(i64, i64, i64, i64) +declare i64 @js_commander_version(i64, i64) +declare double @js_dotenv_config() +declare double @js_dotenv_config_path(i64) +declare i64 @js_dotenv_parse(i64) +declare double @js_datefns_add_days(double, double) +declare double @js_datefns_add_months(double, double) +declare double @js_datefns_add_years(double, double) +declare double @js_datefns_difference_in_days(double, double) +declare double @js_datefns_difference_in_hours(double, double) +declare double @js_datefns_difference_in_minutes(double, double) +declare double @js_datefns_end_of_day(double) +declare i64 @js_datefns_format(double, i64) +declare double @js_datefns_is_after(double, double) +declare double @js_datefns_is_before(double, double) +declare double @js_datefns_parse_iso(i64) +declare double @js_datefns_start_of_day(double) +declare double @js_dayjs_add(i64, double, i64) +declare double @js_dayjs_date(i64) +declare double @js_dayjs_day(i64) +declare double @js_dayjs_diff(i64, i64, i64) +declare double @js_dayjs_end_of(i64, i64) +declare double @js_dayjs_factory(i64) +declare i64 @js_dayjs_format(i64, i64) +declare double @js_dayjs_from_timestamp(double) +declare double @js_dayjs_hour(i64) +declare double @js_dayjs_is_after(i64, i64) +declare double @js_dayjs_is_before(i64, i64) +declare double @js_dayjs_is_same(i64, i64) +declare double @js_dayjs_is_valid(i64) +declare double @js_dayjs_millisecond(i64) +declare double @js_dayjs_minute(i64) +declare double @js_dayjs_month(i64) +declare double @js_dayjs_now() +declare double @js_dayjs_parse(i64) +declare double @js_dayjs_second(i64) +declare double @js_dayjs_start_of(i64, i64) +declare double @js_dayjs_subtract(i64, double, i64) +declare i64 @js_dayjs_to_iso_string(i64) +declare double @js_dayjs_unix(i64) +declare double @js_dayjs_value_of(i64) +declare double @js_dayjs_year(i64) +declare double @js_moment_add(i64, double, i64) +declare double @js_moment_clone(i64) +declare double @js_moment_date(i64) +declare double @js_moment_day(i64) +declare double @js_moment_diff(i64, i64, i64) +declare double @js_moment_end_of(i64, i64) +declare double @js_moment_factory(i64) +declare i64 @js_moment_format(i64, i64) +declare i64 @js_moment_from_now(i64) +declare double @js_moment_from_timestamp(double) +declare double @js_moment_hour(i64) +declare double @js_moment_is_after(i64, i64) +declare double @js_moment_is_before(i64, i64) +declare double @js_moment_is_between(i64, i64, i64) +declare double @js_moment_is_same(i64, i64, i64) +declare double @js_moment_is_valid(i64) +declare double @js_moment_millisecond(i64) +declare double @js_moment_minute(i64) +declare double @js_moment_month(i64) +declare double @js_moment_now() +declare double @js_moment_parse(i64) +declare double @js_moment_second(i64) +declare double @js_moment_start_of(i64, i64) +declare double @js_moment_subtract(i64, double, i64) +declare double @js_moment_to_date(i64) +declare i64 @js_moment_to_iso_string(i64) +declare double @js_moment_unix(i64) +declare double @js_moment_value_of(i64) +declare double @js_moment_year(i64) +declare i64 @js_decimal_abs(i64) +declare i64 @js_decimal_ceil(i64) +declare double @js_decimal_cmp(i64, i64) +declare double @js_decimal_cmp_value(i64, double) +declare i64 @js_decimal_coerce_to_handle(double) +declare i64 @js_decimal_div(i64, i64) +declare i64 @js_decimal_div_number(i64, double) +declare i64 @js_decimal_div_value(i64, double) +declare double @js_decimal_eq(i64, i64) +declare double @js_decimal_eq_value(i64, double) +declare i64 @js_decimal_floor(i64) +declare i64 @js_decimal_from_number(double) +declare i64 @js_decimal_from_string(i64) +declare double @js_decimal_gt(i64, i64) +declare double @js_decimal_gt_value(i64, double) +declare double @js_decimal_gte(i64, i64) +declare double @js_decimal_gte_value(i64, double) +declare double @js_decimal_is_negative(i64) +declare double @js_decimal_is_positive(i64) +declare double @js_decimal_is_zero(i64) +declare double @js_decimal_lt(i64, i64) +declare double @js_decimal_lt_value(i64, double) +declare double @js_decimal_lte(i64, i64) +declare double @js_decimal_lte_value(i64, double) +declare i64 @js_decimal_minus(i64, i64) +declare i64 @js_decimal_minus_number(i64, double) +declare i64 @js_decimal_minus_value(i64, double) +declare i64 @js_decimal_mod(i64, i64) +declare i64 @js_decimal_mod_value(i64, double) +declare i64 @js_decimal_neg(i64) +declare i64 @js_decimal_plus(i64, i64) +declare i64 @js_decimal_plus_number(i64, double) +declare i64 @js_decimal_plus_value(i64, double) +declare i64 @js_decimal_pow(i64, double) +declare i64 @js_decimal_round(i64) +declare i64 @js_decimal_sqrt(i64) +declare i64 @js_decimal_times(i64, i64) +declare i64 @js_decimal_times_number(i64, double) +declare i64 @js_decimal_times_value(i64, double) +declare i64 @js_decimal_to_fixed(i64, double) +declare double @js_decimal_to_number(i64) +declare i64 @js_decimal_to_string(i64) +declare i64 @js_ethers_format_ether(i64) +declare i64 @js_ethers_format_units(i64, double) +declare i64 @js_ethers_get_address(i64) +declare i64 @js_ethers_parse_ether(i64) +declare i64 @js_ethers_parse_units(i64, double) +declare i64 @js_lodash_camel_case(i64) +declare i64 @js_lodash_capitalize(i64) +declare i64 @js_lodash_chunk(i64, double) +declare double @js_lodash_clamp(double, double, double) +declare i64 @js_lodash_compact(i64) +declare i64 @js_lodash_concat(i64, i64) +declare i64 @js_lodash_difference(i64, i64) +declare i64 @js_lodash_drop(i64, double) +declare i64 @js_lodash_drop_right(i64, double) +declare double @js_lodash_ends_with(i64, i64) +declare i64 @js_lodash_escape(i64) +declare double @js_lodash_first(i64) +declare i64 @js_lodash_flatten(i64) +declare double @js_lodash_in_range(double, double, double) +declare double @js_lodash_includes(i64, i64) +declare i64 @js_lodash_initial(i64) +declare i64 @js_lodash_kebab_case(i64) +declare double @js_lodash_last(i64) +declare i64 @js_lodash_lower_case(i64) +declare i64 @js_lodash_lower_first(i64) +declare double @js_lodash_max(i64) +declare double @js_lodash_max_by(i64, double) +declare double @js_lodash_mean(i64) +declare double @js_lodash_mean_by(i64, double) +declare double @js_lodash_min(i64) +declare double @js_lodash_min_by(i64, double) +declare i64 @js_lodash_pad(i64, double) +declare i64 @js_lodash_pad_end(i64, double) +declare i64 @js_lodash_pad_start(i64, double) +declare double @js_lodash_random(double, double) +declare i64 @js_lodash_repeat(i64, double) +declare i64 @js_lodash_replace(i64, i64, i64) +declare i64 @js_lodash_reverse(i64) +declare double @js_lodash_size(i64) +declare i64 @js_lodash_snake_case(i64) +declare i64 @js_lodash_split(i64, i64) +declare i64 @js_lodash_start_case(i64) +declare double @js_lodash_starts_with(i64, i64) +declare double @js_lodash_sum(i64) +declare double @js_lodash_sum_by(i64, double) +declare i64 @js_lodash_tail(i64) +declare i64 @js_lodash_take(i64, double) +declare i64 @js_lodash_take_right(i64, double) +declare i64 @js_lodash_trim(i64) +declare i64 @js_lodash_trim_end(i64) +declare i64 @js_lodash_trim_start(i64) +declare i64 @js_lodash_truncate(i64, double) +declare i64 @js_lodash_unescape(i64) +declare i64 @js_lodash_uniq(i64) +declare i64 @js_lodash_upper_case(i64) +declare i64 @js_lodash_upper_first(i64) +declare void @js_lru_cache_clear(i64) +declare double @js_lru_cache_delete(i64, double) +declare double @js_lru_cache_get(i64, double) +declare double @js_lru_cache_has(i64, double) +declare i64 @js_lru_cache_new(double) +declare double @js_lru_cache_peek(i64, double) +declare i64 @js_lru_cache_set(i64, double, double) +declare double @js_lru_cache_size(i64) +declare double @js_event_emitter_subclass_init(double) +declare double @js_array_subclass_init(double, double) +declare double @js_map_set_subclass_init(double, i32, double) +declare double @js_promise_subclass_init(double, double) +declare double @js_node_stream_readable_new(double) +declare double @js_node_stream_readable_subclass_init(double, double) +declare double @js_node_stream_writable_new(double) +declare double @js_node_stream_writable_subclass_init(double, double) +declare double @js_node_stream_duplex_new(double) +declare double @js_node_stream_duplex_subclass_init(double, double) +declare double @js_node_stream_transform_new(double) +declare double @js_node_stream_transform_subclass_init(double, double) +declare double @js_node_stream_passthrough_new(double) +declare double @js_node_stream_readable_from(double) +declare double @js_node_stream_readable_from_options(double, double) +declare double @js_node_stream_duplex_from_options(double, double) +declare double @js_node_stream_is_disturbed(double) +declare double @js_node_stream_is_errored(double) +declare double @js_node_stream_is_readable(double) +declare double @js_node_stream_is_writable(double) +declare double @js_node_stream_is_array_buffer_view(double) +declare double @js_node_stream_is_uint8_array(double) +declare double @js_node_stream_is_destroyed(double) +declare double @js_node_stream_uint8_array_to_buffer(double) +declare double @js_node_stream_get_default_hwm(double) +declare double @js_node_stream_set_default_hwm(double, double) +declare double @js_node_stream_add_abort_signal(double, double) +declare double @js_node_stream_compose(i64) +declare double @js_node_stream_pipeline(i64) +declare double @js_node_stream_finished(i64) +declare double @js_node_stream_duplex_pair(double) +declare double @js_node_stream_readable_to_web(double) +declare double @js_node_stream_writable_to_web(double) +declare double @js_node_stream_duplex_to_web(double) +declare double @js_node_stream_readable_from_web(double, double) +declare double @js_node_stream_writable_from_web(double, double) +declare double @js_node_stream_duplex_from_web(double, double) +declare double @js_node_stream_to_web(double) +declare double @js_node_stream_from_web(double) +declare double @js_node_stream_method_readable_aborted(i64) +declare double @js_node_stream_method_closed(i64) +declare double @js_node_stream_method_errored(i64) +declare double @js_node_stream_method_readable_did_read(i64) +declare double @js_node_stream_method_destroyed(i64) +declare double @js_node_stream_method_destroy(i64, double) +declare double @js_node_stream_method_pause(i64) +declare double @js_node_stream_method_readable(i64) +declare double @js_node_stream_method_readable_length(i64) +declare double @js_node_stream_method_readable_flowing(i64) +declare double @js_node_stream_method_readable_ended(i64) +declare double @js_node_stream_method_readable_object_mode(i64) +declare double @js_node_stream_method_pipe(i64, double, double) +declare double @js_node_stream_method_unpipe(i64, double) +declare double @js_node_stream_method_is_paused(i64) +declare double @js_node_stream_method_resume(i64) +declare double @js_node_stream_method_readable_encoding(i64) +declare double @js_node_stream_method_cork(i64) +declare double @js_node_stream_method_uncork(i64) +declare double @js_node_stream_method_writable_corked(i64) +declare double @js_node_stream_method_writable_length(i64) +declare double @js_node_stream_method_writable_need_drain(i64) +declare double @js_node_stream_method_writable(i64) +declare double @js_node_stream_method_writable_ended(i64) +declare double @js_node_stream_method_writable_finished(i64) +declare double @js_node_stream_method_allow_half_open(i64) +declare double @js_node_stream_method_set_encoding(i64, double) +declare double @js_node_stream_method_writable_object_mode(i64) +declare double @js_event_emitter_emit(i64, i64, i64) +declare double @js_event_emitter_emit0(i64, i64) +declare double @js_event_emitter_listener_count(i64, i64, i64) +declare i64 @js_event_emitter_new() +declare i64 @js_event_emitter_new_with_options(double) +declare i64 @js_event_emitter_on(i64, i64, i64) +declare i64 @js_event_emitter_once(i64, i64, i64) +declare i64 @js_event_emitter_prepend_listener(i64, i64, i64) +declare i64 @js_event_emitter_prepend_once_listener(i64, i64, i64) +declare i64 @js_event_emitter_remove_all_listeners(i64, i64) +declare i64 @js_event_emitter_remove_listener(i64, i64, i64) +declare i64 @js_event_emitter_set_max_listeners(i64, double) +declare double @js_event_emitter_get_max_listeners(i64) +declare i64 @js_event_emitter_event_names(i64) +declare i64 @js_event_emitter_listeners(i64, i64) +declare i64 @js_event_emitter_raw_listeners(i64, i64) +declare double @js_event_emitter_domain_value(i64) +declare i64 @js_event_emitter_async_resource_new(double) +declare double @js_event_emitter_async_resource_call(double) +declare double @js_event_emitter_async_resource_async_id(i64) +declare double @js_event_emitter_async_resource_trigger_async_id(i64) +declare double @js_event_emitter_async_resource_async_resource(i64) +declare double @js_event_emitter_async_resource_emit_destroy(i64) +declare i64 @js_events_once(double, i64, double) +declare i64 @js_events_on(double, i64, double) +declare i64 @js_events_add_abort_listener(double, double) +declare i64 @js_events_get_event_listeners(double, i64) +declare double @js_events_listener_count(double, i64) +declare double @js_events_get_max_listeners(double) +declare double @js_events_set_max_listeners(double, i64) +declare double @js_events_init() +declare i64 @js_domain_create() +declare i64 @js_domain_on(i64, i64, i64) +declare double @js_domain_emit(i64, i64, i64) +declare double @js_domain_run(i64, double, i64) +declare double @js_domain_bind(i64, double) +declare double @js_domain_intercept(i64, double) +declare i64 @js_domain_add(i64, double) +declare i64 @js_domain_remove(i64, double) +declare double @js_domain_enter(i64) +declare double @js_domain_exit(i64) +declare i64 @js_string_decoder_new(i64) +declare double @js_string_decoder_write(i64, double) +declare double @js_string_decoder_end(i64, double) +declare double @js_querystring_escape(double) +declare double @js_querystring_unescape(double) +declare i64 @js_querystring_unescape_buffer(double, double) +declare i64 @js_querystring_parse(double, double, double, double) +declare double @js_querystring_stringify(double, double, double, double) +declare i32 @js_fastify_add_hook(i64, i64, i64) +declare i32 @js_fastify_all(i64, i64, i64) +declare i64 @js_fastify_create() +declare i64 @js_fastify_create_with_opts(double) +declare double @js_fastify_ctx_html(i64, i64, double) +declare double @js_fastify_ctx_json(i64, double, double) +declare double @js_fastify_ctx_redirect(i64, i64, double) +declare double @js_fastify_ctx_text(i64, i64, double) +declare i32 @js_fastify_delete(i64, i64, i64) +declare i32 @js_fastify_get(i64, i64, i64) +declare i32 @js_fastify_head(i64, i64, i64) +declare void @js_fastify_listen(i64, double, i64) +declare void @js_fastify_app_close(i64) +declare i64 @js_fastify_app_server(i64) +declare void @js_fastify_app_on(i64, i64, i64) +declare i32 @js_fastify_options(i64, i64, i64) +declare i32 @js_fastify_patch(i64, i64, i64) +declare i32 @js_fastify_post(i64, i64, i64) +declare i32 @js_fastify_put(i64, i64, i64) +declare i32 @js_fastify_register(i64, i64, double) +declare i64 @js_fastify_reply_header(i64, i64, i64) +declare i32 @js_fastify_reply_send(i64, double) +declare i64 @js_fastify_reply_status(i64, double) +declare i64 @js_fastify_reply_type(i64, i64) +declare i64 @js_fastify_req_body(i64) +declare double @js_fastify_req_get_user_data(i64) +declare i64 @js_fastify_req_header(i64, i64) +declare i64 @js_fastify_req_headers(i64) +declare double @js_fastify_req_json(i64) +declare i64 @js_fastify_req_method(i64) +declare i64 @js_fastify_req_param(i64, i64) +declare i64 @js_fastify_req_params(i64) +declare i64 @js_fastify_req_query(i64) +declare double @js_fastify_req_query_object(i64) +declare void @js_fastify_req_set_user_data(i64, double) +declare i64 @js_fastify_req_url(i64) +declare i32 @js_fastify_route(i64, i64, i64, i64) +declare i32 @js_fastify_set_error_handler(i64, i64) +declare double @js_nodemailer_create_transport(i64) +declare i64 @js_nodemailer_send_mail(i64, i64) +declare i64 @js_nodemailer_verify(i64) +declare i64 @js_ratelimit_block(i64, i64, double) +declare i64 @js_ratelimit_consume(i64, i64, double) +declare i64 @js_ratelimit_create(i64) +declare i64 @js_ratelimit_delete(i64, i64) +declare i64 @js_ratelimit_get(i64, i64) +declare i64 @js_ratelimit_new_from_options(i64) +declare i64 @js_ratelimit_penalty(i64, i64, double) +declare i64 @js_ratelimit_reward(i64, i64, double) +declare double @js_validator_contains(i64, i64) +declare double @js_validator_equals(i64, i64) +declare double @js_validator_is_alpha(i64) +declare double @js_validator_is_alphanumeric(i64) +declare double @js_validator_is_email(i64) +declare double @js_validator_is_empty(i64) +declare double @js_validator_is_float(i64) +declare double @js_validator_is_hexadecimal(i64) +declare double @js_validator_is_int(i64) +declare double @js_validator_is_json(i64) +declare double @js_validator_is_length(i64, double, double) +declare double @js_validator_is_lowercase(i64) +declare double @js_validator_is_numeric(i64) +declare double @js_validator_is_uppercase(i64) +declare double @js_validator_is_url(i64) +declare double @js_validator_is_uuid(i64) +declare i64 @js_date_to_locale_string(double) +declare i64 @js_number_to_locale_string(double) +declare double @js_value_to_locale_string(double) +declare i64 @js_string_split_regex(i64, i64) +declare i32 @js_object_delete_dynamic(i64, double) +declare double @js_object_get_prototype_of(double) +declare double @js_object_set_prototype_of(double, double) +declare double @js_object_define_properties(double, double) +declare double @js_math_acos(double) +declare double @js_math_asin(double) +declare double @js_math_atan(double) +declare double @js_math_atan2(double, double) +declare double @js_math_cos(double) +declare double @js_math_expm1(double) +declare double @js_math_log(double) +declare double @js_math_log10(double) +declare double @js_math_log1p(double) +declare double @js_math_log2(double) +declare double @js_math_sin(double) +declare double @js_math_tan(double) +declare double @js_atomics_load(ptr, double, double) +declare double @js_atomics_is_lock_free(ptr, double) +declare double @js_atomics_store(ptr, double, double, double) +declare double @js_atomics_add(ptr, double, double, double) +declare double @js_atomics_sub(ptr, double, double, double) +declare double @js_atomics_and(ptr, double, double, double) +declare double @js_atomics_or(ptr, double, double, double) +declare double @js_atomics_xor(ptr, double, double, double) +declare double @js_atomics_exchange(ptr, double, double, double) +declare double @js_atomics_compare_exchange(ptr, double, double, double, double) +declare double @js_atomics_notify(ptr, double, double, double) +declare double @js_atomics_wait(ptr, double, double, double, double) +declare double @js_atomics_wait_async(ptr, double, double, double, double) +declare double @js_number_is_finite(double) +declare double @js_json_get_bool(i64, i64) +declare double @js_json_get_number(i64, i64) +declare i64 @js_json_get_string(i64, i64) +declare double @js_json_is_valid(i64) +declare i64 @js_json_stringify_bool(double) +declare i64 @js_json_stringify_null() +declare i64 @js_json_stringify_number(double) +declare i64 @js_json_stringify_string(i64) +declare void @js_set_property(double, i64, i64, double) +declare i64 @js_error_get_message(i64) +declare double @js_await_js_promise(double) +declare i64 @js_text_decoder_decode(i64) +declare i64 @js_text_encoder_encode(double) +declare double @js_call_function(i64, i64, i64, i64, i64) +declare double @js_call_method(double, i64, i64, i64, i64) +declare double @js_call_value(double, i64, i64) +declare double @js_closure_call_array(i64, ptr, i64) +declare double @js_closure_call_apply_with_spread(double, ptr, i64, i64) +declare double @js_create_callback(i64, i64, i64) +declare double @js_dynamic_neg(double) +declare i32 @js_dynamic_string_equals(double, double) +declare double @js_is_nan(double) +declare i32 @js_jsvalue_compare(double, double) +declare i32 @js_jsvalue_loose_equals(double, double) +declare void @js_gc_collect() +declare void @js_console_assert(double, i64) +declare void @js_console_assert_spread(double, i64) +declare void @js_console_group(i64) +declare double @js_console_context(double) +declare double @js_console_create_task(double) +declare i64 @js_fetch_get(i64) +declare i64 @js_fetch_get_with_auth(i64, i64) +declare i64 @js_fetch_post(i64, i64, i64) +declare i64 @js_fetch_post_with_auth(i64, i64, i64) +declare double @js_fetch_stream_close(double) +declare i64 @js_fetch_stream_poll(double) +declare double @js_fetch_stream_start(i64, i64, i64, i64) +declare double @js_fetch_stream_status(double) +declare i64 @js_fetch_text(i64) +declare i64 @js_fetch_with_options(i64, i64, i64, i64) +declare void @js_fetch_set_pending_signal(double) +declare i64 @js_fetch_headers_to_json(double) +declare double @js_net_create_connection(i32, i64, i64) +declare i64 @js_net_create_server(i64, i64) +declare double @js_net_normalize_args(double) +declare double @js_net_create_server_handle_stub(double, double, double, double, double) +declare void @js_net_validate_create_server_options(double) +declare i64 @js_net_socket_set_timeout(i64, double, i64) +declare void @js_net_server_listen(i64, double, double, double) +declare void @js_net_server_close(i64, i64) +declare i64 @js_net_server_address(i64) +declare void @js_net_server_on(i64, i64, i64) +declare double @js_net_server_get_listening(i64) +declare double @js_net_server_get_connections(i64) +declare double @js_net_server_get_max_connections(i64) +declare double @js_net_server_set_max_connections(i64, double) +declare double @js_net_server_get_drop_max_connection(i64) +declare double @js_net_server_set_drop_max_connection(i64, double) +declare i64 @js_net_block_list_new() +declare double @js_net_block_list_is_block_list(double) +declare double @js_net_block_list_add_address(i64, i64, i64) +declare double @js_net_block_list_add_range(i64, i64, i64, i64) +declare double @js_net_block_list_add_subnet(i64, i64, double, i64) +declare double @js_net_block_list_check(i64, i64, i64) +declare double @js_net_block_list_to_json(i64) +declare i64 @js_net_block_list_rules(i64) +declare double @js_net_block_list_from_json(i64, double) +declare i64 @js_net_socket_address_new(double) +declare double @js_net_socket_address_parse(i64) +declare i64 @js_net_socket_address_get_address(i64) +declare i64 @js_net_socket_address_get_family(i64) +declare double @js_net_socket_address_get_port(i64) +declare double @js_net_socket_address_get_flowlabel(i64) +declare double @js_net_socket_get_type_of_service(i64) +declare i64 @js_net_socket_set_type_of_service(i64, double) +declare i64 @js_net_socket_address(i64) +declare i64 @js_net_socket_once(i64, i64, i64) +declare i64 @js_net_socket_remove_listener(i64, i64, i64) +declare i64 @js_net_socket_remove_all_listeners(i64, i64) +declare double @js_net_socket_listener_count(i64, i64) +declare i64 @js_net_socket_event_names(i64) +declare i64 @js_net_socket_reset_and_destroy(i64) +declare i64 @js_net_server_once(i64, i64, i64) +declare i64 @js_net_server_remove_listener(i64, i64, i64) +declare i64 @js_net_server_remove_all_listeners(i64, i64) +declare double @js_net_server_listener_count(i64, i64) +declare i64 @js_net_server_event_names(i64) +declare double @js_performance_now() +declare double @js_perf_mark(double, double) +declare double @js_perf_measure(double, double, double) +declare double @js_perf_get_entries() +declare double @js_perf_get_entries_by_type(double) +declare double @js_perf_get_entries_by_name(double, double) +declare double @js_perf_clear_marks(double) +declare double @js_perf_clear_measures(double) +declare double @js_perf_event_loop_utilization(double, double) +declare double @js_perf_to_json() +declare double @js_perf_clear_resource_timings() +declare double @js_perf_set_resource_timing_buffer_size(double) +declare double @js_perf_mark_resource_timing(double, double, double, double, double, double, double, double) +declare double @js_perf_timerify(double, double) +declare double @js_perf_observer_new(double) +declare double @js_perf_observer_observe(double, double) +declare double @js_perf_observer_disconnect(double) +declare double @js_perf_observer_take_records(double) +declare double @js_perf_monitor_event_loop_delay(double) +declare double @js_perf_create_histogram(double) +declare double @js_perf_histogram_noop() +declare double @js_perf_histogram_percentile(double) +declare double @js_iter_result_set(double, i32) +declare double @js_iter_result_set_f64(double, i32) +declare double @js_iter_result_set_i32(i32, i32) +declare double @js_iter_result_set_i1(i32, i32) +declare double @js_iter_result_get_value() +declare double @js_iter_result_get_value_f64() +declare i32 @js_iter_result_get_value_i32() +declare i32 @js_iter_result_get_value_i1() +declare double @js_iter_result_get_done() +declare i64 @js_async_step_chain(double, i64) +declare i64 @js_async_step_done(double, i64) +declare i64 @js_get_current_step_closure() +declare double @js_async_first_call(double) +declare double @js_async_generator_resume(double, double, double) +declare i64 @js_slugify(i64) +declare i64 @js_slugify_strict(i64) +declare void @js_register_class_getter(i64, i64, i64, i64) +declare void @js_register_class_setter(i64, i64, i64, i64) +declare void @js_register_class_method_bind_length(i64, i64, i64, i64) +declare void @js_register_class_static_method_bind_length(i64, i64, i64, i64) +declare void @js_register_class_static_getter(i64, i64, i64, i64) +declare void @js_register_class_static_setter(i64, i64, i64, i64) +declare void @js_register_class_method(i64, i64, i64, i64, i64, i64, i64) +declare void @js_register_class_constructor(i64, i64, i64, i64) +declare void @js_register_class_constructor_flags(i64, i64, i64) +declare void @js_register_class_static_method(i64, i64, i64, i64, i64, i64) +declare double @js_class_static_method_call(double, i64, i64, ptr, i64) +declare double @js_class_method_bind(double, i64, i64) +declare double @js_class_method_bind_by_id(double, i64) +declare double @js_class_prototype_method_value(double, double) +declare double @js_implicit_this_get() +declare double @js_implicit_this_get_sloppy() +declare double @js_implicit_this_set(double) +declare double @js_static_this_resolve(double) +declare void @js_static_this_arm_classref(i32) +declare void @js_static_this_arm_value(double) +declare double @js_ctor_return_override(double, double, i32) +declare double @js_new_target_get() +declare double @js_new_target_set(double) +declare double @js_get_export(i64, i64, i64) +declare double @js_get_property(double, i64, i64) +declare i64 @js_load_module(i64, i64) +declare double @js_module_dynamic_import_apply_hooks(double) +declare double @js_native_call_method_nullsafe(double, i64, i64, i64, i64) +declare double @js_native_call_value(double, i64, i64) +declare double @js_new_from_handle(double, i64, i64) +declare double @js_new_instance(i64, i64, i64, i64, i64) +declare void @js_runtime_init() +declare double @js_object_set_symbol_method(double, double, double) +declare double @js_object_set_method_by_name(double, double, double) +declare double @js_object_define_accessor(double, double, double, double) +declare double @js_object_literal_set_computed(double, double, double) +declare double @js_object_literal_to_property_key(double) +declare double @js_object_literal_set_prototype(double, double) +declare double @js_to_primitive(double, i32) +declare void @js_register_class_has_instance(i32, i64) +declare void @js_register_class_to_string_tag(i32, i64) +declare double @js_object_to_string(double) +declare double @js_object_group_by(double, double) +declare double @js_map_group_by(double, double) +declare double @js_array_from_async(double, double, double) +declare double @js_jsx(double, double) +declare double @js_jsxs(double, double) +declare i64 @js_node_http_server_ref(i64) +declare i64 @js_node_http_server_unref(i64) +declare i64 @js_node_https_server_ref(i64) +declare i64 @js_node_https_server_unref(i64) +declare double @js_http_client_request_flush_headers(i64, double, double) +declare double @js_node_http_im_http_version_major(i64) +declare double @js_node_http_im_http_version_minor(i64) +declare i64 @js_node_http_im_pause_self(i64) +declare i64 @js_node_http_im_resume_self(i64) +declare i64 @js_commander_args_array(i64) +declare i64 @js_commander_argument(i64, i64) + +define i64 @perry_fn_spike_ts__fib_i64(i64 %arg3) alwaysinline { +entry.0: + %r1 = alloca i64 + store i64 %arg3, ptr %r1 + %r2 = alloca i64 + %r3 = load i64, ptr %r1 + %r4 = icmp slt i64 %r3, 2 + br i1 %r4, label %i64.cond.then.1, label %i64.cond.else.2 + +i64.cond.then.1: + %r5 = load i64, ptr %r1 + store i64 %r5, ptr %r2 + br label %i64.cond.merge.3 + +i64.cond.else.2: + %r6 = load i64, ptr %r1 + %r7 = sub i64 %r6, 1 + %r8 = call i64 @perry_fn_spike_ts__fib_i64(i64 %r7) + %r9 = load i64, ptr %r1 + %r10 = sub i64 %r9, 2 + %r11 = call i64 @perry_fn_spike_ts__fib_i64(i64 %r10) + %r12 = add i64 %r8, %r11 + store i64 %r12, ptr %r2 + br label %i64.cond.merge.3 + +i64.cond.merge.3: + %r13 = load i64, ptr %r2 + ret i64 %r13 +} + +define double @perry_fn_spike_ts__fib(double %arg3) alwaysinline { +entry.0: + %r1 = fptosi double %arg3 to i64 + %r2 = call i64 @perry_fn_spike_ts__fib_i64(i64 %r1) + %r3 = sitofp i64 %r2 to double + ret double %r3 +} + +define double @perry_closure_spike_ts__1(i64 %this_closure, double %arg4, double %arg5) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 2) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %arg4, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = alloca double + store double %arg5, ptr %r8 + call void @js_shadow_slot_bind(i32 1, ptr %r8) + %r9 = load double, ptr %r7 + %r10 = load double, ptr %r8 + %r11 = call double @js_dynamic_sub(double %r9, double %r10) + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r11 +} + +define double @perry_closure_spike_ts__4(i64 %this_closure, double %arg19) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 1) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r15 = alloca [32 x double] + %r7 = alloca double + store double %arg19, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = load double, ptr @spike_ts_.str.0.handle + %r9 = load double, ptr %r7 + %r10 = call i64 @js_string_coerce(double %r9) + %r11 = or i64 %r10, 9223090561878065152 + %r12 = bitcast i64 %r11 to double + %r13 = load double, ptr @spike_ts_.str.1.handle + %r14 = load double, ptr @spike_ts_.str.0.handle + %r16 = getelementptr double, ptr %r15, i64 0 + store double %r14, ptr %r16 + %r17 = getelementptr double, ptr %r15, i64 1 + store double %r12, ptr %r17 + %r18 = getelementptr double, ptr %r15, i64 2 + store double %r13, ptr %r18 + %r19 = ptrtoint ptr %r15 to i64 + %r20 = call i64 @js_string_concat_chain(i64 %r19, i32 3) + %r21 = or i64 %r20, 9223090561878065152 + %r22 = bitcast i64 %r21 to double + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r22 +} + +define double @perry_closure_spike_ts__5(i64 %this_closure) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 5) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r10 = alloca i64 + store i64 9222246136947933185, ptr %r10 + %r33 = alloca i64 + store i64 9222246136947933185, ptr %r33 + %r56 = alloca i64 + store i64 9222246136947933185, ptr %r56 + %r58 = alloca i64 + store i64 9222246136947933185, ptr %r58 + %r60 = alloca i64 + store i64 9222246136947933185, ptr %r60 + %r83 = alloca i64 + store i64 9222246136947933185, ptr %r83 + %r96 = alloca double + store double 0x7FFC000000000001, ptr %r96 + %r103 = alloca [6 x i64] + %r7 = alloca i64 + %r8 = or i64 %this_closure, 9222527611924643840 + store i64 %r8, ptr %r7 + call void @js_shadow_slot_bind(i32 4, ptr %r7) + %r9 = call i64 @js_box_alloc_bits(i64 9222246136947933185) + store i64 %r9, ptr %r10 + %r11 = load ptr, ptr %r2 + %r12 = icmp eq ptr %r11, null + br i1 %r12, label %ss.slow.1, label %ss.chk_top.2 + +ss.slow.1: + call void @js_shadow_slot_bind(i32 1, ptr %r10) + br label %ss.done.5 + +ss.chk_top.2: + %r13 = getelementptr inbounds i8, ptr %r11, i64 24 + %r14 = load i64, ptr %r13 + %r15 = icmp eq i64 %r14, -1 + br i1 %r15, label %ss.done.5, label %ss.chk_len.3 + +ss.chk_len.3: + %r16 = add i64 %r14, 1 + %r17 = getelementptr inbounds i8, ptr %r11, i64 8 + %r18 = load i64, ptr %r17 + %r19 = icmp ult i64 %r16, %r18 + br i1 %r19, label %ss.store.4, label %ss.done.5 + +ss.store.4: + %r20 = load ptr, ptr %r11 + %r21 = shl i64 %r16, 4 + %r22 = getelementptr inbounds i8, ptr %r20, i64 %r21 + %r23 = getelementptr inbounds i8, ptr %r22, i64 8 + %r24 = load i64, ptr %r10 + %r25 = ptrtoint ptr %r10 to i64 + %r26 = and i64 %r25, 1 + %r27 = icmp eq i64 %r26, 0 + %r28 = select i1 %r27, i64 %r25, i64 0 + %r29 = or i64 %r28, 1 + store i64 %r24, ptr %r22 + store i64 %r29, ptr %r23 + %r30 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r31 = icmp ne i32 %r30, 0 + br i1 %r31, label %ss.barrier.6, label %ss.done.5 + +ss.done.5: + %r32 = call i64 @js_box_alloc_bits(i64 9222246136947933185) + store i64 %r32, ptr %r33 + %r34 = load ptr, ptr %r2 + %r35 = icmp eq ptr %r34, null + br i1 %r35, label %ss.slow.7, label %ss.chk_top.8 + +ss.barrier.6: + call void @js_write_barrier_root_nanbox(i64 %r24) + br label %ss.done.5 + +ss.slow.7: + call void @js_shadow_slot_bind(i32 0, ptr %r33) + br label %ss.done.11 + +ss.chk_top.8: + %r36 = getelementptr inbounds i8, ptr %r34, i64 24 + %r37 = load i64, ptr %r36 + %r38 = icmp eq i64 %r37, -1 + br i1 %r38, label %ss.done.11, label %ss.chk_len.9 + +ss.chk_len.9: + %r39 = add i64 %r37, 0 + %r40 = getelementptr inbounds i8, ptr %r34, i64 8 + %r41 = load i64, ptr %r40 + %r42 = icmp ult i64 %r39, %r41 + br i1 %r42, label %ss.store.10, label %ss.done.11 + +ss.store.10: + %r43 = load ptr, ptr %r34 + %r44 = shl i64 %r39, 4 + %r45 = getelementptr inbounds i8, ptr %r43, i64 %r44 + %r46 = getelementptr inbounds i8, ptr %r45, i64 8 + %r47 = load i64, ptr %r33 + %r48 = ptrtoint ptr %r33 to i64 + %r49 = and i64 %r48, 1 + %r50 = icmp eq i64 %r49, 0 + %r51 = select i1 %r50, i64 %r48, i64 0 + %r52 = or i64 %r51, 1 + store i64 %r47, ptr %r45 + store i64 %r52, ptr %r46 + %r53 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r54 = icmp ne i32 %r53, 0 + br i1 %r54, label %ss.barrier.12, label %ss.done.11 + +ss.done.11: + %r55 = call i64 @js_i32_box_alloc(i32 0) + store i64 %r55, ptr %r56 + %r57 = call i64 @js_bool_box_alloc(i32 0) + store i64 %r57, ptr %r58 + %r59 = call i64 @js_box_alloc_bits(i64 9222246136947933185) + store i64 %r59, ptr %r60 + %r61 = load ptr, ptr %r2 + %r62 = icmp eq ptr %r61, null + br i1 %r62, label %ss.slow.13, label %ss.chk_top.14 + +ss.barrier.12: + call void @js_write_barrier_root_nanbox(i64 %r47) + br label %ss.done.11 + +ss.slow.13: + call void @js_shadow_slot_bind(i32 2, ptr %r60) + br label %ss.done.17 + +ss.chk_top.14: + %r63 = getelementptr inbounds i8, ptr %r61, i64 24 + %r64 = load i64, ptr %r63 + %r65 = icmp eq i64 %r64, -1 + br i1 %r65, label %ss.done.17, label %ss.chk_len.15 + +ss.chk_len.15: + %r66 = add i64 %r64, 2 + %r67 = getelementptr inbounds i8, ptr %r61, i64 8 + %r68 = load i64, ptr %r67 + %r69 = icmp ult i64 %r66, %r68 + br i1 %r69, label %ss.store.16, label %ss.done.17 + +ss.store.16: + %r70 = load ptr, ptr %r61 + %r71 = shl i64 %r66, 4 + %r72 = getelementptr inbounds i8, ptr %r70, i64 %r71 + %r73 = getelementptr inbounds i8, ptr %r72, i64 8 + %r74 = load i64, ptr %r60 + %r75 = ptrtoint ptr %r60 to i64 + %r76 = and i64 %r75, 1 + %r77 = icmp eq i64 %r76, 0 + %r78 = select i1 %r77, i64 %r75, i64 0 + %r79 = or i64 %r78, 1 + store i64 %r74, ptr %r72 + store i64 %r79, ptr %r73 + %r80 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r81 = icmp ne i32 %r80, 0 + br i1 %r81, label %ss.barrier.18, label %ss.done.17 + +ss.done.17: + %r82 = call i64 @js_bool_box_alloc(i32 0) + store i64 %r82, ptr %r83 + %r84 = load i64, ptr %r56 + call void @js_i32_box_set(i64 %r84, i32 0) + %r85 = sitofp i32 0 to double + %r86 = load i64, ptr %r58 + %r87 = zext i1 false to i32 + call void @js_bool_box_set(i64 %r86, i32 %r87) + %r88 = select i1 false, i64 9222246136947933188, i64 9222246136947933187 + %r89 = bitcast i64 %r88 to double + %r90 = load i64, ptr %r83 + %r91 = zext i1 false to i32 + call void @js_bool_box_set(i64 %r90, i32 %r91) + %r92 = select i1 false, i64 9222246136947933188, i64 9222246136947933187 + %r93 = bitcast i64 %r92 to double + %r94 = load i64, ptr %r60 + %r95 = bitcast double 0x7FFC000000000001 to i64 + call void @js_box_set_bits(i64 %r94, i64 %r95) + call void @js_write_barrier(i64 %r94, i64 %r95) + %r97 = load i64, ptr %r10 + %r98 = load i64, ptr %r33 + %r99 = load i64, ptr %r56 + %r100 = load i64, ptr %r58 + %r101 = load i64, ptr %r60 + %r102 = load i64, ptr %r83 + %r104 = getelementptr i64, ptr %r103, i64 0 + store i64 %r97, ptr %r104 + %r105 = getelementptr i64, ptr %r103, i64 1 + store i64 %r98, ptr %r105 + %r106 = getelementptr i64, ptr %r103, i64 2 + store i64 %r99, ptr %r106 + %r107 = getelementptr i64, ptr %r103, i64 3 + store i64 %r100, ptr %r107 + %r108 = getelementptr i64, ptr %r103, i64 4 + store i64 %r101, ptr %r108 + %r109 = getelementptr i64, ptr %r103, i64 5 + store i64 %r102, ptr %r109 + %r110 = call i64 @js_closure_alloc_with_captures_singleton(ptr @perry_closure_spike_ts__8, i32 6, ptr %r103) + %r111 = or i64 %r110, 9222527611924643840 + %r112 = bitcast i64 %r111 to double + store double %r112, ptr %r96 + %r113 = load ptr, ptr %r2 + %r114 = icmp eq ptr %r113, null + br i1 %r114, label %ss.slow.19, label %ss.chk_top.20 + +ss.barrier.18: + call void @js_write_barrier_root_nanbox(i64 %r74) + br label %ss.done.17 + +ss.slow.19: + call void @js_shadow_slot_bind(i32 3, ptr %r96) + br label %ss.done.23 + +ss.chk_top.20: + %r115 = getelementptr inbounds i8, ptr %r113, i64 24 + %r116 = load i64, ptr %r115 + %r117 = icmp eq i64 %r116, -1 + br i1 %r117, label %ss.done.23, label %ss.chk_len.21 + +ss.chk_len.21: + %r118 = add i64 %r116, 3 + %r119 = getelementptr inbounds i8, ptr %r113, i64 8 + %r120 = load i64, ptr %r119 + %r121 = icmp ult i64 %r118, %r120 + br i1 %r121, label %ss.store.22, label %ss.done.23 + +ss.store.22: + %r122 = load ptr, ptr %r113 + %r123 = shl i64 %r118, 4 + %r124 = getelementptr inbounds i8, ptr %r122, i64 %r123 + %r125 = getelementptr inbounds i8, ptr %r124, i64 8 + %r126 = load i64, ptr %r96 + %r127 = ptrtoint ptr %r96 to i64 + %r128 = and i64 %r127, 1 + %r129 = icmp eq i64 %r128, 0 + %r130 = select i1 %r129, i64 %r127, i64 0 + %r131 = or i64 %r130, 1 + store i64 %r126, ptr %r124 + store i64 %r131, ptr %r125 + %r132 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r133 = icmp ne i32 %r132, 0 + br i1 %r133, label %ss.barrier.24, label %ss.done.23 + +ss.done.23: + %r134 = load double, ptr %r96 + %r135 = call double @js_async_first_call(double %r134) + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r135 + +ss.barrier.24: + call void @js_write_barrier_root_nanbox(i64 %r126) + br label %ss.done.23 +} + +define double @perry_closure_spike_ts__8(i64 %this_closure, double %arg31, double %arg32) #1 { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 5) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r11 = alloca double + store double 0x7FFC000000000001, ptr %r11 + %r43 = alloca double + store volatile double 0x7FFC000000000001, ptr %r43 + %r156 = alloca double + %r7 = alloca double + store double %arg31, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = alloca double + store double %arg32, ptr %r8 + %r9 = alloca i64 + %r10 = or i64 %this_closure, 9222527611924643840 + store i64 %r10, ptr %r9 + call void @js_shadow_slot_bind(i32 4, ptr %r9) + %r12 = call i64 @js_get_current_step_closure() + %r13 = or i64 %r12, 9222527611924643840 + %r14 = bitcast i64 %r13 to double + store double %r14, ptr %r11 + %r15 = load ptr, ptr %r2 + %r16 = icmp eq ptr %r15, null + br i1 %r16, label %ss.slow.1, label %ss.chk_top.2 + +ss.slow.1: + call void @js_shadow_slot_bind(i32 1, ptr %r11) + br label %ss.done.5 + +ss.chk_top.2: + %r17 = getelementptr inbounds i8, ptr %r15, i64 24 + %r18 = load i64, ptr %r17 + %r19 = icmp eq i64 %r18, -1 + br i1 %r19, label %ss.done.5, label %ss.chk_len.3 + +ss.chk_len.3: + %r20 = add i64 %r18, 1 + %r21 = getelementptr inbounds i8, ptr %r15, i64 8 + %r22 = load i64, ptr %r21 + %r23 = icmp ult i64 %r20, %r22 + br i1 %r23, label %ss.store.4, label %ss.done.5 + +ss.store.4: + %r24 = load ptr, ptr %r15 + %r25 = shl i64 %r20, 4 + %r26 = getelementptr inbounds i8, ptr %r24, i64 %r25 + %r27 = getelementptr inbounds i8, ptr %r26, i64 8 + %r28 = load i64, ptr %r11 + %r29 = ptrtoint ptr %r11 to i64 + %r30 = and i64 %r29, 1 + %r31 = icmp eq i64 %r30, 0 + %r32 = select i1 %r31, i64 %r29, i64 0 + %r33 = or i64 %r32, 1 + store i64 %r28, ptr %r26 + store i64 %r33, ptr %r27 + %r34 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r35 = icmp ne i32 %r34, 0 + br i1 %r35, label %ss.barrier.6, label %ss.done.5 + +ss.done.5: + %r36 = call ptr @js_try_push() + %r37 = call i32 @_setjmp(ptr %r36) #0 + %r38 = icmp ne i32 %r37, 0 + br i1 %r38, label %try.catch.8, label %try.body.7 + +ss.barrier.6: + call void @js_write_barrier_root_nanbox(i64 %r28) + br label %ss.done.5 + +try.body.7: + br label %dowhile.body.10 + +try.catch.8: + call void @js_try_end() + %r155 = call double @js_get_exception() + call void @js_clear_exception() + store double %r155, ptr %r156 + %r157 = load ptr, ptr %r2 + %r158 = icmp eq ptr %r157, null + br i1 %r158, label %ss.slow.39, label %ss.chk_top.40 + +try.finally.9: + %r197 = call double @js_iter_result_get_done() + %r198 = call i32 @js_is_truthy(double %r197) + %r199 = icmp ne i32 %r198, 0 + br i1 %r199, label %if.then.48, label %if.else.49 + +dowhile.body.10: + %r39 = load double, ptr %r8 + %r40 = bitcast double %r39 to i64 + %r41 = icmp eq i64 %r40, 9222246136947933188 + br i1 %r41, label %if.then.13, label %if.else.14 + +dowhile.cond.11: + %r152 = select i1 false, i64 9222246136947933188, i64 9222246136947933187 + %r153 = bitcast i64 %r152 to double + %r154 = icmp eq i64 %r152, 9222246136947933188 + br i1 %r154, label %dowhile.body.10, label %dowhile.exit.12 + +dowhile.exit.12: + call void @js_try_end() + br label %try.finally.9 + +if.then.13: + %r42 = load double, ptr %r7 + call void @js_throw(double %r42) + unreachable + +if.else.14: + %r44 = load double, ptr %r7 + store volatile double %r44, ptr %r43 + %r45 = load ptr, ptr %r2 + %r46 = icmp eq ptr %r45, null + br i1 %r46, label %ss.slow.16, label %ss.chk_top.17 + +if.merge.15: + %r137 = load ptr, ptr %r2 + %r138 = icmp eq ptr %r137, null + br i1 %r138, label %ss.slow.34, label %ss.chk_top.35 + +ss.slow.16: + call void @js_shadow_slot_bind(i32 2, ptr %r43) + br label %ss.done.20 + +ss.chk_top.17: + %r47 = getelementptr inbounds i8, ptr %r45, i64 24 + %r48 = load i64, ptr %r47 + %r49 = icmp eq i64 %r48, -1 + br i1 %r49, label %ss.done.20, label %ss.chk_len.18 + +ss.chk_len.18: + %r50 = add i64 %r48, 2 + %r51 = getelementptr inbounds i8, ptr %r45, i64 8 + %r52 = load i64, ptr %r51 + %r53 = icmp ult i64 %r50, %r52 + br i1 %r53, label %ss.store.19, label %ss.done.20 + +ss.store.19: + %r54 = load ptr, ptr %r45 + %r55 = shl i64 %r50, 4 + %r56 = getelementptr inbounds i8, ptr %r54, i64 %r55 + %r57 = getelementptr inbounds i8, ptr %r56, i64 8 + %r58 = load volatile i64, ptr %r43 + %r59 = ptrtoint ptr %r43 to i64 + %r60 = and i64 %r59, 1 + %r61 = icmp eq i64 %r60, 0 + %r62 = select i1 %r61, i64 %r59, i64 0 + %r63 = or i64 %r62, 1 + store i64 %r58, ptr %r56 + store i64 %r63, ptr %r57 + %r64 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r65 = icmp ne i32 %r64, 0 + br i1 %r65, label %ss.barrier.21, label %ss.done.20 + +ss.done.20: + %r66 = load volatile double, ptr %r43 + %r67 = load i64, ptr %r9 + %r68 = and i64 %r67, 281474976710655 + %r69 = call i64 @js_closure_get_capture_bits(i64 %r68, i32 4) + %r70 = bitcast double %r66 to i64 + call void @js_box_set_bits(i64 %r69, i64 %r70) + call void @js_write_barrier(i64 %r69, i64 %r70) + %r71 = load i64, ptr %r9 + %r72 = and i64 %r71, 281474976710655 + %r73 = call i64 @js_closure_get_capture_bits(i64 %r72, i32 3) + %r74 = call i32 @js_bool_box_get(i64 %r73) + %r75 = icmp ne i32 %r74, 0 + br i1 %r75, label %if.then.22, label %if.else.23 + +ss.barrier.21: + call void @js_write_barrier_root_nanbox(i64 %r58) + br label %ss.done.20 + +if.then.22: + %r76 = call double @js_iter_result_set(double 0x7FFC000000000001, i32 1) + br label %dowhile.exit.12 + +if.else.23: + br label %if.merge.24 + +if.merge.24: + br label %while.cond.25 + +while.cond.25: + %r77 = select i1 true, i64 9222246136947933188, i64 9222246136947933187 + %r78 = bitcast i64 %r77 to double + %r79 = icmp eq i64 %r77, 9222246136947933188 + br i1 %r79, label %while.body.26, label %while.exit.27 + +while.body.26: + %r80 = load i64, ptr %r9 + %r81 = and i64 %r80, 281474976710655 + %r82 = call i64 @js_closure_get_capture_bits(i64 %r81, i32 2) + %r83 = call i32 @js_i32_box_get(i64 %r82) + %r84 = icmp eq i32 %r83, 0 + br i1 %r84, label %if.then.28, label %if.else.29 + +while.exit.27: + br label %if.merge.15 + +if.then.28: + %r85 = call i64 @js_promise_resolved(double 42.0) + %r86 = or i64 %r85, 9222527611924643840 + %r87 = bitcast i64 %r86 to double + %r88 = load i64, ptr %r9 + %r89 = and i64 %r88, 281474976710655 + %r90 = call i64 @js_closure_get_capture_bits(i64 %r89, i32 1) + call void @js_box_set_bits(i64 %r90, i64 %r86) + call void @js_write_barrier(i64 %r90, i64 %r86) + %r91 = load i64, ptr %r9 + %r92 = and i64 %r91, 281474976710655 + %r93 = call i64 @js_closure_get_capture_bits(i64 %r92, i32 2) + call void @js_i32_box_set(i64 %r93, i32 1) + %r94 = sitofp i32 1 to double + %r95 = load i64, ptr %r9 + %r96 = and i64 %r95, 281474976710655 + %r97 = call i64 @js_closure_get_capture_bits(i64 %r96, i32 1) + %r98 = call i64 @js_box_get_bits(i64 %r97) + %r99 = bitcast i64 %r98 to double + %r100 = call double @js_iter_result_set(double %r99, i32 0) + br label %dowhile.exit.12 + +if.else.29: + br label %if.merge.30 + +if.merge.30: + %r101 = load i64, ptr %r9 + %r102 = and i64 %r101, 281474976710655 + %r103 = call i64 @js_closure_get_capture_bits(i64 %r102, i32 2) + %r104 = call i32 @js_i32_box_get(i64 %r103) + %r105 = icmp eq i32 %r104, 1 + br i1 %r105, label %if.then.31, label %if.else.32 + +if.then.31: + %r106 = load i64, ptr %r9 + %r107 = and i64 %r106, 281474976710655 + %r108 = call i64 @js_closure_get_capture_bits(i64 %r107, i32 4) + %r109 = call i64 @js_box_get_bits(i64 %r108) + %r110 = bitcast i64 %r109 to double + %r111 = load i64, ptr %r9 + %r112 = and i64 %r111, 281474976710655 + %r113 = call i64 @js_closure_get_capture_bits(i64 %r112, i32 0) + call void @js_box_set_bits(i64 %r113, i64 %r109) + call void @js_write_barrier(i64 %r113, i64 %r109) + %r114 = call i64 @js_array_alloc(i32 2) + %r115 = call i32 @js_gc_temp_root_push(i64 %r114) + %r116 = load double, ptr @spike_ts_.str.2.handle + call void @js_array_push_f64_temp_rooted(i32 %r115, double %r116) + %r117 = load i64, ptr %r9 + %r118 = and i64 %r117, 281474976710655 + %r119 = call i64 @js_closure_get_capture_bits(i64 %r118, i32 0) + %r120 = call i64 @js_box_get_bits(i64 %r119) + %r121 = bitcast i64 %r120 to double + call void @js_array_push_f64_temp_rooted(i32 %r115, double %r121) + %r122 = call i64 @js_gc_temp_root_get(i32 %r115) + call void @js_console_log_spread(i64 %r122) + call void @js_gc_temp_root_truncate(i32 %r115) + %r123 = load i64, ptr %r9 + %r124 = and i64 %r123, 281474976710655 + %r125 = call i64 @js_closure_get_capture_bits(i64 %r124, i32 3) + %r126 = zext i1 true to i32 + call void @js_bool_box_set(i64 %r125, i32 %r126) + %r127 = select i1 true, i64 9222246136947933188, i64 9222246136947933187 + %r128 = bitcast i64 %r127 to double + %r129 = call double @js_iter_result_set(double 0x7FFC000000000001, i32 1) + br label %dowhile.exit.12 + +if.else.32: + br label %if.merge.33 + +if.merge.33: + %r130 = load i64, ptr %r9 + %r131 = and i64 %r130, 281474976710655 + %r132 = call i64 @js_closure_get_capture_bits(i64 %r131, i32 3) + %r133 = zext i1 true to i32 + call void @js_bool_box_set(i64 %r132, i32 %r133) + %r134 = select i1 true, i64 9222246136947933188, i64 9222246136947933187 + %r135 = bitcast i64 %r134 to double + %r136 = call double @js_iter_result_set(double 0x7FFC000000000001, i32 1) + br label %dowhile.exit.12 + +ss.slow.34: + call void @js_shadow_slot_set(i32 2, i64 0) + br label %ss.done.38 + +ss.chk_top.35: + %r139 = getelementptr inbounds i8, ptr %r137, i64 24 + %r140 = load i64, ptr %r139 + %r141 = icmp eq i64 %r140, -1 + br i1 %r141, label %ss.done.38, label %ss.chk_len.36 + +ss.chk_len.36: + %r142 = add i64 %r140, 2 + %r143 = getelementptr inbounds i8, ptr %r137, i64 8 + %r144 = load i64, ptr %r143 + %r145 = icmp ult i64 %r142, %r144 + br i1 %r145, label %ss.store.37, label %ss.done.38 + +ss.store.37: + %r146 = load ptr, ptr %r137 + %r147 = shl i64 %r142, 4 + %r148 = getelementptr inbounds i8, ptr %r146, i64 %r147 + %r149 = getelementptr inbounds i8, ptr %r148, i64 8 + %r150 = load i64, ptr %r149 + %r151 = and i64 %r150, -2 + store i64 0, ptr %r148 + store i64 %r151, ptr %r149 + br label %ss.done.38 + +ss.done.38: + br label %dowhile.cond.11 + +ss.slow.39: + call void @js_shadow_slot_bind(i32 3, ptr %r156) + br label %ss.done.43 + +ss.chk_top.40: + %r159 = getelementptr inbounds i8, ptr %r157, i64 24 + %r160 = load i64, ptr %r159 + %r161 = icmp eq i64 %r160, -1 + br i1 %r161, label %ss.done.43, label %ss.chk_len.41 + +ss.chk_len.41: + %r162 = add i64 %r160, 3 + %r163 = getelementptr inbounds i8, ptr %r157, i64 8 + %r164 = load i64, ptr %r163 + %r165 = icmp ult i64 %r162, %r164 + br i1 %r165, label %ss.store.42, label %ss.done.43 + +ss.store.42: + %r166 = load ptr, ptr %r157 + %r167 = shl i64 %r162, 4 + %r168 = getelementptr inbounds i8, ptr %r166, i64 %r167 + %r169 = getelementptr inbounds i8, ptr %r168, i64 8 + %r170 = load i64, ptr %r156 + %r171 = ptrtoint ptr %r156 to i64 + %r172 = and i64 %r171, 1 + %r173 = icmp eq i64 %r172, 0 + %r174 = select i1 %r173, i64 %r171, i64 0 + %r175 = or i64 %r174, 1 + store i64 %r170, ptr %r168 + store i64 %r175, ptr %r169 + %r176 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r177 = icmp ne i32 %r176, 0 + br i1 %r177, label %ss.barrier.44, label %ss.done.43 + +ss.done.43: + %r178 = load double, ptr %r8 + %r179 = bitcast double %r178 to i64 + %r180 = icmp eq i64 %r179, 9222246136947933188 + br i1 %r180, label %if.then.45, label %if.else.46 + +ss.barrier.44: + call void @js_write_barrier_root_nanbox(i64 %r170) + br label %ss.done.43 + +if.then.45: + %r181 = load double, ptr %r156 + %r182 = call i64 @js_promise_rejected(double %r181) + %r183 = or i64 %r182, 9222527611924643840 + %r184 = bitcast i64 %r183 to double + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r184 + +if.else.46: + br label %if.merge.47 + +if.merge.47: + %r185 = load double, ptr %r11 + %r186 = load double, ptr %r156 + %r187 = select i1 true, i64 9222246136947933188, i64 9222246136947933187 + %r188 = bitcast i64 %r187 to double + %r189 = call double @js_implicit_this_set(double 0x7FFC000000000001) + %r190 = bitcast double %r189 to i64 + %r191 = call i32 @js_gc_temp_root_push(i64 %r190) + %r192 = call i64 @js_closure_unbox_callee_checked(double %r185) + %r193 = call double @js_closure_call2(i64 %r192, double %r186, double %r188) + %r194 = call i64 @js_gc_temp_root_get(i32 %r191) + %r195 = bitcast i64 %r194 to double + call void @js_gc_temp_root_truncate(i32 %r191) + %r196 = call double @js_implicit_this_set(double %r195) + %shadow_pop_l_1 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_1) + ret double %r193 + +if.then.48: + %r200 = call double @js_iter_result_get_value() + %r201 = load double, ptr %r11 + %r202 = bitcast double %r201 to i64 + %r203 = and i64 %r202, 281474976710655 + %r204 = call i64 @js_async_step_done(double %r200, i64 %r203) + %r205 = or i64 %r204, 9222527611924643840 + %r206 = bitcast i64 %r205 to double + %shadow_pop_l_2 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_2) + ret double %r206 + +if.else.49: + br label %if.merge.50 + +if.merge.50: + %r207 = call double @js_iter_result_get_value() + %r208 = load double, ptr %r11 + %r209 = bitcast double %r208 to i64 + %r210 = and i64 %r209, 281474976710655 + %r211 = call i64 @js_async_step_chain(double %r207, i64 %r210) + %r212 = or i64 %r211, 9222527611924643840 + %r213 = bitcast i64 %r212 to double + %shadow_pop_l_3 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_3) + ret double %r213 +} + +define double @perry_method_spike_ts__Point__norm(double %this_arg) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 1) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %this_arg, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = load double, ptr %r7 + %r9 = bitcast double %r8 to i64 + %r10 = and i64 %r9, 281474976710655 + %r11 = load double, ptr @spike_ts_.str.3.handle + %r12 = bitcast double %r11 to i64 + %r13 = and i64 %r12, 281474976710655 + %r14 = load i64, ptr @perry_class_keys_spike_ts__Point + %r15 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r16 = icmp eq i8 %r15, 0 + %r17 = lshr i64 %r9, 48 + %r18 = icmp eq i64 %r17, 32765 + %r19 = icmp ugt i64 %r10, 1048575 + %r20 = and i1 %r18, %r19 + %r21 = and i1 %r20, %r16 + br i1 %r21, label %class_field_inline.deref.4, label %class_field_inline.guardcall.5 + +class_field_get_number.fast.1: + %r56 = inttoptr i64 %r10 to ptr + %r57 = getelementptr i8, ptr %r56, i64 32 + %r58 = getelementptr double, ptr %r57, i64 0 + %r59 = load double, ptr %r58 + br label %class_field_get_number.merge.3 + +class_field_get_number.fallback.2: + call void @js_typed_feedback_record_fallback_call(i64 7695367220062322688) + %r60 = call double @js_object_get_field_by_name_f64(i64 %r9, i64 %r13) + %r61 = call double @js_number_coerce(double %r60) + br label %class_field_get_number.merge.3 + +class_field_get_number.merge.3: + %r62 = phi double [ %r59, %class_field_get_number.fast.1 ], [ %r61, %class_field_get_number.fallback.2 ] + %r63 = load double, ptr %r7 + %r64 = bitcast double %r63 to i64 + %r65 = and i64 %r64, 281474976710655 + %r66 = load double, ptr @spike_ts_.str.3.handle + %r67 = bitcast double %r66 to i64 + %r68 = and i64 %r67, 281474976710655 + %r69 = load i64, ptr @perry_class_keys_spike_ts__Point + %r70 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r71 = icmp eq i8 %r70, 0 + %r72 = lshr i64 %r64, 48 + %r73 = icmp eq i64 %r72, 32765 + %r74 = icmp ugt i64 %r65, 1048575 + %r75 = and i1 %r73, %r74 + %r76 = and i1 %r75, %r71 + br i1 %r76, label %class_field_inline.deref.9, label %class_field_inline.guardcall.10 + +class_field_inline.deref.4: + %r22 = inttoptr i64 %r10 to ptr + %r23 = getelementptr i8, ptr %r22, i64 -8 + %r24 = load i8, ptr %r23 + %r25 = icmp eq i8 %r24, 2 + %r26 = getelementptr i8, ptr %r22, i64 -7 + %r27 = load i8, ptr %r26 + %r28 = and i8 %r27, -128 + %r29 = icmp eq i8 %r28, 0 + %r30 = getelementptr i8, ptr %r22, i64 -6 + %r31 = load i16, ptr %r30 + %r32 = load i32, ptr %r22 + %r33 = icmp eq i32 %r32, 1 + %r34 = getelementptr i8, ptr %r22, i64 4 + %r35 = load i32, ptr %r34 + %r36 = icmp eq i32 %r35, 1 + %r37 = getelementptr i8, ptr %r22, i64 12 + %r38 = load i32, ptr %r37 + %r39 = icmp ugt i32 %r38, 0 + %r40 = getelementptr i8, ptr %r22, i64 16 + %r41 = load i64, ptr %r40 + %r42 = icmp eq i64 %r41, %r14 + %r43 = and i1 %r25, %r29 + %r44 = and i1 %r43, %r33 + %r45 = and i1 %r44, %r36 + %r46 = and i1 %r45, %r39 + %r47 = and i1 %r46, %r42 + %r48 = and i16 %r31, 2048 + %r49 = icmp eq i16 %r48, 0 + %r50 = and i1 %r47, %r49 + %r51 = and i16 %r31, 4096 + %r52 = icmp ne i16 %r51, 0 + %r53 = and i1 %r50, %r52 + br i1 %r53, label %class_field_get_number.fast.1, label %class_field_inline.guardcall.5 + +class_field_inline.guardcall.5: + %r54 = call i32 @js_typed_feedback_class_field_get_guard(i64 7695367220062322688, double %r8, i32 1, i64 %r14, i64 %r13, i32 0, i32 1) + %r55 = icmp ne i32 %r54, 0 + br i1 %r55, label %class_field_get_number.fast.1, label %class_field_get_number.fallback.2 + +class_field_get_number.fast.6: + %r111 = inttoptr i64 %r65 to ptr + %r112 = getelementptr i8, ptr %r111, i64 32 + %r113 = getelementptr double, ptr %r112, i64 0 + %r114 = load double, ptr %r113 + br label %class_field_get_number.merge.8 + +class_field_get_number.fallback.7: + call void @js_typed_feedback_record_fallback_call(i64 7695367220062322689) + %r115 = call double @js_object_get_field_by_name_f64(i64 %r64, i64 %r68) + %r116 = call double @js_number_coerce(double %r115) + br label %class_field_get_number.merge.8 + +class_field_get_number.merge.8: + %r117 = phi double [ %r114, %class_field_get_number.fast.6 ], [ %r116, %class_field_get_number.fallback.7 ] + %r118 = fmul double %r62, %r117 + %r119 = load double, ptr %r7 + %r120 = bitcast double %r119 to i64 + %r121 = and i64 %r120, 281474976710655 + %r122 = load double, ptr @spike_ts_.str.4.handle + %r123 = bitcast double %r122 to i64 + %r124 = and i64 %r123, 281474976710655 + %r125 = load i64, ptr @perry_class_keys_spike_ts__Point + %r126 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r127 = icmp eq i8 %r126, 0 + %r128 = lshr i64 %r120, 48 + %r129 = icmp eq i64 %r128, 32765 + %r130 = icmp ugt i64 %r121, 1048575 + %r131 = and i1 %r129, %r130 + %r132 = and i1 %r131, %r127 + br i1 %r132, label %class_field_inline.deref.14, label %class_field_inline.guardcall.15 + +class_field_inline.deref.9: + %r77 = inttoptr i64 %r65 to ptr + %r78 = getelementptr i8, ptr %r77, i64 -8 + %r79 = load i8, ptr %r78 + %r80 = icmp eq i8 %r79, 2 + %r81 = getelementptr i8, ptr %r77, i64 -7 + %r82 = load i8, ptr %r81 + %r83 = and i8 %r82, -128 + %r84 = icmp eq i8 %r83, 0 + %r85 = getelementptr i8, ptr %r77, i64 -6 + %r86 = load i16, ptr %r85 + %r87 = load i32, ptr %r77 + %r88 = icmp eq i32 %r87, 1 + %r89 = getelementptr i8, ptr %r77, i64 4 + %r90 = load i32, ptr %r89 + %r91 = icmp eq i32 %r90, 1 + %r92 = getelementptr i8, ptr %r77, i64 12 + %r93 = load i32, ptr %r92 + %r94 = icmp ugt i32 %r93, 0 + %r95 = getelementptr i8, ptr %r77, i64 16 + %r96 = load i64, ptr %r95 + %r97 = icmp eq i64 %r96, %r69 + %r98 = and i1 %r80, %r84 + %r99 = and i1 %r98, %r88 + %r100 = and i1 %r99, %r91 + %r101 = and i1 %r100, %r94 + %r102 = and i1 %r101, %r97 + %r103 = and i16 %r86, 2048 + %r104 = icmp eq i16 %r103, 0 + %r105 = and i1 %r102, %r104 + %r106 = and i16 %r86, 4096 + %r107 = icmp ne i16 %r106, 0 + %r108 = and i1 %r105, %r107 + br i1 %r108, label %class_field_get_number.fast.6, label %class_field_inline.guardcall.10 + +class_field_inline.guardcall.10: + %r109 = call i32 @js_typed_feedback_class_field_get_guard(i64 7695367220062322689, double %r63, i32 1, i64 %r69, i64 %r68, i32 0, i32 1) + %r110 = icmp ne i32 %r109, 0 + br i1 %r110, label %class_field_get_number.fast.6, label %class_field_get_number.fallback.7 + +class_field_get_number.fast.11: + %r167 = inttoptr i64 %r121 to ptr + %r168 = getelementptr i8, ptr %r167, i64 32 + %r169 = getelementptr double, ptr %r168, i64 1 + %r170 = load double, ptr %r169 + br label %class_field_get_number.merge.13 + +class_field_get_number.fallback.12: + call void @js_typed_feedback_record_fallback_call(i64 7695367220062322690) + %r171 = call double @js_object_get_field_by_name_f64(i64 %r120, i64 %r124) + %r172 = call double @js_number_coerce(double %r171) + br label %class_field_get_number.merge.13 + +class_field_get_number.merge.13: + %r173 = phi double [ %r170, %class_field_get_number.fast.11 ], [ %r172, %class_field_get_number.fallback.12 ] + %r174 = load double, ptr %r7 + %r175 = bitcast double %r174 to i64 + %r176 = and i64 %r175, 281474976710655 + %r177 = load double, ptr @spike_ts_.str.4.handle + %r178 = bitcast double %r177 to i64 + %r179 = and i64 %r178, 281474976710655 + %r180 = load i64, ptr @perry_class_keys_spike_ts__Point + %r181 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r182 = icmp eq i8 %r181, 0 + %r183 = lshr i64 %r175, 48 + %r184 = icmp eq i64 %r183, 32765 + %r185 = icmp ugt i64 %r176, 1048575 + %r186 = and i1 %r184, %r185 + %r187 = and i1 %r186, %r182 + br i1 %r187, label %class_field_inline.deref.19, label %class_field_inline.guardcall.20 + +class_field_inline.deref.14: + %r133 = inttoptr i64 %r121 to ptr + %r134 = getelementptr i8, ptr %r133, i64 -8 + %r135 = load i8, ptr %r134 + %r136 = icmp eq i8 %r135, 2 + %r137 = getelementptr i8, ptr %r133, i64 -7 + %r138 = load i8, ptr %r137 + %r139 = and i8 %r138, -128 + %r140 = icmp eq i8 %r139, 0 + %r141 = getelementptr i8, ptr %r133, i64 -6 + %r142 = load i16, ptr %r141 + %r143 = load i32, ptr %r133 + %r144 = icmp eq i32 %r143, 1 + %r145 = getelementptr i8, ptr %r133, i64 4 + %r146 = load i32, ptr %r145 + %r147 = icmp eq i32 %r146, 1 + %r148 = getelementptr i8, ptr %r133, i64 12 + %r149 = load i32, ptr %r148 + %r150 = icmp ugt i32 %r149, 1 + %r151 = getelementptr i8, ptr %r133, i64 16 + %r152 = load i64, ptr %r151 + %r153 = icmp eq i64 %r152, %r125 + %r154 = and i1 %r136, %r140 + %r155 = and i1 %r154, %r144 + %r156 = and i1 %r155, %r147 + %r157 = and i1 %r156, %r150 + %r158 = and i1 %r157, %r153 + %r159 = and i16 %r142, 2048 + %r160 = icmp eq i16 %r159, 0 + %r161 = and i1 %r158, %r160 + %r162 = and i16 %r142, 4096 + %r163 = icmp ne i16 %r162, 0 + %r164 = and i1 %r161, %r163 + br i1 %r164, label %class_field_get_number.fast.11, label %class_field_inline.guardcall.15 + +class_field_inline.guardcall.15: + %r165 = call i32 @js_typed_feedback_class_field_get_guard(i64 7695367220062322690, double %r119, i32 1, i64 %r125, i64 %r124, i32 1, i32 1) + %r166 = icmp ne i32 %r165, 0 + br i1 %r166, label %class_field_get_number.fast.11, label %class_field_get_number.fallback.12 + +class_field_get_number.fast.16: + %r222 = inttoptr i64 %r176 to ptr + %r223 = getelementptr i8, ptr %r222, i64 32 + %r224 = getelementptr double, ptr %r223, i64 1 + %r225 = load double, ptr %r224 + br label %class_field_get_number.merge.18 + +class_field_get_number.fallback.17: + call void @js_typed_feedback_record_fallback_call(i64 7695367220062322691) + %r226 = call double @js_object_get_field_by_name_f64(i64 %r175, i64 %r179) + %r227 = call double @js_number_coerce(double %r226) + br label %class_field_get_number.merge.18 + +class_field_get_number.merge.18: + %r228 = phi double [ %r225, %class_field_get_number.fast.16 ], [ %r227, %class_field_get_number.fallback.17 ] + %r229 = fmul double %r173, %r228 + %r230 = fadd double %r118, %r229 + %r231 = call double @llvm.sqrt.f64(double %r230) + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r231 + +class_field_inline.deref.19: + %r188 = inttoptr i64 %r176 to ptr + %r189 = getelementptr i8, ptr %r188, i64 -8 + %r190 = load i8, ptr %r189 + %r191 = icmp eq i8 %r190, 2 + %r192 = getelementptr i8, ptr %r188, i64 -7 + %r193 = load i8, ptr %r192 + %r194 = and i8 %r193, -128 + %r195 = icmp eq i8 %r194, 0 + %r196 = getelementptr i8, ptr %r188, i64 -6 + %r197 = load i16, ptr %r196 + %r198 = load i32, ptr %r188 + %r199 = icmp eq i32 %r198, 1 + %r200 = getelementptr i8, ptr %r188, i64 4 + %r201 = load i32, ptr %r200 + %r202 = icmp eq i32 %r201, 1 + %r203 = getelementptr i8, ptr %r188, i64 12 + %r204 = load i32, ptr %r203 + %r205 = icmp ugt i32 %r204, 1 + %r206 = getelementptr i8, ptr %r188, i64 16 + %r207 = load i64, ptr %r206 + %r208 = icmp eq i64 %r207, %r180 + %r209 = and i1 %r191, %r195 + %r210 = and i1 %r209, %r199 + %r211 = and i1 %r210, %r202 + %r212 = and i1 %r211, %r205 + %r213 = and i1 %r212, %r208 + %r214 = and i16 %r197, 2048 + %r215 = icmp eq i16 %r214, 0 + %r216 = and i1 %r213, %r215 + %r217 = and i16 %r197, 4096 + %r218 = icmp ne i16 %r217, 0 + %r219 = and i1 %r216, %r218 + br i1 %r219, label %class_field_get_number.fast.16, label %class_field_inline.guardcall.20 + +class_field_inline.guardcall.20: + %r220 = call i32 @js_typed_feedback_class_field_get_guard(i64 7695367220062322691, double %r174, i32 1, i64 %r180, i64 %r179, i32 1, i32 1) + %r221 = icmp ne i32 %r220, 0 + br i1 %r221, label %class_field_get_number.fast.16, label %class_field_get_number.fallback.17 +} + +define internal double @perry_method_spike_ts__Point__norm__pshape(double %this_arg) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 1) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %this_arg, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = load double, ptr %r7 + %r9 = bitcast double %r8 to i64 + %r10 = and i64 %r9, 281474976710655 + %r11 = inttoptr i64 %r10 to ptr + %r12 = getelementptr i8, ptr %r11, i64 32 + %r13 = getelementptr double, ptr %r12, i64 0 + %r14 = load double, ptr %r13 + %r15 = bitcast double %r14 to i64 + %r16 = and i64 %r15, 9218868437227405312 + %r17 = icmp ne i64 %r16, 9218868437227405312 + br i1 %r17, label %ptr_shape_get_number.plain.1, label %ptr_shape_get_number.coerce.2 + +ptr_shape_get_number.plain.1: + br label %ptr_shape_get_number.merge.3 + +ptr_shape_get_number.coerce.2: + %r18 = call double @js_number_coerce(double %r14) + br label %ptr_shape_get_number.merge.3 + +ptr_shape_get_number.merge.3: + %r19 = phi double [ %r14, %ptr_shape_get_number.plain.1 ], [ %r18, %ptr_shape_get_number.coerce.2 ] + %r20 = load double, ptr %r7 + %r21 = bitcast double %r20 to i64 + %r22 = and i64 %r21, 281474976710655 + %r23 = inttoptr i64 %r22 to ptr + %r24 = getelementptr i8, ptr %r23, i64 32 + %r25 = getelementptr double, ptr %r24, i64 0 + %r26 = load double, ptr %r25 + %r27 = bitcast double %r26 to i64 + %r28 = and i64 %r27, 9218868437227405312 + %r29 = icmp ne i64 %r28, 9218868437227405312 + br i1 %r29, label %ptr_shape_get_number.plain.4, label %ptr_shape_get_number.coerce.5 + +ptr_shape_get_number.plain.4: + br label %ptr_shape_get_number.merge.6 + +ptr_shape_get_number.coerce.5: + %r30 = call double @js_number_coerce(double %r26) + br label %ptr_shape_get_number.merge.6 + +ptr_shape_get_number.merge.6: + %r31 = phi double [ %r26, %ptr_shape_get_number.plain.4 ], [ %r30, %ptr_shape_get_number.coerce.5 ] + %r32 = fmul double %r19, %r31 + %r33 = load double, ptr %r7 + %r34 = bitcast double %r33 to i64 + %r35 = and i64 %r34, 281474976710655 + %r36 = inttoptr i64 %r35 to ptr + %r37 = getelementptr i8, ptr %r36, i64 32 + %r38 = getelementptr double, ptr %r37, i64 1 + %r39 = load double, ptr %r38 + %r40 = bitcast double %r39 to i64 + %r41 = and i64 %r40, 9218868437227405312 + %r42 = icmp ne i64 %r41, 9218868437227405312 + br i1 %r42, label %ptr_shape_get_number.plain.7, label %ptr_shape_get_number.coerce.8 + +ptr_shape_get_number.plain.7: + br label %ptr_shape_get_number.merge.9 + +ptr_shape_get_number.coerce.8: + %r43 = call double @js_number_coerce(double %r39) + br label %ptr_shape_get_number.merge.9 + +ptr_shape_get_number.merge.9: + %r44 = phi double [ %r39, %ptr_shape_get_number.plain.7 ], [ %r43, %ptr_shape_get_number.coerce.8 ] + %r45 = load double, ptr %r7 + %r46 = bitcast double %r45 to i64 + %r47 = and i64 %r46, 281474976710655 + %r48 = inttoptr i64 %r47 to ptr + %r49 = getelementptr i8, ptr %r48, i64 32 + %r50 = getelementptr double, ptr %r49, i64 1 + %r51 = load double, ptr %r50 + %r52 = bitcast double %r51 to i64 + %r53 = and i64 %r52, 9218868437227405312 + %r54 = icmp ne i64 %r53, 9218868437227405312 + br i1 %r54, label %ptr_shape_get_number.plain.10, label %ptr_shape_get_number.coerce.11 + +ptr_shape_get_number.plain.10: + br label %ptr_shape_get_number.merge.12 + +ptr_shape_get_number.coerce.11: + %r55 = call double @js_number_coerce(double %r51) + br label %ptr_shape_get_number.merge.12 + +ptr_shape_get_number.merge.12: + %r56 = phi double [ %r51, %ptr_shape_get_number.plain.10 ], [ %r55, %ptr_shape_get_number.coerce.11 ] + %r57 = fmul double %r44, %r56 + %r58 = fadd double %r32, %r57 + %r59 = call double @llvm.sqrt.f64(double %r58) + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double %r59 +} + +define double @spike_ts__Point_constructor(double %this_arg, double %arg16, double %arg17) { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r3 = call ptr @js_shadow_frame_enter(i32 1) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r7 = alloca double + store double %this_arg, ptr %r7 + call void @js_shadow_slot_bind(i32 0, ptr %r7) + %r8 = alloca double + store double %arg16, ptr %r8 + %r9 = alloca double + store double %arg17, ptr %r9 + %r10 = load double, ptr %r7 + %r11 = bitcast double %r10 to i64 + %r12 = and i64 %r11, 281474976710655 + %r13 = load double, ptr @spike_ts_.str.3.handle + %r14 = bitcast double %r13 to i64 + %r15 = and i64 %r14, 281474976710655 + %r16 = load i64, ptr @perry_class_keys_spike_ts__Point + %r17 = bitcast double 0x7FFC000000000001 to i64 + %r18 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r19 = icmp eq i8 %r18, 0 + %r20 = lshr i64 %r11, 48 + %r21 = icmp eq i64 %r20, 32765 + %r22 = icmp ugt i64 %r12, 1048575 + %r23 = and i1 %r21, %r22 + %r24 = and i1 %r23, %r19 + br i1 %r24, label %class_field_inline.deref.4, label %class_field_inline.guardcall.5 + +class_field_set.fast.1: + %r65 = inttoptr i64 %r12 to ptr + %r66 = getelementptr i8, ptr %r65, i64 32 + %r67 = getelementptr double, ptr %r66, i64 0 + %r68 = call double @js_array_numeric_value_to_raw_f64(double 0x7FFC000000000001) + store double %r68, ptr %r67 + br label %class_field_set.merge.3 + +class_field_set.fallback.2: + call void @js_class_field_set_fallback(i64 7695367220062322692, i64 %r11, i64 %r15, double 0x7FFC000000000001) + br label %class_field_set.merge.3 + +class_field_set.merge.3: + %r69 = load double, ptr %r7 + %r70 = bitcast double %r69 to i64 + %r71 = and i64 %r70, 281474976710655 + %r72 = load double, ptr @spike_ts_.str.4.handle + %r73 = bitcast double %r72 to i64 + %r74 = and i64 %r73, 281474976710655 + %r75 = load i64, ptr @perry_class_keys_spike_ts__Point + %r76 = bitcast double 0x7FFC000000000001 to i64 + %r77 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r78 = icmp eq i8 %r77, 0 + %r79 = lshr i64 %r70, 48 + %r80 = icmp eq i64 %r79, 32765 + %r81 = icmp ugt i64 %r71, 1048575 + %r82 = and i1 %r80, %r81 + %r83 = and i1 %r82, %r78 + br i1 %r83, label %class_field_inline.deref.9, label %class_field_inline.guardcall.10 + +class_field_inline.deref.4: + %r25 = inttoptr i64 %r12 to ptr + %r26 = getelementptr i8, ptr %r25, i64 -8 + %r27 = load i8, ptr %r26 + %r28 = icmp eq i8 %r27, 2 + %r29 = getelementptr i8, ptr %r25, i64 -7 + %r30 = load i8, ptr %r29 + %r31 = and i8 %r30, -128 + %r32 = icmp eq i8 %r31, 0 + %r33 = getelementptr i8, ptr %r25, i64 -6 + %r34 = load i16, ptr %r33 + %r35 = load i32, ptr %r25 + %r36 = icmp eq i32 %r35, 1 + %r37 = getelementptr i8, ptr %r25, i64 4 + %r38 = load i32, ptr %r37 + %r39 = icmp eq i32 %r38, 1 + %r40 = getelementptr i8, ptr %r25, i64 12 + %r41 = load i32, ptr %r40 + %r42 = icmp ugt i32 %r41, 0 + %r43 = getelementptr i8, ptr %r25, i64 16 + %r44 = load i64, ptr %r43 + %r45 = icmp eq i64 %r44, %r16 + %r46 = and i1 %r28, %r32 + %r47 = and i1 %r46, %r36 + %r48 = and i1 %r47, %r39 + %r49 = and i1 %r48, %r42 + %r50 = and i1 %r49, %r45 + %r51 = and i16 %r34, 2048 + %r52 = icmp eq i16 %r51, 0 + %r53 = and i1 %r50, %r52 + %r54 = and i16 %r34, 4096 + %r55 = icmp ne i16 %r54, 0 + %r56 = and i1 %r53, %r55 + %r57 = and i16 %r34, 1 + %r58 = icmp eq i16 %r57, 0 + %r59 = and i1 %r56, %r58 + %r60 = and i64 %r17, 9218868437227405312 + %r61 = icmp ne i64 %r60, 9218868437227405312 + %r62 = and i1 %r59, %r61 + br i1 %r62, label %class_field_set.fast.1, label %class_field_inline.guardcall.5 + +class_field_inline.guardcall.5: + %r63 = call i32 @js_typed_feedback_class_field_set_guard(i64 7695367220062322692, double %r10, i32 1, i64 %r16, i64 %r15, i32 0, double 0x7FFC000000000001, i32 1) + %r64 = icmp ne i32 %r63, 0 + br i1 %r64, label %class_field_set.fast.1, label %class_field_set.fallback.2 + +class_field_set.fast.6: + %r124 = inttoptr i64 %r71 to ptr + %r125 = getelementptr i8, ptr %r124, i64 32 + %r126 = getelementptr double, ptr %r125, i64 1 + %r127 = call double @js_array_numeric_value_to_raw_f64(double 0x7FFC000000000001) + store double %r127, ptr %r126 + br label %class_field_set.merge.8 + +class_field_set.fallback.7: + call void @js_class_field_set_fallback(i64 7695367220062322693, i64 %r70, i64 %r74, double 0x7FFC000000000001) + br label %class_field_set.merge.8 + +class_field_set.merge.8: + %r128 = load double, ptr %r7 + %r129 = load double, ptr %r8 + %r130 = bitcast double %r128 to i64 + %r131 = and i64 %r130, 281474976710655 + %r132 = load double, ptr @spike_ts_.str.3.handle + %r133 = bitcast double %r132 to i64 + %r134 = and i64 %r133, 281474976710655 + %r135 = load i64, ptr @perry_class_keys_spike_ts__Point + %r136 = bitcast double %r129 to i64 + %r137 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r138 = icmp eq i8 %r137, 0 + %r139 = lshr i64 %r130, 48 + %r140 = icmp eq i64 %r139, 32765 + %r141 = icmp ugt i64 %r131, 1048575 + %r142 = and i1 %r140, %r141 + %r143 = and i1 %r142, %r138 + br i1 %r143, label %class_field_inline.deref.14, label %class_field_inline.guardcall.15 + +class_field_inline.deref.9: + %r84 = inttoptr i64 %r71 to ptr + %r85 = getelementptr i8, ptr %r84, i64 -8 + %r86 = load i8, ptr %r85 + %r87 = icmp eq i8 %r86, 2 + %r88 = getelementptr i8, ptr %r84, i64 -7 + %r89 = load i8, ptr %r88 + %r90 = and i8 %r89, -128 + %r91 = icmp eq i8 %r90, 0 + %r92 = getelementptr i8, ptr %r84, i64 -6 + %r93 = load i16, ptr %r92 + %r94 = load i32, ptr %r84 + %r95 = icmp eq i32 %r94, 1 + %r96 = getelementptr i8, ptr %r84, i64 4 + %r97 = load i32, ptr %r96 + %r98 = icmp eq i32 %r97, 1 + %r99 = getelementptr i8, ptr %r84, i64 12 + %r100 = load i32, ptr %r99 + %r101 = icmp ugt i32 %r100, 1 + %r102 = getelementptr i8, ptr %r84, i64 16 + %r103 = load i64, ptr %r102 + %r104 = icmp eq i64 %r103, %r75 + %r105 = and i1 %r87, %r91 + %r106 = and i1 %r105, %r95 + %r107 = and i1 %r106, %r98 + %r108 = and i1 %r107, %r101 + %r109 = and i1 %r108, %r104 + %r110 = and i16 %r93, 2048 + %r111 = icmp eq i16 %r110, 0 + %r112 = and i1 %r109, %r111 + %r113 = and i16 %r93, 4096 + %r114 = icmp ne i16 %r113, 0 + %r115 = and i1 %r112, %r114 + %r116 = and i16 %r93, 1 + %r117 = icmp eq i16 %r116, 0 + %r118 = and i1 %r115, %r117 + %r119 = and i64 %r76, 9218868437227405312 + %r120 = icmp ne i64 %r119, 9218868437227405312 + %r121 = and i1 %r118, %r120 + br i1 %r121, label %class_field_set.fast.6, label %class_field_inline.guardcall.10 + +class_field_inline.guardcall.10: + %r122 = call i32 @js_typed_feedback_class_field_set_guard(i64 7695367220062322693, double %r69, i32 1, i64 %r75, i64 %r74, i32 1, double 0x7FFC000000000001, i32 1) + %r123 = icmp ne i32 %r122, 0 + br i1 %r123, label %class_field_set.fast.6, label %class_field_set.fallback.7 + +class_field_set.fast.11: + %r184 = inttoptr i64 %r131 to ptr + %r185 = getelementptr i8, ptr %r184, i64 32 + %r186 = getelementptr double, ptr %r185, i64 0 + %r187 = call double @js_array_numeric_value_to_raw_f64(double %r129) + store double %r187, ptr %r186 + br label %class_field_set.merge.13 + +class_field_set.fallback.12: + call void @js_class_field_set_fallback(i64 7695367220062322694, i64 %r130, i64 %r134, double %r129) + br label %class_field_set.merge.13 + +class_field_set.merge.13: + %r188 = load double, ptr %r7 + %r189 = load double, ptr %r9 + %r190 = bitcast double %r188 to i64 + %r191 = and i64 %r190, 281474976710655 + %r192 = load double, ptr @spike_ts_.str.4.handle + %r193 = bitcast double %r192 to i64 + %r194 = and i64 %r193, 281474976710655 + %r195 = load i64, ptr @perry_class_keys_spike_ts__Point + %r196 = bitcast double %r189 to i64 + %r197 = load volatile i8, ptr @PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED + %r198 = icmp eq i8 %r197, 0 + %r199 = lshr i64 %r190, 48 + %r200 = icmp eq i64 %r199, 32765 + %r201 = icmp ugt i64 %r191, 1048575 + %r202 = and i1 %r200, %r201 + %r203 = and i1 %r202, %r198 + br i1 %r203, label %class_field_inline.deref.19, label %class_field_inline.guardcall.20 + +class_field_inline.deref.14: + %r144 = inttoptr i64 %r131 to ptr + %r145 = getelementptr i8, ptr %r144, i64 -8 + %r146 = load i8, ptr %r145 + %r147 = icmp eq i8 %r146, 2 + %r148 = getelementptr i8, ptr %r144, i64 -7 + %r149 = load i8, ptr %r148 + %r150 = and i8 %r149, -128 + %r151 = icmp eq i8 %r150, 0 + %r152 = getelementptr i8, ptr %r144, i64 -6 + %r153 = load i16, ptr %r152 + %r154 = load i32, ptr %r144 + %r155 = icmp eq i32 %r154, 1 + %r156 = getelementptr i8, ptr %r144, i64 4 + %r157 = load i32, ptr %r156 + %r158 = icmp eq i32 %r157, 1 + %r159 = getelementptr i8, ptr %r144, i64 12 + %r160 = load i32, ptr %r159 + %r161 = icmp ugt i32 %r160, 0 + %r162 = getelementptr i8, ptr %r144, i64 16 + %r163 = load i64, ptr %r162 + %r164 = icmp eq i64 %r163, %r135 + %r165 = and i1 %r147, %r151 + %r166 = and i1 %r165, %r155 + %r167 = and i1 %r166, %r158 + %r168 = and i1 %r167, %r161 + %r169 = and i1 %r168, %r164 + %r170 = and i16 %r153, 2048 + %r171 = icmp eq i16 %r170, 0 + %r172 = and i1 %r169, %r171 + %r173 = and i16 %r153, 4096 + %r174 = icmp ne i16 %r173, 0 + %r175 = and i1 %r172, %r174 + %r176 = and i16 %r153, 1 + %r177 = icmp eq i16 %r176, 0 + %r178 = and i1 %r175, %r177 + %r179 = and i64 %r136, 9218868437227405312 + %r180 = icmp ne i64 %r179, 9218868437227405312 + %r181 = and i1 %r178, %r180 + br i1 %r181, label %class_field_set.fast.11, label %class_field_inline.guardcall.15 + +class_field_inline.guardcall.15: + %r182 = call i32 @js_typed_feedback_class_field_set_guard(i64 7695367220062322694, double %r128, i32 1, i64 %r135, i64 %r134, i32 0, double %r129, i32 1) + %r183 = icmp ne i32 %r182, 0 + br i1 %r183, label %class_field_set.fast.11, label %class_field_set.fallback.12 + +class_field_set.fast.16: + %r244 = inttoptr i64 %r191 to ptr + %r245 = getelementptr i8, ptr %r244, i64 32 + %r246 = getelementptr double, ptr %r245, i64 1 + %r247 = call double @js_array_numeric_value_to_raw_f64(double %r189) + store double %r247, ptr %r246 + br label %class_field_set.merge.18 + +class_field_set.fallback.17: + call void @js_class_field_set_fallback(i64 7695367220062322695, i64 %r190, i64 %r194, double %r189) + br label %class_field_set.merge.18 + +class_field_set.merge.18: + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret double 0x7FFC000000000001 + +class_field_inline.deref.19: + %r204 = inttoptr i64 %r191 to ptr + %r205 = getelementptr i8, ptr %r204, i64 -8 + %r206 = load i8, ptr %r205 + %r207 = icmp eq i8 %r206, 2 + %r208 = getelementptr i8, ptr %r204, i64 -7 + %r209 = load i8, ptr %r208 + %r210 = and i8 %r209, -128 + %r211 = icmp eq i8 %r210, 0 + %r212 = getelementptr i8, ptr %r204, i64 -6 + %r213 = load i16, ptr %r212 + %r214 = load i32, ptr %r204 + %r215 = icmp eq i32 %r214, 1 + %r216 = getelementptr i8, ptr %r204, i64 4 + %r217 = load i32, ptr %r216 + %r218 = icmp eq i32 %r217, 1 + %r219 = getelementptr i8, ptr %r204, i64 12 + %r220 = load i32, ptr %r219 + %r221 = icmp ugt i32 %r220, 1 + %r222 = getelementptr i8, ptr %r204, i64 16 + %r223 = load i64, ptr %r222 + %r224 = icmp eq i64 %r223, %r195 + %r225 = and i1 %r207, %r211 + %r226 = and i1 %r225, %r215 + %r227 = and i1 %r226, %r218 + %r228 = and i1 %r227, %r221 + %r229 = and i1 %r228, %r224 + %r230 = and i16 %r213, 2048 + %r231 = icmp eq i16 %r230, 0 + %r232 = and i1 %r229, %r231 + %r233 = and i16 %r213, 4096 + %r234 = icmp ne i16 %r233, 0 + %r235 = and i1 %r232, %r234 + %r236 = and i16 %r213, 1 + %r237 = icmp eq i16 %r236, 0 + %r238 = and i1 %r235, %r237 + %r239 = and i64 %r196, 9218868437227405312 + %r240 = icmp ne i64 %r239, 9218868437227405312 + %r241 = and i1 %r238, %r240 + br i1 %r241, label %class_field_set.fast.16, label %class_field_inline.guardcall.20 + +class_field_inline.guardcall.20: + %r242 = call i32 @js_typed_feedback_class_field_set_guard(i64 7695367220062322695, double %r188, i32 1, i64 %r195, i64 %r194, i32 1, double %r189, i32 1) + %r243 = icmp ne i32 %r242, 0 + br i1 %r243, label %class_field_set.fast.16, label %class_field_set.fallback.17 +} + +define double @__perry_wrap_perry_fn_spike_ts__fib(i64 %this_closure, double %a0) { +entry.0: + %r1 = call double @perry_fn_spike_ts__fib(double %a0) + ret double %r1 +} + +define double @__perry_wrap_perry_method_spike_ts__Point__norm(i64 %this_closure) { +entry.0: + %r1 = call double @js_implicit_this_get() + %r2 = call double @perry_method_spike_ts__Point__norm(double %r1) + ret double %r2 +} + +define internal double @__perry_wrap_perry_unknown_func(i64 %this_closure, double %a0, double %a1, double %a2, double %a3, double %a4) { +entry.0: + ret double 0x7FFC000000000001 +} + +define void @spike_ts__init() { +entry.0: + ret void +} + +define i32 @main() { +entry.0: + %r1 = alloca i64 + %r2 = alloca ptr + store ptr null, ptr %r2 + %r7 = alloca double + store double 0x7FFC000000000001, ptr %r7 + %r8 = alloca ptr + %r9 = call ptr @js_inline_arena_state() + store ptr %r9, ptr %r8 + %r97 = alloca double + store double 0x7FFC000000000001, ptr %r97 + %r138 = alloca double + store double 0x7FFC000000000001, ptr %r138 + %r176 = alloca double + store double 0x7FFC000000000001, ptr %r176 + %r177 = alloca double + store double 0x7FFC000000000001, ptr %r177 + %r178 = alloca double + store double 0x7FFC000000000001, ptr %r178 + %r179 = alloca double + store double 0x7FFC000000000001, ptr %r179 + %r263 = alloca double + store double 0x7FFC000000000001, ptr %r263 + %r291 = alloca double + store double 0x7FFC000000000001, ptr %r291 + %r371 = alloca i64 + %r383 = alloca i64 + %r394 = alloca double + store double 0x7FFC000000000001, ptr %r394 + %r461 = alloca [5 x i64] + call void @js_gc_init() + call void @js_gc_write_barriers_emitted(i32 1) + call void @perry_macos_bundle_chdir() + call void @__perry_init_strings_spike_ts() + %r3 = call ptr @js_shadow_frame_enter(i32 6) + store ptr %r3, ptr %r2 + %r4 = getelementptr inbounds i8, ptr %r3, i64 24 + %r5 = load i64, ptr %r4 + %r6 = sub i64 %r5, 1 + store i64 %r6, ptr %r1 + %r372 = load i64, ptr @perry_class_keys_spike_ts__Point + store i64 %r372, ptr %r371 + %r384 = load i64, ptr @perry_class_keys_spike_ts__Point + store i64 %r384, ptr %r383 + %r10 = load ptr, ptr %r8 + %r11 = getelementptr i8, ptr %r10, i64 8 + %r12 = load i64, ptr %r11 + %r13 = add i64 %r12, 80 + %r14 = getelementptr i8, ptr %r10, i64 16 + %r15 = load i64, ptr %r14 + %r16 = icmp ule i64 %r13, %r15 + br i1 %r16, label %arrlit.fast.1, label %arrlit.slow.2 + +arrlit.fast.1: + store i64 %r13, ptr %r11 + %r17 = load ptr, ptr %r10 + %r18 = getelementptr i8, ptr %r17, i64 %r12 + br label %arrlit.merge.3 + +arrlit.slow.2: + %r19 = call ptr @js_inline_arena_slow_alloc(ptr %r10, i64 80, i64 8) + br label %arrlit.merge.3 + +arrlit.merge.3: + %r20 = phi ptr [ %r18, %arrlit.fast.1 ], [ %r19, %arrlit.slow.2 ] + store i64 344671126017, ptr %r20 + %r21 = getelementptr i8, ptr %r20, i64 8 + store i64 34359738376, ptr %r21 + %r22 = getelementptr i8, ptr %r20, i64 8 + %r23 = ptrtoint ptr %r22 to i64 + %r24 = getelementptr inbounds i8, ptr %r20, i64 16 + store double 3.0, ptr %r24 + %r25 = getelementptr inbounds i8, ptr %r20, i64 24 + store double 1.0, ptr %r25 + %r26 = getelementptr inbounds i8, ptr %r20, i64 32 + store double 4.0, ptr %r26 + %r27 = getelementptr inbounds i8, ptr %r20, i64 40 + store double 1.0, ptr %r27 + %r28 = getelementptr inbounds i8, ptr %r20, i64 48 + store double 5.0, ptr %r28 + %r29 = getelementptr inbounds i8, ptr %r20, i64 56 + store double 9.0, ptr %r29 + %r30 = getelementptr inbounds i8, ptr %r20, i64 64 + store double 2.0, ptr %r30 + %r31 = getelementptr inbounds i8, ptr %r20, i64 72 + store double 6.0, ptr %r31 + %r32 = call i32 @js_array_mark_numeric_f64_layout(i64 %r23) + %r33 = or i64 %r23, 9222527611924643840 + %r34 = bitcast i64 %r33 to double + store double %r34, ptr %r7 + %r35 = load ptr, ptr %r2 + %r36 = icmp eq ptr %r35, null + br i1 %r36, label %ss.slow.4, label %ss.chk_top.5 + +ss.slow.4: + call void @js_shadow_slot_bind(i32 0, ptr %r7) + br label %ss.done.8 + +ss.chk_top.5: + %r37 = getelementptr inbounds i8, ptr %r35, i64 24 + %r38 = load i64, ptr %r37 + %r39 = icmp eq i64 %r38, -1 + br i1 %r39, label %ss.done.8, label %ss.chk_len.6 + +ss.chk_len.6: + %r40 = add i64 %r38, 0 + %r41 = getelementptr inbounds i8, ptr %r35, i64 8 + %r42 = load i64, ptr %r41 + %r43 = icmp ult i64 %r40, %r42 + br i1 %r43, label %ss.store.7, label %ss.done.8 + +ss.store.7: + %r44 = load ptr, ptr %r35 + %r45 = shl i64 %r40, 4 + %r46 = getelementptr inbounds i8, ptr %r44, i64 %r45 + %r47 = getelementptr inbounds i8, ptr %r46, i64 8 + %r48 = load i64, ptr %r7 + %r49 = ptrtoint ptr %r7 to i64 + %r50 = and i64 %r49, 1 + %r51 = icmp eq i64 %r50, 0 + %r52 = select i1 %r51, i64 %r49, i64 0 + %r53 = or i64 %r52, 1 + store i64 %r48, ptr %r46 + store i64 %r53, ptr %r47 + %r54 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r55 = icmp ne i32 %r54, 0 + br i1 %r55, label %ss.barrier.9, label %ss.done.8 + +ss.done.8: + %r56 = load double, ptr %r7 + %r57 = call i64 @js_closure_alloc_singleton(ptr @perry_closure_spike_ts__1) + %r58 = or i64 %r57, 9222527611924643840 + %r59 = bitcast i64 %r58 to double + %r60 = bitcast double %r56 to i64 + %r61 = and i64 %r60, 281474976710655 + %r62 = call i64 @js_validate_array_comparator(double %r59) + %r63 = call i64 @js_array_sort_with_comparator(i64 %r61, i64 %r62) + %r64 = or i64 %r63, 9222527611924643840 + %r65 = bitcast i64 %r64 to double + %r66 = call i64 @js_array_alloc(i32 2) + %r67 = call i32 @js_gc_temp_root_push(i64 %r66) + %r68 = load double, ptr @spike_ts_.str.5.handle + call void @js_array_push_f64_temp_rooted(i32 %r67, double %r68) + %r69 = call double @perry_fn_spike_ts__fib(double 20.0) + call void @js_array_push_f64_temp_rooted(i32 %r67, double %r69) + %r70 = call i64 @js_gc_temp_root_get(i32 %r67) + call void @js_console_log_spread(i64 %r70) + call void @js_gc_temp_root_truncate(i32 %r67) + %r71 = call i64 @js_array_alloc(i32 2) + %r72 = call i32 @js_gc_temp_root_push(i64 %r71) + %r73 = load double, ptr @spike_ts_.str.6.handle + call void @js_array_push_f64_temp_rooted(i32 %r72, double %r73) + %r74 = load double, ptr %r7 + %r75 = load double, ptr @spike_ts_.str.7.handle + %r76 = bitcast double %r74 to i64 + %r77 = and i64 %r76, 281474976710655 + %r78 = call i64 @js_array_join_value(i64 %r77, double %r75) + %r79 = or i64 %r78, 9223090561878065152 + %r80 = bitcast i64 %r79 to double + call void @js_array_push_f64_temp_rooted(i32 %r72, double %r80) + %r81 = call i64 @js_gc_temp_root_get(i32 %r72) + call void @js_console_log_spread(i64 %r81) + call void @js_gc_temp_root_truncate(i32 %r72) + %r82 = load ptr, ptr %r2 + %r83 = icmp eq ptr %r82, null + br i1 %r83, label %ss.slow.10, label %ss.chk_top.11 + +ss.barrier.9: + call void @js_write_barrier_root_nanbox(i64 %r48) + br label %ss.done.8 + +ss.slow.10: + call void @js_shadow_slot_set(i32 0, i64 0) + br label %ss.done.14 + +ss.chk_top.11: + %r84 = getelementptr inbounds i8, ptr %r82, i64 24 + %r85 = load i64, ptr %r84 + %r86 = icmp eq i64 %r85, -1 + br i1 %r86, label %ss.done.14, label %ss.chk_len.12 + +ss.chk_len.12: + %r87 = add i64 %r85, 0 + %r88 = getelementptr inbounds i8, ptr %r82, i64 8 + %r89 = load i64, ptr %r88 + %r90 = icmp ult i64 %r87, %r89 + br i1 %r90, label %ss.store.13, label %ss.done.14 + +ss.store.13: + %r91 = load ptr, ptr %r82 + %r92 = shl i64 %r87, 4 + %r93 = getelementptr inbounds i8, ptr %r91, i64 %r92 + %r94 = getelementptr inbounds i8, ptr %r93, i64 8 + %r95 = load i64, ptr %r94 + %r96 = and i64 %r95, -2 + store i64 0, ptr %r93 + store i64 %r96, ptr %r94 + br label %ss.done.14 + +ss.done.14: + %r98 = call i64 @js_map_alloc(i32 8) + %r99 = or i64 %r98, 9222527611924643840 + %r100 = bitcast i64 %r99 to double + store double %r100, ptr %r97 + %r101 = load ptr, ptr %r2 + %r102 = icmp eq ptr %r101, null + br i1 %r102, label %ss.slow.15, label %ss.chk_top.16 + +ss.slow.15: + call void @js_shadow_slot_bind(i32 1, ptr %r97) + br label %ss.done.19 + +ss.chk_top.16: + %r103 = getelementptr inbounds i8, ptr %r101, i64 24 + %r104 = load i64, ptr %r103 + %r105 = icmp eq i64 %r104, -1 + br i1 %r105, label %ss.done.19, label %ss.chk_len.17 + +ss.chk_len.17: + %r106 = add i64 %r104, 1 + %r107 = getelementptr inbounds i8, ptr %r101, i64 8 + %r108 = load i64, ptr %r107 + %r109 = icmp ult i64 %r106, %r108 + br i1 %r109, label %ss.store.18, label %ss.done.19 + +ss.store.18: + %r110 = load ptr, ptr %r101 + %r111 = shl i64 %r106, 4 + %r112 = getelementptr inbounds i8, ptr %r110, i64 %r111 + %r113 = getelementptr inbounds i8, ptr %r112, i64 8 + %r114 = load i64, ptr %r97 + %r115 = ptrtoint ptr %r97 to i64 + %r116 = and i64 %r115, 1 + %r117 = icmp eq i64 %r116, 0 + %r118 = select i1 %r117, i64 %r115, i64 0 + %r119 = or i64 %r118, 1 + store i64 %r114, ptr %r112 + store i64 %r119, ptr %r113 + %r120 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r121 = icmp ne i32 %r120, 0 + br i1 %r121, label %ss.barrier.20, label %ss.done.19 + +ss.done.19: + %r122 = load double, ptr %r97 + %r123 = load double, ptr @spike_ts_.str.8.handle + %r124 = bitcast double %r122 to i64 + %r125 = and i64 %r124, 281474976710655 + %r126 = call i64 @js_get_string_pointer_unified(double %r123) + %r127 = call i64 @js_map_set_string_number(i64 %r125, i64 %r126, double 1.0) + %r128 = or i64 %r127, 9222527611924643840 + %r129 = bitcast i64 %r128 to double + %r130 = load double, ptr %r97 + %r131 = load double, ptr @spike_ts_.str.9.handle + %r132 = bitcast double %r130 to i64 + %r133 = and i64 %r132, 281474976710655 + %r134 = call i64 @js_get_string_pointer_unified(double %r131) + %r135 = call i64 @js_map_set_string_number(i64 %r133, i64 %r134, double 2.0) + %r136 = or i64 %r135, 9222527611924643840 + %r137 = bitcast i64 %r136 to double + %r139 = load double, ptr %r97 + store double %r139, ptr %r138 + %r140 = load ptr, ptr %r2 + %r141 = icmp eq ptr %r140, null + br i1 %r141, label %ss.slow.21, label %ss.chk_top.22 + +ss.barrier.20: + call void @js_write_barrier_root_nanbox(i64 %r114) + br label %ss.done.19 + +ss.slow.21: + call void @js_shadow_slot_bind(i32 2, ptr %r138) + br label %ss.done.25 + +ss.chk_top.22: + %r142 = getelementptr inbounds i8, ptr %r140, i64 24 + %r143 = load i64, ptr %r142 + %r144 = icmp eq i64 %r143, -1 + br i1 %r144, label %ss.done.25, label %ss.chk_len.23 + +ss.chk_len.23: + %r145 = add i64 %r143, 2 + %r146 = getelementptr inbounds i8, ptr %r140, i64 8 + %r147 = load i64, ptr %r146 + %r148 = icmp ult i64 %r145, %r147 + br i1 %r148, label %ss.store.24, label %ss.done.25 + +ss.store.24: + %r149 = load ptr, ptr %r140 + %r150 = shl i64 %r145, 4 + %r151 = getelementptr inbounds i8, ptr %r149, i64 %r150 + %r152 = getelementptr inbounds i8, ptr %r151, i64 8 + %r153 = load i64, ptr %r138 + %r154 = ptrtoint ptr %r138 to i64 + %r155 = and i64 %r154, 1 + %r156 = icmp eq i64 %r155, 0 + %r157 = select i1 %r156, i64 %r154, i64 0 + %r158 = or i64 %r157, 1 + store i64 %r153, ptr %r151 + store i64 %r158, ptr %r152 + %r159 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r160 = icmp ne i32 %r159, 0 + br i1 %r160, label %ss.barrier.26, label %ss.done.25 + +ss.done.25: + %r161 = load ptr, ptr %r2 + %r162 = icmp eq ptr %r161, null + br i1 %r162, label %ss.slow.27, label %ss.chk_top.28 + +ss.barrier.26: + call void @js_write_barrier_root_nanbox(i64 %r153) + br label %ss.done.25 + +ss.slow.27: + call void @js_shadow_slot_set(i32 1, i64 0) + br label %ss.done.31 + +ss.chk_top.28: + %r163 = getelementptr inbounds i8, ptr %r161, i64 24 + %r164 = load i64, ptr %r163 + %r165 = icmp eq i64 %r164, -1 + br i1 %r165, label %ss.done.31, label %ss.chk_len.29 + +ss.chk_len.29: + %r166 = add i64 %r164, 1 + %r167 = getelementptr inbounds i8, ptr %r161, i64 8 + %r168 = load i64, ptr %r167 + %r169 = icmp ult i64 %r166, %r168 + br i1 %r169, label %ss.store.30, label %ss.done.31 + +ss.store.30: + %r170 = load ptr, ptr %r161 + %r171 = shl i64 %r166, 4 + %r172 = getelementptr inbounds i8, ptr %r170, i64 %r171 + %r173 = getelementptr inbounds i8, ptr %r172, i64 8 + %r174 = load i64, ptr %r173 + %r175 = and i64 %r174, -2 + store i64 0, ptr %r172 + store i64 %r175, ptr %r173 + br label %ss.done.31 + +ss.done.31: + store double 0x7FFC000000000001, ptr %r176 + store double 0.0, ptr %r177 + store double 0.0, ptr %r178 + store double 0.0, ptr %r179 + br label %for.cond.32 + +for.cond.32: + %r180 = load double, ptr %r138 + %r181 = bitcast double %r180 to i64 + %r182 = and i64 %r181, 281474976710655 + %r183 = call i32 @js_map_size(i64 %r182) + %r184 = sitofp i32 %r183 to double + store double %r184, ptr %r177 + %r185 = load double, ptr %r179 + %r186 = fcmp oeq double %r185, 0.0 + %r187 = select i1 %r186, i64 9222246136947933188, i64 9222246136947933187 + %r188 = bitcast i64 %r187 to double + %r189 = icmp eq i64 %r187, 9222246136947933188 + br i1 %r189, label %ternary.then.36, label %ternary.else.37 + +for.body.33: + %r236 = load double, ptr %r138 + %r237 = load double, ptr %r179 + %r238 = bitcast double %r236 to i64 + %r239 = and i64 %r238, 281474976710655 + %r240 = fptosi double %r237 to i32 + %r241 = call double @js_map_entry_key_at(i64 %r239, i32 %r240) + store double %r241, ptr %r176 + %r242 = load ptr, ptr %r2 + %r243 = icmp eq ptr %r242, null + br i1 %r243, label %ss.slow.48, label %ss.chk_top.49 + +for.update.34: + %r319 = load double, ptr %r179 + %r320 = call double @js_to_numeric(double %r319) + %r321 = call double @js_numeric_step(double %r320, i32 1) + store double %r321, ptr %r179 + br label %for.cond.32 + +for.exit.35: + %r322 = load ptr, ptr %r2 + %r323 = icmp eq ptr %r322, null + br i1 %r323, label %ss.slow.65, label %ss.chk_top.66 + +ternary.then.36: + %r190 = load double, ptr %r179 + br label %ternary.merge.38 + +ternary.else.37: + %r191 = load double, ptr %r138 + %r192 = load double, ptr %r179 + %r193 = fsub double %r192, 1.0 + %r194 = bitcast double %r191 to i64 + %r195 = and i64 %r194, 281474976710655 + %r196 = fptosi double %r193 to i32 + %r197 = call double @js_map_entry_key_at(i64 %r195, i32 %r196) + %r198 = load double, ptr %r176 + %r199 = bitcast double %r197 to i64 + %r200 = bitcast double %r198 to i64 + %r201 = call i64 @js_eq(i64 %r199, i64 %r200) + %r202 = bitcast i64 %r201 to double + %r203 = icmp eq i64 %r201, 9222246136947933188 + br i1 %r203, label %ternary.then.39, label %ternary.else.40 + +ternary.merge.38: + %r228 = phi double [ %r190, %ternary.then.36 ], [ %r227, %ternary.merge.41 ] + store double %r228, ptr %r179 + %r229 = load double, ptr %r179 + %r230 = load double, ptr %r177 + %r231 = fcmp olt double %r229, %r230 + %r232 = select i1 %r231, i64 9222246136947933188, i64 9222246136947933187 + %r233 = bitcast i64 %r232 to double + %r234 = call i32 @js_is_truthy(double %r233) + %r235 = icmp ne i32 %r234, 0 + br i1 %r235, label %for.body.33, label %for.exit.35 + +ternary.then.39: + %r204 = load double, ptr %r179 + br label %ternary.merge.41 + +ternary.else.40: + %r205 = load double, ptr %r138 + %r206 = load double, ptr %r176 + %r207 = call double @js_map_find_key_index(double %r205, double %r206) + store double %r207, ptr %r178 + %r208 = load double, ptr %r178 + %r209 = fcmp oge double %r208, 0.0 + %r210 = select i1 %r209, i64 9222246136947933188, i64 9222246136947933187 + %r211 = bitcast i64 %r210 to double + %r212 = icmp eq i64 %r210, 9222246136947933188 + br i1 %r212, label %ternary.then.42, label %ternary.else.43 + +ternary.merge.41: + %r227 = phi double [ %r204, %ternary.then.39 ], [ %r226, %ternary.merge.44 ] + br label %ternary.merge.38 + +ternary.then.42: + %r213 = load double, ptr %r178 + %r214 = load double, ptr %r179 + %r215 = fcmp olt double %r213, %r214 + %r216 = select i1 %r215, i64 9222246136947933188, i64 9222246136947933187 + %r217 = bitcast i64 %r216 to double + %r218 = icmp eq i64 %r216, 9222246136947933188 + br i1 %r218, label %ternary.then.45, label %ternary.else.46 + +ternary.else.43: + %r224 = load double, ptr %r179 + %r225 = fsub double %r224, 1.0 + br label %ternary.merge.44 + +ternary.merge.44: + %r226 = phi double [ %r223, %ternary.merge.47 ], [ %r225, %ternary.else.43 ] + br label %ternary.merge.41 + +ternary.then.45: + %r219 = load double, ptr %r178 + %r220 = fadd double %r219, 1.0 + br label %ternary.merge.47 + +ternary.else.46: + %r221 = load double, ptr %r179 + %r222 = fsub double %r221, 1.0 + br label %ternary.merge.47 + +ternary.merge.47: + %r223 = phi double [ %r220, %ternary.then.45 ], [ %r222, %ternary.else.46 ] + br label %ternary.merge.44 + +ss.slow.48: + call void @js_shadow_slot_bind(i32 3, ptr %r176) + br label %ss.done.52 + +ss.chk_top.49: + %r244 = getelementptr inbounds i8, ptr %r242, i64 24 + %r245 = load i64, ptr %r244 + %r246 = icmp eq i64 %r245, -1 + br i1 %r246, label %ss.done.52, label %ss.chk_len.50 + +ss.chk_len.50: + %r247 = add i64 %r245, 3 + %r248 = getelementptr inbounds i8, ptr %r242, i64 8 + %r249 = load i64, ptr %r248 + %r250 = icmp ult i64 %r247, %r249 + br i1 %r250, label %ss.store.51, label %ss.done.52 + +ss.store.51: + %r251 = load ptr, ptr %r242 + %r252 = shl i64 %r247, 4 + %r253 = getelementptr inbounds i8, ptr %r251, i64 %r252 + %r254 = getelementptr inbounds i8, ptr %r253, i64 8 + %r255 = load i64, ptr %r176 + %r256 = ptrtoint ptr %r176 to i64 + %r257 = and i64 %r256, 1 + %r258 = icmp eq i64 %r257, 0 + %r259 = select i1 %r258, i64 %r256, i64 0 + %r260 = or i64 %r259, 1 + store i64 %r255, ptr %r253 + store i64 %r260, ptr %r254 + %r261 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r262 = icmp ne i32 %r261, 0 + br i1 %r262, label %ss.barrier.53, label %ss.done.52 + +ss.done.52: + %r264 = load double, ptr %r138 + %r265 = load double, ptr %r179 + %r266 = bitcast double %r264 to i64 + %r267 = and i64 %r266, 281474976710655 + %r268 = fptosi double %r265 to i32 + %r269 = call double @js_map_entry_key_at(i64 %r267, i32 %r268) + store double %r269, ptr %r263 + %r270 = load ptr, ptr %r2 + %r271 = icmp eq ptr %r270, null + br i1 %r271, label %ss.slow.54, label %ss.chk_top.55 + +ss.barrier.53: + call void @js_write_barrier_root_nanbox(i64 %r255) + br label %ss.done.52 + +ss.slow.54: + call void @js_shadow_slot_bind(i32 4, ptr %r263) + br label %ss.done.58 + +ss.chk_top.55: + %r272 = getelementptr inbounds i8, ptr %r270, i64 24 + %r273 = load i64, ptr %r272 + %r274 = icmp eq i64 %r273, -1 + br i1 %r274, label %ss.done.58, label %ss.chk_len.56 + +ss.chk_len.56: + %r275 = add i64 %r273, 4 + %r276 = getelementptr inbounds i8, ptr %r270, i64 8 + %r277 = load i64, ptr %r276 + %r278 = icmp ult i64 %r275, %r277 + br i1 %r278, label %ss.store.57, label %ss.done.58 + +ss.store.57: + %r279 = load ptr, ptr %r270 + %r280 = shl i64 %r275, 4 + %r281 = getelementptr inbounds i8, ptr %r279, i64 %r280 + %r282 = getelementptr inbounds i8, ptr %r281, i64 8 + %r283 = load i64, ptr %r263 + %r284 = ptrtoint ptr %r263 to i64 + %r285 = and i64 %r284, 1 + %r286 = icmp eq i64 %r285, 0 + %r287 = select i1 %r286, i64 %r284, i64 0 + %r288 = or i64 %r287, 1 + store i64 %r283, ptr %r281 + store i64 %r288, ptr %r282 + %r289 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r290 = icmp ne i32 %r289, 0 + br i1 %r290, label %ss.barrier.59, label %ss.done.58 + +ss.done.58: + %r292 = load double, ptr %r138 + %r293 = load double, ptr %r179 + %r294 = bitcast double %r292 to i64 + %r295 = and i64 %r294, 281474976710655 + %r296 = fptosi double %r293 to i32 + %r297 = call double @js_map_entry_value_at(i64 %r295, i32 %r296) + store double %r297, ptr %r291 + %r298 = call i64 @js_array_alloc(i32 3) + %r299 = call i32 @js_gc_temp_root_push(i64 %r298) + %r300 = load double, ptr %r263 + call void @js_array_push_f64_temp_rooted(i32 %r299, double %r300) + %r301 = load double, ptr @spike_ts_.str.10.handle + call void @js_array_push_f64_temp_rooted(i32 %r299, double %r301) + %r302 = load double, ptr %r291 + call void @js_array_push_f64_temp_rooted(i32 %r299, double %r302) + %r303 = call i64 @js_gc_temp_root_get(i32 %r299) + call void @js_console_log_spread(i64 %r303) + call void @js_gc_temp_root_truncate(i32 %r299) + %r304 = load ptr, ptr %r2 + %r305 = icmp eq ptr %r304, null + br i1 %r305, label %ss.slow.60, label %ss.chk_top.61 + +ss.barrier.59: + call void @js_write_barrier_root_nanbox(i64 %r283) + br label %ss.done.58 + +ss.slow.60: + call void @js_shadow_slot_set(i32 4, i64 0) + br label %ss.done.64 + +ss.chk_top.61: + %r306 = getelementptr inbounds i8, ptr %r304, i64 24 + %r307 = load i64, ptr %r306 + %r308 = icmp eq i64 %r307, -1 + br i1 %r308, label %ss.done.64, label %ss.chk_len.62 + +ss.chk_len.62: + %r309 = add i64 %r307, 4 + %r310 = getelementptr inbounds i8, ptr %r304, i64 8 + %r311 = load i64, ptr %r310 + %r312 = icmp ult i64 %r309, %r311 + br i1 %r312, label %ss.store.63, label %ss.done.64 + +ss.store.63: + %r313 = load ptr, ptr %r304 + %r314 = shl i64 %r309, 4 + %r315 = getelementptr inbounds i8, ptr %r313, i64 %r314 + %r316 = getelementptr inbounds i8, ptr %r315, i64 8 + %r317 = load i64, ptr %r316 + %r318 = and i64 %r317, -2 + store i64 0, ptr %r315 + store i64 %r318, ptr %r316 + br label %ss.done.64 + +ss.done.64: + br label %for.update.34 + +ss.slow.65: + call void @js_shadow_slot_set(i32 2, i64 0) + br label %ss.done.69 + +ss.chk_top.66: + %r324 = getelementptr inbounds i8, ptr %r322, i64 24 + %r325 = load i64, ptr %r324 + %r326 = icmp eq i64 %r325, -1 + br i1 %r326, label %ss.done.69, label %ss.chk_len.67 + +ss.chk_len.67: + %r327 = add i64 %r325, 2 + %r328 = getelementptr inbounds i8, ptr %r322, i64 8 + %r329 = load i64, ptr %r328 + %r330 = icmp ult i64 %r327, %r329 + br i1 %r330, label %ss.store.68, label %ss.done.69 + +ss.store.68: + %r331 = load ptr, ptr %r322 + %r332 = shl i64 %r327, 4 + %r333 = getelementptr inbounds i8, ptr %r331, i64 %r332 + %r334 = getelementptr inbounds i8, ptr %r333, i64 8 + %r335 = load i64, ptr %r334 + %r336 = and i64 %r335, -2 + store i64 0, ptr %r333 + store i64 %r336, ptr %r334 + br label %ss.done.69 + +ss.done.69: + %r337 = load ptr, ptr %r2 + %r338 = icmp eq ptr %r337, null + br i1 %r338, label %ss.slow.70, label %ss.chk_top.71 + +ss.slow.70: + call void @js_shadow_slot_set(i32 3, i64 0) + br label %ss.done.74 + +ss.chk_top.71: + %r339 = getelementptr inbounds i8, ptr %r337, i64 24 + %r340 = load i64, ptr %r339 + %r341 = icmp eq i64 %r340, -1 + br i1 %r341, label %ss.done.74, label %ss.chk_len.72 + +ss.chk_len.72: + %r342 = add i64 %r340, 3 + %r343 = getelementptr inbounds i8, ptr %r337, i64 8 + %r344 = load i64, ptr %r343 + %r345 = icmp ult i64 %r342, %r344 + br i1 %r345, label %ss.store.73, label %ss.done.74 + +ss.store.73: + %r346 = load ptr, ptr %r337 + %r347 = shl i64 %r342, 4 + %r348 = getelementptr inbounds i8, ptr %r346, i64 %r347 + %r349 = getelementptr inbounds i8, ptr %r348, i64 8 + %r350 = load i64, ptr %r349 + %r351 = and i64 %r350, -2 + store i64 0, ptr %r348 + store i64 %r351, ptr %r349 + br label %ss.done.74 + +ss.done.74: + %r352 = load ptr, ptr %r2 + %r353 = icmp eq ptr %r352, null + br i1 %r353, label %ss.slow.75, label %ss.chk_top.76 + +ss.slow.75: + call void @js_shadow_slot_set(i32 4, i64 0) + br label %ss.done.79 + +ss.chk_top.76: + %r354 = getelementptr inbounds i8, ptr %r352, i64 24 + %r355 = load i64, ptr %r354 + %r356 = icmp eq i64 %r355, -1 + br i1 %r356, label %ss.done.79, label %ss.chk_len.77 + +ss.chk_len.77: + %r357 = add i64 %r355, 4 + %r358 = getelementptr inbounds i8, ptr %r352, i64 8 + %r359 = load i64, ptr %r358 + %r360 = icmp ult i64 %r357, %r359 + br i1 %r360, label %ss.store.78, label %ss.done.79 + +ss.store.78: + %r361 = load ptr, ptr %r352 + %r362 = shl i64 %r357, 4 + %r363 = getelementptr inbounds i8, ptr %r361, i64 %r362 + %r364 = getelementptr inbounds i8, ptr %r363, i64 8 + %r365 = load i64, ptr %r364 + %r366 = and i64 %r365, -2 + store i64 0, ptr %r363 + store i64 %r366, ptr %r364 + br label %ss.done.79 + +ss.done.79: + %r367 = call i64 @js_array_alloc(i32 2) + %r368 = call i32 @js_gc_temp_root_push(i64 %r367) + %r369 = load double, ptr @spike_ts_.str.11.handle + call void @js_array_push_f64_temp_rooted(i32 %r368, double %r369) + %r370 = call i32 @js_gc_temp_root_push(i64 0) + %r373 = load i64, ptr %r371 + %r374 = call i64 @js_object_alloc_class_inline_keys(i32 1, i32 0, i32 2, i64 %r373) + %r375 = call i32 @js_gc_temp_root_push(i64 %r374) + %r376 = or i64 %r374, 9222527611924643840 + %r377 = bitcast i64 %r376 to double + %r378 = call double @spike_ts__Point_constructor(double %r377, double 3.0, double 4.0) + %r379 = call i64 @js_gc_temp_root_get(i32 %r375) + %r380 = or i64 %r379, 9222527611924643840 + %r381 = bitcast i64 %r380 to double + call void @js_gc_init_typed_shape_layout(i64 %r379, i32 2, ptr @perry_typed_shape_raw_f64_mask_spike_ts__Point, i32 1, ptr null, i32 0) + %r382 = call double @js_ctor_return_override(double %r381, double %r378, i32 0) + call void @js_gc_temp_root_truncate(i32 %r370) + %r385 = load i64, ptr %r383 + br label %method_direct.guard.80 + +method_direct.guard.80: + %r386 = call i32 @js_method_direct_shape_guard(double %r382, i32 1, i64 %r385) + %r387 = icmp ne i32 %r386, 0 + br i1 %r387, label %method_direct.fast.81, label %method_direct.fallback.82 + +method_direct.fast.81: + %r388 = call double @perry_method_spike_ts__Point__norm__pshape(double %r382) + br label %method_direct.merge.83 + +method_direct.fallback.82: + %r389 = ptrtoint ptr @spike_ts_.str.12.dispatch to i64 + %r390 = or i64 %r389, 9221120237041090560 + %r391 = call double @js_native_call_method_by_id(double %r382, i64 %r390, ptr null, i64 0) + br label %method_direct.merge.83 + +method_direct.merge.83: + %r392 = phi double [ %r388, %method_direct.fast.81 ], [ %r391, %method_direct.fallback.82 ] + call void @js_array_push_f64_temp_rooted(i32 %r368, double %r392) + %r393 = call i64 @js_gc_temp_root_get(i32 %r368) + call void @js_console_log_spread(i64 %r393) + call void @js_gc_temp_root_truncate(i32 %r368) + %r395 = call i64 @js_closure_alloc_singleton(ptr @perry_closure_spike_ts__4) + %r396 = or i64 %r395, 9222527611924643840 + %r397 = bitcast i64 %r396 to double + store double %r397, ptr %r394 + %r398 = load ptr, ptr %r2 + %r399 = icmp eq ptr %r398, null + br i1 %r399, label %ss.slow.84, label %ss.chk_top.85 + +ss.slow.84: + call void @js_shadow_slot_bind(i32 5, ptr %r394) + br label %ss.done.88 + +ss.chk_top.85: + %r400 = getelementptr inbounds i8, ptr %r398, i64 24 + %r401 = load i64, ptr %r400 + %r402 = icmp eq i64 %r401, -1 + br i1 %r402, label %ss.done.88, label %ss.chk_len.86 + +ss.chk_len.86: + %r403 = add i64 %r401, 5 + %r404 = getelementptr inbounds i8, ptr %r398, i64 8 + %r405 = load i64, ptr %r404 + %r406 = icmp ult i64 %r403, %r405 + br i1 %r406, label %ss.store.87, label %ss.done.88 + +ss.store.87: + %r407 = load ptr, ptr %r398 + %r408 = shl i64 %r403, 4 + %r409 = getelementptr inbounds i8, ptr %r407, i64 %r408 + %r410 = getelementptr inbounds i8, ptr %r409, i64 8 + %r411 = load i64, ptr %r394 + %r412 = ptrtoint ptr %r394 to i64 + %r413 = and i64 %r412, 1 + %r414 = icmp eq i64 %r413, 0 + %r415 = select i1 %r414, i64 %r412, i64 0 + %r416 = or i64 %r415, 1 + store i64 %r411, ptr %r409 + store i64 %r416, ptr %r410 + %r417 = load atomic i32, ptr @PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT seq_cst, align 4 + %r418 = icmp ne i32 %r417, 0 + br i1 %r418, label %ss.barrier.89, label %ss.done.88 + +ss.done.88: + %r419 = load double, ptr %r394 + %r420 = load double, ptr @spike_ts_.str.13.handle + %r421 = bitcast double %r419 to i64 + %r422 = and i64 %r421, 281474976710655 + %r423 = call i32 @js_typed_feedback_closure_direct_call_guard(i64 7695367220062322696, double %r419, ptr @perry_closure_spike_ts__4, i32 1, i32 1) + %r424 = icmp ne i32 %r423, 0 + br i1 %r424, label %closure_direct.fast.90, label %closure_direct.fallback.91 + +ss.barrier.89: + call void @js_write_barrier_root_nanbox(i64 %r411) + br label %ss.done.88 + +closure_direct.fast.90: + %r425 = call double @perry_closure_spike_ts__4(i64 %r422, double %r420) + br label %closure_direct.merge.92 + +closure_direct.fallback.91: + call void @js_typed_feedback_record_fallback_call(i64 7695367220062322696) + %r426 = call double @js_implicit_this_set(double 0x7FFC000000000001) + %r427 = bitcast double %r426 to i64 + %r428 = call i32 @js_gc_temp_root_push(i64 %r427) + %r429 = call double @js_closure_call1(i64 %r422, double %r420) + %r430 = call i64 @js_gc_temp_root_get(i32 %r428) + %r431 = bitcast i64 %r430 to double + call void @js_gc_temp_root_truncate(i32 %r428) + %r432 = call double @js_implicit_this_set(double %r431) + br label %closure_direct.merge.92 + +closure_direct.merge.92: + %r433 = phi double [ %r425, %closure_direct.fast.90 ], [ %r429, %closure_direct.fallback.91 ] + %r434 = bitcast double %r433 to i64 + %r435 = call i32 @js_gc_temp_root_push(i64 %r434) + %r436 = call i64 @js_array_alloc(i32 1) + %r437 = call i32 @js_gc_temp_root_push(i64 %r436) + %r438 = call i64 @js_gc_temp_root_get(i32 %r435) + %r439 = bitcast i64 %r438 to double + call void @js_array_push_f64_temp_rooted(i32 %r437, double %r439) + %r440 = call i64 @js_gc_temp_root_get(i32 %r437) + call void @js_console_log_spread(i64 %r440) + call void @js_gc_temp_root_truncate(i32 %r435) + %r441 = load ptr, ptr %r2 + %r442 = icmp eq ptr %r441, null + br i1 %r442, label %ss.slow.93, label %ss.chk_top.94 + +ss.slow.93: + call void @js_shadow_slot_set(i32 5, i64 0) + br label %ss.done.97 + +ss.chk_top.94: + %r443 = getelementptr inbounds i8, ptr %r441, i64 24 + %r444 = load i64, ptr %r443 + %r445 = icmp eq i64 %r444, -1 + br i1 %r445, label %ss.done.97, label %ss.chk_len.95 + +ss.chk_len.95: + %r446 = add i64 %r444, 5 + %r447 = getelementptr inbounds i8, ptr %r441, i64 8 + %r448 = load i64, ptr %r447 + %r449 = icmp ult i64 %r446, %r448 + br i1 %r449, label %ss.store.96, label %ss.done.97 + +ss.store.96: + %r450 = load ptr, ptr %r441 + %r451 = shl i64 %r446, 4 + %r452 = getelementptr inbounds i8, ptr %r450, i64 %r451 + %r453 = getelementptr inbounds i8, ptr %r452, i64 8 + %r454 = load i64, ptr %r453 + %r455 = and i64 %r454, -2 + store i64 0, ptr %r452 + store i64 %r455, ptr %r453 + br label %ss.done.97 + +ss.done.97: + %r456 = bitcast double 0x7FFC000000000001 to i64 + %r457 = bitcast double 0x7FFC000000000001 to i64 + %r458 = bitcast double 0x7FFC000000000001 to i64 + %r459 = bitcast double 0x7FFC000000000001 to i64 + %r460 = bitcast double 0x7FFC000000000001 to i64 + %r462 = getelementptr i64, ptr %r461, i64 0 + store i64 %r456, ptr %r462 + %r463 = getelementptr i64, ptr %r461, i64 1 + store i64 %r457, ptr %r463 + %r464 = getelementptr i64, ptr %r461, i64 2 + store i64 %r458, ptr %r464 + %r465 = getelementptr i64, ptr %r461, i64 3 + store i64 %r459, ptr %r465 + %r466 = getelementptr i64, ptr %r461, i64 4 + store i64 %r460, ptr %r466 + %r467 = call i64 @js_closure_alloc_with_captures_singleton(ptr @perry_closure_spike_ts__5, i32 5, ptr %r461) + %r468 = or i64 %r467, 9222527611924643840 + %r469 = bitcast i64 %r468 to double + %r470 = call double @js_implicit_this_set(double 0x7FFC000000000001) + %r471 = bitcast double %r470 to i64 + %r472 = call i32 @js_gc_temp_root_push(i64 %r471) + %r473 = call i64 @js_closure_unbox_callee_checked(double %r469) + %r474 = call double @js_closure_call0(i64 %r473) + %r475 = call i64 @js_gc_temp_root_get(i32 %r472) + %r476 = bitcast i64 %r475 to double + call void @js_gc_temp_root_truncate(i32 %r472) + %r477 = call double @js_implicit_this_set(double %r476) + %r478 = call i32 @js_promise_run_microtasks_event_loop() + %r479 = call i32 @js_timer_tick_if_refed() + %r480 = call i32 @js_callback_timer_tick() + %r481 = call i32 @js_interval_timer_tick() + %r482 = call i32 @js_promise_run_microtasks_event_loop() + %r483 = call i32 @js_timer_tick_if_refed() + %r484 = call i32 @js_callback_timer_tick() + %r485 = call i32 @js_interval_timer_tick() + %r486 = call i32 @js_promise_run_microtasks_event_loop() + %r487 = call i32 @js_timer_tick_if_refed() + %r488 = call i32 @js_callback_timer_tick() + %r489 = call i32 @js_interval_timer_tick() + %r490 = call i32 @js_promise_run_microtasks_event_loop() + %r491 = call i32 @js_timer_tick_if_refed() + %r492 = call i32 @js_callback_timer_tick() + %r493 = call i32 @js_interval_timer_tick() + call void @js_run_stdlib_pump() + br label %event_loop.header.98 + +event_loop.header.98: + %r494 = call i32 @js_event_loop_host_driven() + %r495 = icmp ne i32 %r494, 0 + br i1 %r495, label %event_loop.host_return.100, label %event_loop.check_pending.99 + +event_loop.check_pending.99: + %r496 = call i32 @js_timer_has_pending() + %r497 = call i32 @js_callback_timer_has_pending() + %r498 = call i32 @js_interval_timer_has_pending() + %r499 = call i32 @js_stdlib_has_active_handles() + %r500 = call i32 @js_microtasks_pending() + %r501 = or i32 %r496, %r497 + %r502 = or i32 %r498, %r499 + %r503 = or i32 %r501, %r502 + %r504 = or i32 %r503, 0 + %r505 = or i32 %r504, %r500 + %r506 = icmp ne i32 %r505, 0 + br i1 %r506, label %event_loop.body.101, label %event_loop.exit.102 + +event_loop.host_return.100: + call void @js_typed_feedback_maybe_dump_trace() + %shadow_pop_l_0 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_0) + ret i32 0 + +event_loop.body.101: + %r507 = call i32 @js_promise_run_microtasks_event_loop() + %r508 = call i32 @js_timer_tick() + %r509 = call i32 @js_callback_timer_tick() + %r510 = call i32 @js_interval_timer_tick() + call void @js_run_stdlib_pump() + call void @js_wait_for_event() + br label %event_loop.header.98 + +event_loop.exit.102: + call void @js_process_emit_before_exit(double 0x0) + %r511 = call i32 @js_promise_run_microtasks_event_loop() + %r512 = call i32 @js_timer_tick_if_refed() + %r513 = call i32 @js_callback_timer_tick() + %r514 = call i32 @js_interval_timer_tick() + call void @js_process_run_finalization_exit() + call void @js_trace_events_flush_output() + call void @js_promise_report_unhandled_rejections() + call void @js_gc_release_current_thread_collection_side_allocations() + %r515 = call i32 @js_process_pending_exit_code() + call void @js_typed_feedback_maybe_dump_trace() + %shadow_pop_l_1 = load i64, ptr %r1 + call void @js_shadow_frame_pop(i64 %shadow_pop_l_1) + ret i32 %r515 +} + +define void @__perry_init_strings_spike_ts_chunk0() { +entry.0: + %r1 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.0.bytes, i32 7) + %r2 = call double @js_nanbox_string(i64 %r1) + store double %r2, ptr @spike_ts_.str.0.handle + %r3 = ptrtoint ptr @spike_ts_.str.0.handle to i64 + call void @js_gc_register_global_root(i64 %r3) + %r4 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.1.bytes, i32 1) + %r5 = call double @js_nanbox_string(i64 %r4) + store double %r5, ptr @spike_ts_.str.1.handle + %r6 = ptrtoint ptr @spike_ts_.str.1.handle to i64 + call void @js_gc_register_global_root(i64 %r6) + %r7 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.2.bytes, i32 6) + %r8 = call double @js_nanbox_string(i64 %r7) + store double %r8, ptr @spike_ts_.str.2.handle + %r9 = ptrtoint ptr @spike_ts_.str.2.handle to i64 + call void @js_gc_register_global_root(i64 %r9) + %r10 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.3.bytes, i32 1) + %r11 = call double @js_nanbox_string(i64 %r10) + store double %r11, ptr @spike_ts_.str.3.handle + %r12 = ptrtoint ptr @spike_ts_.str.3.handle to i64 + call void @js_gc_register_global_root(i64 %r12) + %r13 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.4.bytes, i32 1) + %r14 = call double @js_nanbox_string(i64 %r13) + store double %r14, ptr @spike_ts_.str.4.handle + %r15 = ptrtoint ptr @spike_ts_.str.4.handle to i64 + call void @js_gc_register_global_root(i64 %r15) + %r16 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.5.bytes, i32 9) + %r17 = call double @js_nanbox_string(i64 %r16) + store double %r17, ptr @spike_ts_.str.5.handle + %r18 = ptrtoint ptr @spike_ts_.str.5.handle to i64 + call void @js_gc_register_global_root(i64 %r18) + %r19 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.6.bytes, i32 7) + %r20 = call double @js_nanbox_string(i64 %r19) + store double %r20, ptr @spike_ts_.str.6.handle + %r21 = ptrtoint ptr @spike_ts_.str.6.handle to i64 + call void @js_gc_register_global_root(i64 %r21) + %r22 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.7.bytes, i32 1) + %r23 = call double @js_nanbox_string(i64 %r22) + store double %r23, ptr @spike_ts_.str.7.handle + %r24 = ptrtoint ptr @spike_ts_.str.7.handle to i64 + call void @js_gc_register_global_root(i64 %r24) + %r25 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.8.bytes, i32 5) + %r26 = call double @js_nanbox_string(i64 %r25) + store double %r26, ptr @spike_ts_.str.8.handle + %r27 = ptrtoint ptr @spike_ts_.str.8.handle to i64 + call void @js_gc_register_global_root(i64 %r27) + %r28 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.9.bytes, i32 4) + %r29 = call double @js_nanbox_string(i64 %r28) + store double %r29, ptr @spike_ts_.str.9.handle + %r30 = ptrtoint ptr @spike_ts_.str.9.handle to i64 + call void @js_gc_register_global_root(i64 %r30) + %r31 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.10.bytes, i32 2) + %r32 = call double @js_nanbox_string(i64 %r31) + store double %r32, ptr @spike_ts_.str.10.handle + %r33 = ptrtoint ptr @spike_ts_.str.10.handle to i64 + call void @js_gc_register_global_root(i64 %r33) + %r34 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.11.bytes, i32 5) + %r35 = call double @js_nanbox_string(i64 %r34) + store double %r35, ptr @spike_ts_.str.11.handle + %r36 = ptrtoint ptr @spike_ts_.str.11.handle to i64 + call void @js_gc_register_global_root(i64 %r36) + %r37 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.12.bytes, i32 4) + %r38 = call double @js_nanbox_string(i64 %r37) + store double %r38, ptr @spike_ts_.str.12.handle + %r39 = ptrtoint ptr @spike_ts_.str.12.handle to i64 + call void @js_gc_register_global_root(i64 %r39) + %r40 = call i64 @js_string_from_bytes(ptr @spike_ts_.str.13.bytes, i32 5) + %r41 = call double @js_nanbox_string(i64 %r40) + store double %r41, ptr @spike_ts_.str.13.handle + %r42 = ptrtoint ptr @spike_ts_.str.13.handle to i64 + call void @js_gc_register_global_root(i64 %r42) + call void @js_register_function_name(ptr @__perry_wrap_perry_fn_spike_ts__fib, ptr @.str.0, i32 3) + call void @js_register_function_name(ptr @perry_closure_spike_ts__4, ptr @.str.1, i32 5) + call void @js_register_function_source(ptr @__perry_wrap_perry_fn_spike_ts__fib, ptr @.str.2, i32 81) + call void @js_register_function_source(ptr @perry_closure_spike_ts__1, ptr @.str.3, i32 15) + call void @js_register_function_source(ptr @perry_closure_spike_ts__4, ptr @.str.4, i32 35) + call void @js_register_function_source(ptr @perry_closure_spike_ts__5, ptr @.str.5, i32 82) + %r43 = call i64 @js_build_class_keys_array(i32 1, i32 2, ptr @perry_class_keys_packed_spike_ts__0, i32 4) + store i64 %r43, ptr @perry_class_keys_spike_ts__Point + call void @js_write_barrier_root_heap_word(i64 %r43) + %r44 = ptrtoint ptr @perry_class_keys_spike_ts__Point to i64 + call void @js_gc_register_global_root(i64 %r44) + %r45 = ptrtoint ptr @perry_method_spike_ts__Point__norm to i64 + %r46 = ptrtoint ptr @spike_ts_.str.12.bytes to i64 + call void @js_register_class_method(i64 1, i64 %r46, i64 4, i64 %r45, i64 0, i64 0, i64 0) + call void @js_register_class_method_bind_length(i64 1, i64 %r46, i64 4, i64 0) + %r47 = ptrtoint ptr @spike_ts__Point_constructor to i64 + call void @js_register_class_constructor(i64 1, i64 %r47, i64 2, i64 0) + call void @js_register_class_id(i32 1) + call void @js_register_class_name(i32 1, ptr @.str.6, i32 5) + call void @js_register_closure_arity(ptr @perry_closure_spike_ts__1, i32 2) + call void @js_register_closure_arity(ptr @perry_closure_spike_ts__4, i32 1) + call void @js_register_closure_arity(ptr @perry_closure_spike_ts__5, i32 0) + call void @js_register_closure_arity(ptr @perry_closure_spike_ts__8, i32 2) + call void @js_register_closure_length(ptr @perry_closure_spike_ts__1, i32 2) + call void @js_register_closure_length(ptr @perry_closure_spike_ts__4, i32 1) + call void @js_register_closure_length(ptr @perry_closure_spike_ts__5, i32 0) + call void @js_register_closure_length(ptr @perry_closure_spike_ts__8, i32 2) + call void @js_register_closure_arrow_function(ptr @perry_closure_spike_ts__1) + call void @js_register_closure_arrow_function(ptr @perry_closure_spike_ts__4) + call void @js_register_closure_arrow_function(ptr @perry_closure_spike_ts__5) + call void @js_register_closure_arity(ptr @__perry_wrap_perry_fn_spike_ts__fib, i32 1) + call void @js_register_closure_length(ptr @__perry_wrap_perry_fn_spike_ts__fib, i32 1) + call void @js_register_closure_strict_function(ptr @__perry_wrap_perry_fn_spike_ts__fib) + call void @js_register_closure_strict_function(ptr @perry_closure_spike_ts__1) + call void @js_register_closure_strict_function(ptr @perry_closure_spike_ts__4) + call void @js_register_closure_strict_function(ptr @perry_closure_spike_ts__5) + call void @js_register_closure_strict_function(ptr @perry_closure_spike_ts__8) + ret void +} + +define void @__perry_init_strings_spike_ts() { +entry.0: + call void @__perry_init_strings_spike_ts_chunk0() + ret void +} + + +attributes #0 = { returns_twice } +attributes #1 = { noinline } + +attributes #2 = { nounwind willreturn readnone } + +attributes #3 = { nounwind willreturn readonly } + +attributes #4 = { nounwind willreturn } + +!0 = !{} From cbe26ecfbf6be67d1206bdc4a4f9eb353b738815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Mon, 3 Aug 2026 07:05:40 +0200 Subject: [PATCH 17/26] exp: diff arms share one module identifier (ELF records it in STT_FILE) On Mach-O the module name reaches nothing; on ELF it lands in the object's symtab (#7131), so differently-named diff arms would fail byte-identity on the identifier alone. Same name for both arms. Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/native_emit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs index 9556abb233..0a1b987085 100644 --- a/crates/perry-codegen/src/native_emit.rs +++ b/crates/perry-codegen/src/native_emit.rs @@ -141,7 +141,7 @@ pub fn compile_module_native(llmod: &LlModule, target: Option<&str>) -> Result) -> Result> { let text = llmod.to_ir(); let ctx_text = Context::create(); - let m_text = crate::inprocess::parse_ir_text(&ctx_text, &text, "perry_diff_text")?; + let m_text = crate::inprocess::parse_ir_text(&ctx_text, &text, "perry_native_module")?; let (effective_target, args) = plan_for(llmod, target); let ctx_native = Context::create(); From 934bbdfbddd7fe74988b0e8efa503c468191d019 Mon Sep 17 00:00:00 2001 From: Ralph Kuepper Date: Mon, 3 Aug 2026 10:07:36 +0200 Subject: [PATCH 18/26] =?UTF-8?q?exp:=20Linux=20bring-up=20=E2=80=94=20por?= =?UTF-8?q?table=20A/B=20harness,=20resumable,=20no=20vacuous=20corpus=20s?= =?UTF-8?q?kip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Everything needed to run the Phase 2 sweep on Linux, found by running it. batch_ab.sh could not start on Linux at all: `TIMEOUT=$(command -v "$TIMEOUT")` dies under `set -u` (the intent was coreutils' macOS `gtimeout`), and WT was a hardcoded /Users path. WT now derives from the script's own location, and the free-space probe looks at the filesystem the work dir is actually on rather than "/" — on a typical Linux box /home is a different, much larger volume. Two guards earned by a real interruption: a concurrent cargo build pushed the host into the OOM killer, which killed six compiles mid-link. Those landed in results.txt as CFAIL_BOTH — indistinguishable, after the fact, from six real pre-existing failures, and they cost a full restart of a ~80-minute run. So: re-running now resumes (tests already recorded are skipped), and a compile that dies on a signal is never scored — it waits for memory, retries once, and if it dies again it is recorded as OOM_INFRA and reported on its own summary line, a category no backend conclusion may be drawn from. The corpus gate's missing-file branch printed "skipping" and returned green. The corpora have been tracked in-tree since 4f001d39e, so absence now means a broken checkout, not a branch without artifacts — it is a hard error. That branch was exactly the vacuous green the Linux run had to rule out by hand. Also documents the Fedora LLVM 22 route (no distro package at any version): the upstream release tarball plus a shim prefix, because the tarball's baked-in `llvm-config --system-libs` names its Ubuntu build host's libzstd.a by absolute path and llvm-sys panics on an entry that is neither -lfoo nor an existing file. --- crates/perry-codegen/src/dialect.rs | 12 +-- docs/llvm-inprocess-experiment.md | 26 +++++- experiments/llvm-inprocess-spike/batch_ab.sh | 85 ++++++++++++++++---- 3 files changed, 99 insertions(+), 24 deletions(-) diff --git a/crates/perry-codegen/src/dialect.rs b/crates/perry-codegen/src/dialect.rs index 6aaa809793..2bfca66de6 100644 --- a/crates/perry-codegen/src/dialect.rs +++ b/crates/perry-codegen/src/dialect.rs @@ -1410,12 +1410,12 @@ mod tests { /// natively and pass the LLVM verifier. This is the reader's primary /// gate: a form it cannot express fails here, not in a user build. fn corpus_roundtrip(path: &str) { - let Ok(text) = std::fs::read_to_string(path) else { - // Corpus artifacts live on the experiment branch; absence is a - // skip (other branches), not a failure. - eprintln!("corpus file {path} not present; skipping"); - return; - }; + // The corpora are tracked in-tree alongside this reader, so a missing + // file is a broken checkout, not a branch without artifacts. Skipping + // would make the reader's primary gate pass vacuously — precisely the + // failure mode the Linux bring-up had to rule out by hand. + let text = std::fs::read_to_string(path) + .unwrap_or_else(|e| panic!("corpus file {path} is not readable: {e}")); let (skeleton, fns) = split_corpus(&text); let ctx = Context::create(); let module = crate::inprocess::parse_ir_text(&ctx, &skeleton, "corpus_skel") diff --git a/docs/llvm-inprocess-experiment.md b/docs/llvm-inprocess-experiment.md index 8d734747f0..0c37492379 100644 --- a/docs/llvm-inprocess-experiment.md +++ b/docs/llvm-inprocess-experiment.md @@ -310,6 +310,30 @@ LLVM_SYS_221_PREFIX=/opt/homebrew/opt/llvm \ -p perry-stdlib-static --features perry/llvm-inprocess PERRY_LLVM_INPROCESS=1 perry file.ts -o out # stderr must show the liveness line -# Corpus A/B +# Corpus A/B (resumable; re-running skips tests already in results.txt) experiments/llvm-inprocess-spike/batch_ab.sh /tmp/batch-ab ``` + +### Linux: getting LLVM 22 where the distro has none + +The handoff's `apt.llvm.org` recipe covers Debian/Ubuntu. On a distro with no +LLVM 22 package at all (Fedora 43 stops at `llvm20-devel`; its system libs are +21), use the upstream release tarball, which ships headers, `llvm-config`, the +static `libLLVM*.a` set and a matching clang: + +```bash +curl -LO https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8/LLVM-22.1.8-Linux-X64.tar.xz +tar -xf LLVM-22.1.8-Linux-X64.tar.xz -C ~/opt # ~12 GB unpacked +``` + +One trap: that tarball is built on Ubuntu, so its baked-in +`llvm-config --system-libs` answer names the *build host's* static zstd by +absolute path (`/usr/lib/x86_64-linux-gnu/libzstd.a`). llvm-sys panics on any +`--system-libs` entry that is neither `-lfoo` nor an existing file, so on any +other distro the build dies before it starts. Point `LLVM_SYS_221_PREFIX` at a +one-file shim prefix whose `bin/llvm-config` rewrites that path to `-lzstd` and +forwards everything else (the real binary still answers all path queries +relative to its own prefix, so nothing else needs redirecting). + +Measured cost of the feature build on this host: `perry` 199 MB (vs 53 MB +default), `cargo build --profile perry-dev` 2m49s warm-registry cold-target. diff --git a/experiments/llvm-inprocess-spike/batch_ab.sh b/experiments/llvm-inprocess-spike/batch_ab.sh index be86ca7b05..4d73458ffb 100755 --- a/experiments/llvm-inprocess-spike/batch_ab.sh +++ b/experiments/llvm-inprocess-spike/batch_ab.sh @@ -5,7 +5,9 @@ # Divergence classes reported: SAME, DIFF (output/exit differs), CFAIL_T/CFAIL_P # (one arm's compile failed), CFAIL_BOTH (pre-existing, not backend-related). set -u -WT=/Users/amlug/projects/perry/wt-llvmbackend +# Worktree root: derived from this script's own location so a fresh clone on +# any host works unmodified; override with WT=... for an out-of-tree layout. +WT=${WT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)} SPIKE=$WT/experiments/llvm-inprocess-spike/target/release/perry-llvmc-spike PERRY=$WT/target/perry-dev/perry WORK=${1:?usage: batch_ab.sh [shim|flag] [stride] [offset]} @@ -15,13 +17,15 @@ WORK=${1:?usage: batch_ab.sh [shim|flag] [stride] [offset]} MODE=${2:-shim} STRIDE=${3:-6} OFFSET=${4:-0} -# Portability: "$TIMEOUT" is coreutils' name on macOS (brew), timeout on Linux. -TIMEOUT=$(command -v "$TIMEOUT" || command -v timeout) +# Portability: coreutils installs `gtimeout` on macOS (brew), `timeout` on Linux. +TIMEOUT=$(command -v gtimeout || command -v timeout) +# Probe the filesystem the work dir actually lives on, not "/" — on a typical +# Linux box /home is a separate (and much larger) filesystem than /. free_gb_now() { if [ "$(uname)" = "Darwin" ]; then - df -g /System/Volumes/Data | awk 'NR==2{print $4}' + df -g "$WORK" | awk 'NR==2{print $4}' else - df -BG --output=avail / | awk 'NR==2{gsub("G","",$1); print $1}' + df -BG --output=avail "$WORK" | awk 'NR==2{gsub("G","",$1); print $1}' fi } mkdir -p "$WORK" @@ -29,27 +33,72 @@ export PERRY_RUNTIME_DIR=$WT/target/perry-dev export PERRY_NO_AUTO_OPTIMIZE=1 export PERRY_LLVMC_SPIKE_LOG=$WORK/liveness.log : > "$WORK/liveness.log" +touch "$WORK/results.txt" -i=0 same=0 diff=0 cfail_t=0 cfail_p=0 cfail_both=0 +# A full-suite run is ~100 minutes of a developer workstation's life, so it has +# to survive that workstation being used. Two guards, learned the hard way when +# a concurrent cargo build pushed the box into the OOM killer and six compiles +# died mid-link — recorded as CFAIL_BOTH, which reads exactly like a real +# pre-existing failure: +# +# 1. Re-running skips tests already recorded, so an interrupted run resumes +# instead of starting over (delete results.txt for a clean run). +# 2. A compile killed by a signal (128+n; the OOM killer's SIGKILL is 137) is +# never scored. It waits for memory, retries once, and if it dies again it +# is recorded as OOM/INFRA — a category no backend conclusion may be drawn +# from, and one the summary reports separately. +free_mb_now() { + if [ "$(uname)" = "Darwin" ]; then + vm_stat | awk '/page size of/{p=$8} /Pages free/{f=$3} END{print int(f*p/1048576)}' + else + awk '/MemAvailable/{print int($2/1024)}' /proc/meminfo + fi +} +MIN_FREE_MB=${MIN_FREE_MB:-2048} +wait_for_memory() { + local waited=0 + while [ "$(free_mb_now)" -lt "$MIN_FREE_MB" ] && [ $waited -lt 600 ]; do + sleep 10; waited=$((waited+10)) + done +} +# A compile that exits 128+n died on signal n rather than failing to compile. +# (`timeout`'s own 124 is deliberately NOT in this class: a compile that hangs +# for 180s is a result worth seeing, not infrastructure noise.) +killed_by_signal() { [ "$1" -gt 128 ]; } + +i=0 same=0 diff=0 cfail_t=0 cfail_p=0 cfail_both=0 skipped=0 infra=0 for t in $(ls "$WT"/test-files/test_gap_*.ts | sort); do i=$((i+1)) [ $((i % STRIDE)) -ne $OFFSET ] && continue name=$(basename "$t" .ts) + if grep -q " $name\$\| $name " "$WORK/results.txt"; then skipped=$((skipped+1)); continue; fi free_gb=$(free_gb_now) if [ "$free_gb" -lt 6 ]; then echo "ABORT: only ${free_gb}GB free" | tee -a "$WORK/summary.txt"; exit 2; fi + wait_for_memory - "$TIMEOUT" 180 "$PERRY" "$t" -o "$WORK/$name.t" >"$WORK/$name.t.compile" 2>&1 - ct=$? - if [ "$MODE" = "flag" ]; then - PERRY_LLVM_INPROCESS=${INPROCESS_VALUE:-1} "$TIMEOUT" 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 - cp=$? - # Liveness: the arm must have announced the in-process backend. - if [ $cp -eq 0 ] && ! grep -q "in-process LLVM backend active" "$WORK/$name.p.compile"; then - echo "NOT_LIVE $name" >> "$WORK/results.txt"; cp=97 + compile_arms() { + "$TIMEOUT" 180 "$PERRY" "$t" -o "$WORK/$name.t" >"$WORK/$name.t.compile" 2>&1 + ct=$? + if [ "$MODE" = "flag" ]; then + PERRY_LLVM_INPROCESS=${INPROCESS_VALUE:-1} "$TIMEOUT" 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 + cp=$? + # Liveness: the arm must have announced the in-process backend. + if [ $cp -eq 0 ] && ! grep -q "in-process LLVM backend active" "$WORK/$name.p.compile"; then + echo "NOT_LIVE $name" >> "$WORK/results.txt"; cp=97 + fi + else + PERRY_LLVM_CLANG=$SPIKE "$TIMEOUT" 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 + cp=$? + fi + } + compile_arms + if killed_by_signal $ct || killed_by_signal $cp; then + wait_for_memory + compile_arms + if killed_by_signal $ct || killed_by_signal $cp; then + infra=$((infra+1)); echo "OOM_INFRA $name (signal t=$ct p=$cp — NOT a backend result)" >> "$WORK/results.txt" + rm -f "$WORK/$name".[tp]; continue fi - else - PERRY_LLVM_CLANG=$SPIKE "$TIMEOUT" 180 "$PERRY" "$t" -o "$WORK/$name.p" >"$WORK/$name.p.compile" 2>&1 - cp=$? fi if [ $ct -ne 0 ] && [ $cp -ne 0 ]; then cfail_both=$((cfail_both+1)); echo "CFAIL_BOTH $name" >> "$WORK/results.txt"; rm -f "$WORK/$name".[tp]; continue; fi @@ -72,5 +121,7 @@ else fi { echo "batch A/B complete: same=$same diff=$diff cfail_t=$cfail_t cfail_p=$cfail_p cfail_both=$cfail_both" + echo "resumed (already recorded, not re-run): $skipped" + echo "OOM/INFRA (killed by signal twice — excluded from every conclusion): $infra" echo "in-process compiles proven live: $compiles" } | tee "$WORK/summary.txt" From 2c951e814a171502a2a02ab18d3de2604a13b7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Mon, 3 Aug 2026 10:08:08 +0200 Subject: [PATCH 19/26] exp: migrate all 68 LlBlock semantic methods to typed LlInst variants Every emit(format!) in the semantic surface becomes a typed push: Bin/FNeg/FCmp/ICmp/Alloca/Load{5 flavors}/Store/Cast/Select/Call/ CallIndirect/AsmBarrier/Br/CondBr/Ret/RetVoid/Unreachable/Gep/Phi. Renderers are byte-identical to the replaced format! strings (gate: the full 528-test suite, which pins exact rendered IR). push_inst preserves the terminator discipline and try-region store tracking (typed note_store_ptr twin); contains_gc_unsafe_call answers structurally for typed calls. text_len renders into a thread-local scratch so the codegen-unit balancer's sums stay exact. emit/emit_raw remain the Raw escape hatch (89 bespoke call sites). Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo --- crates/perry-codegen/src/block.rs | 612 ++++++++++++++++++++++-------- crates/perry-codegen/src/inst.rs | 354 ++++++++++++++++- 2 files changed, 785 insertions(+), 181 deletions(-) diff --git a/crates/perry-codegen/src/block.rs b/crates/perry-codegen/src/block.rs index 6795bebb67..6cbab38e7a 100644 --- a/crates/perry-codegen/src/block.rs +++ b/crates/perry-codegen/src/block.rs @@ -109,6 +109,17 @@ impl RegCounter { self.try_region_stores.borrow() } + /// Typed twin of [`note_emitted`] for `LlInst::Store` pushes: record the + /// store destination if we are inside a setjmp-protected region. + pub(crate) fn note_store_ptr(&self, ptr: &str) { + if self.try_region_depth.get() == 0 { + return; + } + if ptr.starts_with('%') { + self.try_region_stores.borrow_mut().insert(ptr.to_string()); + } + } + /// Record `line`'s store destination if we are inside a try region. /// Called from [`LlBlock::emit`], the single choke point every emitter /// (including `emit_raw`) funnels through. @@ -178,14 +189,7 @@ impl LlBlock { /// check cannot be invalidated mid-loop). Intrinsic/libm-style calls /// never enter the perry runtime, so they cannot trigger a collection. pub fn contains_gc_unsafe_call(&self) -> bool { - self.instructions.iter().any(|inst| { - let line = inst.scan_str(); - let Some(pos) = line.find("call ") else { - return false; - }; - let callee = &line[pos..]; - !callee.contains("@llvm.") && !callee.contains(" asm ") - }) + self.instructions.iter().any(|i| i.is_gc_unsafe_call()) } /// Allocate a fresh SSA register name in the enclosing function's @@ -198,6 +202,18 @@ impl LlBlock { self.reg() } + /// Typed twin of [`emit`]: same terminator discipline, same try-region + /// store tracking, no line formatting. + fn push_inst(&mut self, inst: crate::inst::LlInst) { + if self.terminated { + return; + } + if let crate::inst::LlInst::Store { ptr, .. } = &inst { + self.counter.note_store_ptr(ptr); + } + self.instructions.push(inst); + } + fn emit(&mut self, line: impl Into) { // Never emit instructions after a terminator — LLVM rejects them and // the symptom is a confusing `clang` parse error many lines later. @@ -290,72 +306,76 @@ impl LlBlock { pub fn fadd(&mut self, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!( - "{} = fadd {}double {}, {}", - r, - self.fp_flags.fmf_prefix(), - a, - b - )); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "fadd", + pre: self.fp_flags.fmf_prefix(), + ty: "double", + a: a.to_string(), + b: b.to_string(), + }); r } pub fn fsub(&mut self, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!( - "{} = fsub {}double {}, {}", - r, - self.fp_flags.fmf_prefix(), - a, - b - )); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "fsub", + pre: self.fp_flags.fmf_prefix(), + ty: "double", + a: a.to_string(), + b: b.to_string(), + }); r } pub fn fmul(&mut self, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!( - "{} = fmul {}double {}, {}", - r, - self.fp_flags.fmf_prefix(), - a, - b - )); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "fmul", + pre: self.fp_flags.fmf_prefix(), + ty: "double", + a: a.to_string(), + b: b.to_string(), + }); r } pub fn fdiv(&mut self, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!( - "{} = fdiv {}double {}, {}", - r, - self.fp_flags.fmf_prefix(), - a, - b - )); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "fdiv", + pre: self.fp_flags.fmf_prefix(), + ty: "double", + a: a.to_string(), + b: b.to_string(), + }); r } pub fn frem(&mut self, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!( - "{} = frem {}double {}, {}", - r, - self.fp_flags.fmf_prefix(), - a, - b - )); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "frem", + pre: self.fp_flags.fmf_prefix(), + ty: "double", + a: a.to_string(), + b: b.to_string(), + }); r } pub fn fneg(&mut self, a: &str) -> String { let r = self.reg(); - self.emit(format!( - "{} = fneg {}double {}", - r, - self.fp_flags.fmf_prefix(), - a - )); + self.push_inst(crate::inst::LlInst::FNeg { + dst: r.clone(), + pre: self.fp_flags.fmf_prefix(), + a: a.to_string(), + }); r } @@ -365,61 +385,120 @@ impl LlBlock { /// `ogt`, `oge`, `oeq`, `one`, `ord`, `uno`, … pub fn fcmp(&mut self, cond: &str, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = fcmp {} double {}, {}", r, cond, a, b)); + self.push_inst(crate::inst::LlInst::FCmp { + dst: r.clone(), + pred: cond.to_string(), + a: a.to_string(), + b: b.to_string(), + }); r } pub fn icmp_eq(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = icmp eq {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::ICmp { + dst: r.clone(), + pred: "eq", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn icmp_ne(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = icmp ne {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::ICmp { + dst: r.clone(), + pred: "ne", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn icmp_slt(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = icmp slt {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::ICmp { + dst: r.clone(), + pred: "slt", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn icmp_sgt(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = icmp sgt {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::ICmp { + dst: r.clone(), + pred: "sgt", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn icmp_sle(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = icmp sle {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::ICmp { + dst: r.clone(), + pred: "sle", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn icmp_ult(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = icmp ult {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::ICmp { + dst: r.clone(), + pred: "ult", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn icmp_ule(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = icmp ule {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::ICmp { + dst: r.clone(), + pred: "ule", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn icmp_ugt(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = icmp ugt {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::ICmp { + dst: r.clone(), + pred: "ugt", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn icmp_sge(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = icmp sge {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::ICmp { + dst: r.clone(), + pred: "sge", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } @@ -427,22 +506,29 @@ impl LlBlock { pub fn alloca(&mut self, ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = alloca {}", r, ty)); + self.push_inst(crate::inst::LlInst::Alloca { dst: r.clone(), ty }); r } pub fn load(&mut self, ty: LlvmType, ptr: &str) -> String { let r = self.reg(); - self.emit(format!("{} = load {}, ptr {}", r, ty, ptr)); + self.push_inst(crate::inst::LlInst::Load { + dst: r.clone(), + ty, + ptr: ptr.to_string(), + flavor: crate::inst::LoadFlavor::Plain, + }); r } pub fn load_aligned(&mut self, ty: LlvmType, ptr: &str, alignment: u32) -> String { let r = self.reg(); - self.emit(format!( - "{} = load {}, ptr {}, align {}", - r, ty, ptr, alignment - )); + self.push_inst(crate::inst::LlInst::Load { + dst: r.clone(), + ty, + ptr: ptr.to_string(), + flavor: crate::inst::LoadFlavor::Aligned(alignment), + }); r } @@ -451,7 +537,12 @@ impl LlBlock { /// that may be written by `optnone` functions. pub fn load_volatile(&mut self, ty: LlvmType, ptr: &str) -> String { let r = self.reg(); - self.emit(format!("{} = load volatile {}, ptr {}", r, ty, ptr)); + self.push_inst(crate::inst::LlInst::Load { + dst: r.clone(), + ty, + ptr: ptr.to_string(), + flavor: crate::inst::LoadFlavor::Volatile, + }); r } @@ -459,10 +550,12 @@ impl LlBlock { /// atomics. The explicit alignment is required by LLVM atomic loads. pub fn load_atomic_seq_cst(&mut self, ty: LlvmType, ptr: &str, alignment: u32) -> String { let r = self.reg(); - self.emit(format!( - "{} = load atomic {}, ptr {} seq_cst, align {}", - r, ty, ptr, alignment - )); + self.push_inst(crate::inst::LlInst::Load { + dst: r.clone(), + ty, + ptr: ptr.to_string(), + flavor: crate::inst::LoadFlavor::AtomicSeqCst(alignment), + }); r } @@ -479,28 +572,45 @@ impl LlBlock { /// memory changes. pub fn load_invariant(&mut self, ty: LlvmType, ptr: &str) -> String { let r = self.reg(); - self.emit(format!( - "{} = load {}, ptr {}, !invariant.load !0", - r, ty, ptr - )); + self.push_inst(crate::inst::LlInst::Load { + dst: r.clone(), + ty, + ptr: ptr.to_string(), + flavor: crate::inst::LoadFlavor::Invariant, + }); r } pub fn store(&mut self, ty: LlvmType, val: &str, ptr: &str) { - self.emit(format!("store {} {}, ptr {}", ty, val, ptr)); + self.push_inst(crate::inst::LlInst::Store { + ty, + val: val.to_string(), + ptr: ptr.to_string(), + volatile: false, + align: None, + }); } pub fn store_aligned(&mut self, ty: LlvmType, val: &str, ptr: &str, alignment: u32) { - self.emit(format!( - "store {} {}, ptr {}, align {}", - ty, val, ptr, alignment - )); + self.push_inst(crate::inst::LlInst::Store { + ty, + val: val.to_string(), + ptr: ptr.to_string(), + volatile: false, + align: Some(alignment), + }); } /// Store with `volatile` — prevents optimizer from eliminating or /// reordering. Used for module globals. pub fn store_volatile(&mut self, ty: LlvmType, val: &str, ptr: &str) { - self.emit(format!("store volatile {} {}, ptr {}", ty, val, ptr)); + self.push_inst(crate::inst::LlInst::Store { + ty, + val: val.to_string(), + ptr: ptr.to_string(), + volatile: true, + align: None, + }); } // -------- Conversions / bitcasts -------- @@ -513,7 +623,13 @@ impl LlBlock { return src.clone(); } let r = self.reg(); - self.emit(format!("{} = bitcast i64 {} to double", r, val)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "bitcast", + from: "i64", + v: val.to_string(), + to: "double", + }); if !self.terminated { self.double_from_i64.insert(r.clone(), val.to_string()); } @@ -527,7 +643,13 @@ impl LlBlock { return src.clone(); } let r = self.reg(); - self.emit(format!("{} = bitcast double {} to i64", r, val)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "bitcast", + from: "double", + v: val.to_string(), + to: "i64", + }); if !self.terminated { self.i64_from_double.insert(r.clone(), val.to_string()); } @@ -536,37 +658,73 @@ impl LlBlock { pub fn sitofp(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = sitofp {} {} to {}", r, from_ty, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "sitofp", + from: from_ty, + v: val.to_string(), + to: to_ty, + }); r } pub fn uitofp(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = uitofp {} {} to {}", r, from_ty, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "uitofp", + from: from_ty, + v: val.to_string(), + to: to_ty, + }); r } pub fn fpext(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = fpext {} {} to {}", r, from_ty, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "fpext", + from: from_ty, + v: val.to_string(), + to: to_ty, + }); r } pub fn fptrunc(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = fptrunc {} {} to {}", r, from_ty, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "fptrunc", + from: from_ty, + v: val.to_string(), + to: to_ty, + }); r } pub fn fptosi(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = fptosi {} {} to {}", r, from_ty, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "fptosi", + from: from_ty, + v: val.to_string(), + to: to_ty, + }); r } pub fn fptoui(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = fptoui {} {} to {}", r, from_ty, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "fptoui", + from: from_ty, + v: val.to_string(), + to: to_ty, + }); r } @@ -614,10 +772,12 @@ impl LlBlock { // have it (all Apple Silicon); the tower remains the portable path. if crate::codegen::helpers::jscvt_enabled() { let r = self.reg(); - self.emit(format!( - "{} = call i32 @llvm.aarch64.fjcvtzs(double {})", - r, val - )); + self.push_inst(crate::inst::LlInst::Call { + dst: Some(r.clone()), + ret: "i32", + callee: "llvm.aarch64.fjcvtzs".to_string(), + args: vec![("double", val.to_string())], + }); return r; } let bits = self.bitcast_double_to_i64(val); @@ -662,25 +822,49 @@ impl LlBlock { pub fn trunc(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = trunc {} {} to {}", r, from_ty, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "trunc", + from: from_ty, + v: val.to_string(), + to: to_ty, + }); r } pub fn zext(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = zext {} {} to {}", r, from_ty, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "zext", + from: from_ty, + v: val.to_string(), + to: to_ty, + }); r } pub fn sext(&mut self, from_ty: LlvmType, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = sext {} {} to {}", r, from_ty, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "sext", + from: from_ty, + v: val.to_string(), + to: to_ty, + }); r } pub fn inttoptr(&mut self, from_ty: LlvmType, val: &str) -> String { let r = self.reg(); - self.emit(format!("{} = inttoptr {} {} to ptr", r, from_ty, val)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "inttoptr", + from: from_ty, + v: val.to_string(), + to: "ptr", + }); r } @@ -710,10 +894,14 @@ impl LlBlock { // Map bad pointers to a known-safe global that contains 0. let safe_ptr = { let r = self.reg(); - self.emit(format!( - "{} = select i1 {}, ptr @perry_null_guard_zero, ptr {}", - r, is_bad, handle_ptr - )); + self.push_inst(crate::inst::LlInst::Select { + dst: r.clone(), + cond_ty: "i1", + cond: is_bad.clone(), + ty: "ptr", + a: "@perry_null_guard_zero".to_string(), + b: handle_ptr.clone(), + }); r }; // NOTE: must NOT use `!invariant.load` here. This helper is the @@ -732,7 +920,13 @@ impl LlBlock { pub fn ptrtoint(&mut self, val: &str, to_ty: LlvmType) -> String { let r = self.reg(); - self.emit(format!("{} = ptrtoint ptr {} to {}", r, val, to_ty)); + self.push_inst(crate::inst::LlInst::Cast { + dst: r.clone(), + op: "ptrtoint", + from: "ptr", + v: val.to_string(), + to: to_ty, + }); r } @@ -740,19 +934,40 @@ impl LlBlock { pub fn add(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = add {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "add", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn sub(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = sub {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "sub", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn mul(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = mul {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "mul", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } @@ -761,7 +976,14 @@ impl LlBlock { /// `frem double` lowers to on ARM. pub fn srem(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = srem {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "srem", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } @@ -769,43 +991,92 @@ impl LlBlock { /// division paths; JS `/` currently lowers through double division. pub fn sdiv(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = sdiv {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "sdiv", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn and(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = and {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "and", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn or(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = or {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "or", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn xor(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = xor {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "xor", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn shl(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = shl {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "shl", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn ashr(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = ashr {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "ashr", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } pub fn lshr(&mut self, ty: LlvmType, a: &str, b: &str) -> String { let r = self.reg(); - self.emit(format!("{} = lshr {} {}, {}", r, ty, a, b)); + self.push_inst(crate::inst::LlInst::Bin { + dst: r.clone(), + op: "lshr", + pre: "", + ty, + a: a.to_string(), + b: b.to_string(), + }); r } @@ -820,10 +1091,14 @@ impl LlBlock { false_val: &str, ) -> String { let r = self.reg(); - self.emit(format!( - "{} = select {} {}, {} {}, {} {}", - r, cond_ty, cond, ty, true_val, ty, false_val - )); + self.push_inst(crate::inst::LlInst::Select { + dst: r.clone(), + cond_ty, + cond: cond.to_string(), + ty, + a: true_val.to_string(), + b: false_val.to_string(), + }); r } @@ -835,19 +1110,24 @@ impl LlBlock { // codegen finishes to auto-link the providing crate. crate::ext_registry::record_ffi_call(func_name); let r = self.reg(); - let arg_str = format_args(args); - self.emit(format!( - "{} = call {} @{}({})", - r, ret_ty, func_name, arg_str - )); + self.push_inst(crate::inst::LlInst::Call { + dst: Some(r.clone()), + ret: ret_ty, + callee: func_name.to_string(), + args: args.iter().map(|(t, v)| (*t, v.to_string())).collect(), + }); r } pub fn call_void(&mut self, func_name: &str, args: &[(LlvmType, &str)]) { // #835 + #846: same registry hook as `call` — see comment there. crate::ext_registry::record_ffi_call(func_name); - let arg_str = format_args(args); - self.emit(format!("call void @{}({})", func_name, arg_str)); + self.push_inst(crate::inst::LlInst::Call { + dst: None, + ret: "void", + callee: func_name.to_string(), + args: args.iter().map(|(t, v)| (*t, v.to_string())).collect(), + }); } /// Empty inline-asm barrier (`call void asm sideeffect "", ""()`). @@ -859,7 +1139,7 @@ impl LlBlock { /// `for (let i=0;i String { let r = self.reg(); - let arg_str = format_args(args); - let param_types: Vec<&str> = args.iter().map(|(t, _)| *t).collect(); - self.emit(format!( - "{} = call {} ({})* {}({})", - r, - ret_ty, - param_types.join(", "), - fn_ptr, - arg_str - )); + self.push_inst(crate::inst::LlInst::CallIndirect { + dst: r.clone(), + ret: ret_ty, + fptr: fn_ptr.to_string(), + args: args.iter().map(|(t, v)| (*t, v.to_string())).collect(), + }); r } // -------- Control flow -------- pub fn br(&mut self, target: &str) { - self.emit(format!("br label %{}", target)); + self.push_inst(crate::inst::LlInst::Br { + label: target.to_string(), + }); self.terminated = true; } pub fn cond_br(&mut self, cond: &str, true_label: &str, false_label: &str) { - self.emit(format!( - "br i1 {}, label %{}, label %{}", - cond, true_label, false_label - )); + self.push_inst(crate::inst::LlInst::CondBr { + cond: cond.to_string(), + t: true_label.to_string(), + f: false_label.to_string(), + }); self.terminated = true; } pub fn ret(&mut self, ty: LlvmType, val: &str) { - self.emit(format!("ret {} {}", ty, val)); + self.push_inst(crate::inst::LlInst::Ret { + ty, + val: val.to_string(), + }); self.terminated = true; } pub fn ret_void(&mut self) { - self.emit("ret void"); + self.push_inst(crate::inst::LlInst::RetVoid); self.terminated = true; } pub fn unreachable(&mut self) { - self.emit("unreachable"); + self.push_inst(crate::inst::LlInst::Unreachable); self.terminated = true; } @@ -916,15 +1198,13 @@ impl LlBlock { pub fn gep(&mut self, base_ty: LlvmType, ptr: &str, indices: &[(LlvmType, &str)]) -> String { let r = self.reg(); - let idx_str = indices - .iter() - .map(|(t, v)| format!("{} {}", t, v)) - .collect::>() - .join(", "); - self.emit(format!( - "{} = getelementptr {}, ptr {}, {}", - r, base_ty, ptr, idx_str - )); + self.push_inst(crate::inst::LlInst::Gep { + dst: r.clone(), + inbounds: false, + ty: base_ty, + ptr: ptr.to_string(), + idxs: indices.iter().map(|(t, v)| (*t, v.to_string())).collect(), + }); r } @@ -940,26 +1220,26 @@ impl LlBlock { indices: &[(LlvmType, &str)], ) -> String { let r = self.reg(); - let idx_str = indices - .iter() - .map(|(t, v)| format!("{} {}", t, v)) - .collect::>() - .join(", "); - self.emit(format!( - "{} = getelementptr inbounds {}, ptr {}, {}", - r, base_ty, ptr, idx_str - )); + self.push_inst(crate::inst::LlInst::Gep { + dst: r.clone(), + inbounds: true, + ty: base_ty, + ptr: ptr.to_string(), + idxs: indices.iter().map(|(t, v)| (*t, v.to_string())).collect(), + }); r } pub fn phi(&mut self, ty: LlvmType, incoming: &[(&str, &str)]) -> String { let r = self.reg(); - let pairs = incoming - .iter() - .map(|(val, label)| format!("[ {}, %{} ]", val, label)) - .collect::>() - .join(", "); - self.emit(format!("{} = phi {} {}", r, ty, pairs)); + self.push_inst(crate::inst::LlInst::Phi { + dst: r.clone(), + ty, + pairs: incoming + .iter() + .map(|(v, l)| (v.to_string(), l.to_string())) + .collect(), + }); r } diff --git a/crates/perry-codegen/src/inst.rs b/crates/perry-codegen/src/inst.rs index 7c9196c9c2..1ada483767 100644 --- a/crates/perry-codegen/src/inst.rs +++ b/crates/perry-codegen/src/inst.rs @@ -1,42 +1,366 @@ //! Typed instruction storage for `LlBlock` (exp/llvm-inprocess, Phase 2b). //! -//! `Raw` carries a pre-rendered line exactly as the string emitter produced -//! it (two-space indent included), so introducing this enum changes zero -//! bytes of rendered IR — the migration gate. Typed variants land -//! opcode-by-opcode as `block.rs`'s semantic methods move off `format!`; -//! each variant must (1) render byte-identically to what the method -//! previously formatted and (2) be constructible natively by `dialect`'s -//! builder without a text round-trip. `PERRY_LLVM_INPROCESS=diff`'s -//! object-byte verdict gates every step; the raw-vs-typed instruction -//! counts are the migration ratchet. +//! Every variant renders byte-identically to the `format!` string the +//! corresponding `block.rs` semantic method used to emit — the migration +//! gate is the full unit suite (which pins exact rendered IR) plus +//! `PERRY_LLVM_INPROCESS=diff`'s object-byte verdict. `Raw` remains the +//! carrier for the `emit_raw` escape hatch (89 call sites of bespoke +//! shapes); typed variants are constructed natively by `dialect.rs` without +//! any per-line text, and the per-module raw-vs-typed counts are the +//! migration ratchet. +//! +//! Operands stay in the emitter's existing currency — register-name / +//! literal token strings — so lowering code is untouched by the migration; +//! what disappears is the line formatting and the line re-parsing. + +use crate::types::LlvmType; + +pub enum LoadFlavor { + Plain, + Aligned(u32), + Volatile, + AtomicSeqCst(u32), + /// `!invariant.load !0` tagged (issue #52). + Invariant, +} pub enum LlInst { /// Pre-rendered instruction line, two-space indent included. Raw(String), + /// Binary op: `dst =
 a, b`. `pre` is the fast-math
+    /// prefix for fp ops (`"reassoc contract "` etc., trailing space
+    /// included) and `""` for integer/bit ops.
+    Bin {
+        dst: String,
+        op: &'static str,
+        pre: &'static str,
+        ty: LlvmType,
+        a: String,
+        b: String,
+    },
+    FNeg {
+        dst: String,
+        pre: &'static str,
+        a: String,
+    },
+    FCmp {
+        dst: String,
+        pred: String,
+        a: String,
+        b: String,
+    },
+    ICmp {
+        dst: String,
+        pred: &'static str,
+        ty: LlvmType,
+        a: String,
+        b: String,
+    },
+    Alloca {
+        dst: String,
+        ty: LlvmType,
+    },
+    Load {
+        dst: String,
+        ty: LlvmType,
+        ptr: String,
+        flavor: LoadFlavor,
+    },
+    Store {
+        ty: LlvmType,
+        val: String,
+        ptr: String,
+        volatile: bool,
+        align: Option,
+    },
+    /// All `X to Y` conversions: bitcast, trunc/zext/sext, fp<->int, ptr<->int.
+    Cast {
+        dst: String,
+        op: &'static str,
+        from: LlvmType,
+        v: String,
+        to: LlvmType,
+    },
+    Select {
+        dst: String,
+        cond_ty: LlvmType,
+        cond: String,
+        ty: LlvmType,
+        a: String,
+        b: String,
+    },
+    /// Direct call `@callee` (name WITHOUT the `@`). `dst: None` renders the
+    /// value-less form (`call void ...` and friends).
+    Call {
+        dst: Option,
+        ret: LlvmType,
+        callee: String,
+        args: Vec<(LlvmType, String)>,
+    },
+    /// Pre-opaque-pointer indirect call, rendered `(T1, T2)*` exactly as the
+    /// text emitter always has.
+    CallIndirect {
+        dst: String,
+        ret: LlvmType,
+        fptr: String,
+        args: Vec<(LlvmType, String)>,
+    },
+    /// `call void asm sideeffect "", ""()` — the loop-preservation barrier.
+    AsmBarrier,
+    Br {
+        label: String,
+    },
+    CondBr {
+        cond: String,
+        t: String,
+        f: String,
+    },
+    Ret {
+        ty: LlvmType,
+        val: String,
+    },
+    RetVoid,
+    Unreachable,
+    Gep {
+        dst: String,
+        inbounds: bool,
+        ty: LlvmType,
+        ptr: String,
+        idxs: Vec<(LlvmType, String)>,
+    },
+    Phi {
+        dst: String,
+        ty: LlvmType,
+        /// (value, block-label-without-%) pairs.
+        pairs: Vec<(String, String)>,
+    },
 }
 
 impl LlInst {
-    /// Append the rendered line (no trailing newline) to `out`.
+    /// Append the rendered line (no trailing newline) to `out`. Must stay
+    /// byte-identical to the `format!` the emitting method used — the unit
+    /// suite pins this.
     pub fn render_into(&self, out: &mut String) {
+        use std::fmt::Write;
         match self {
             LlInst::Raw(s) => out.push_str(s),
+            LlInst::Bin {
+                dst,
+                op,
+                pre,
+                ty,
+                a,
+                b,
+            } => {
+                let _ = write!(out, "  {dst} = {op} {pre}{ty} {a}, {b}");
+            }
+            LlInst::FNeg { dst, pre, a } => {
+                let _ = write!(out, "  {dst} = fneg {pre}double {a}");
+            }
+            LlInst::FCmp { dst, pred, a, b } => {
+                let _ = write!(out, "  {dst} = fcmp {pred} double {a}, {b}");
+            }
+            LlInst::ICmp {
+                dst,
+                pred,
+                ty,
+                a,
+                b,
+            } => {
+                let _ = write!(out, "  {dst} = icmp {pred} {ty} {a}, {b}");
+            }
+            LlInst::Alloca { dst, ty } => {
+                let _ = write!(out, "  {dst} = alloca {ty}");
+            }
+            LlInst::Load {
+                dst,
+                ty,
+                ptr,
+                flavor,
+            } => match flavor {
+                LoadFlavor::Plain => {
+                    let _ = write!(out, "  {dst} = load {ty}, ptr {ptr}");
+                }
+                LoadFlavor::Aligned(n) => {
+                    let _ = write!(out, "  {dst} = load {ty}, ptr {ptr}, align {n}");
+                }
+                LoadFlavor::Volatile => {
+                    let _ = write!(out, "  {dst} = load volatile {ty}, ptr {ptr}");
+                }
+                LoadFlavor::AtomicSeqCst(n) => {
+                    let _ = write!(
+                        out,
+                        "  {dst} = load atomic {ty}, ptr {ptr} seq_cst, align {n}"
+                    );
+                }
+                LoadFlavor::Invariant => {
+                    let _ = write!(out, "  {dst} = load {ty}, ptr {ptr}, !invariant.load !0");
+                }
+            },
+            LlInst::Store {
+                ty,
+                val,
+                ptr,
+                volatile,
+                align,
+            } => {
+                if *volatile {
+                    let _ = write!(out, "  store volatile {ty} {val}, ptr {ptr}");
+                } else {
+                    let _ = write!(out, "  store {ty} {val}, ptr {ptr}");
+                }
+                if let Some(n) = align {
+                    let _ = write!(out, ", align {n}");
+                }
+            }
+            LlInst::Cast {
+                dst,
+                op,
+                from,
+                v,
+                to,
+            } => {
+                let _ = write!(out, "  {dst} = {op} {from} {v} to {to}");
+            }
+            LlInst::Select {
+                dst,
+                cond_ty,
+                cond,
+                ty,
+                a,
+                b,
+            } => {
+                let _ = write!(out, "  {dst} = select {cond_ty} {cond}, {ty} {a}, {ty} {b}");
+            }
+            LlInst::Call {
+                dst,
+                ret,
+                callee,
+                args,
+            } => {
+                out.push_str("  ");
+                if let Some(d) = dst {
+                    let _ = write!(out, "{d} = ");
+                }
+                let _ = write!(out, "call {ret} @{callee}(");
+                push_args(out, args);
+                out.push(')');
+            }
+            LlInst::CallIndirect {
+                dst,
+                ret,
+                fptr,
+                args,
+            } => {
+                let _ = write!(out, "  {dst} = call {ret} (");
+                for (i, (t, _)) in args.iter().enumerate() {
+                    if i > 0 {
+                        out.push_str(", ");
+                    }
+                    out.push_str(t);
+                }
+                let _ = write!(out, ")* {fptr}(");
+                push_args(out, args);
+                out.push(')');
+            }
+            LlInst::AsmBarrier => {
+                out.push_str("  call void asm sideeffect \"\", \"\"()");
+            }
+            LlInst::Br { label } => {
+                let _ = write!(out, "  br label %{label}");
+            }
+            LlInst::CondBr { cond, t, f } => {
+                let _ = write!(out, "  br i1 {cond}, label %{t}, label %{f}");
+            }
+            LlInst::Ret { ty, val } => {
+                let _ = write!(out, "  ret {ty} {val}");
+            }
+            LlInst::RetVoid => out.push_str("  ret void"),
+            LlInst::Unreachable => out.push_str("  unreachable"),
+            LlInst::Gep {
+                dst,
+                inbounds,
+                ty,
+                ptr,
+                idxs,
+            } => {
+                let kw = if *inbounds {
+                    "getelementptr inbounds"
+                } else {
+                    "getelementptr"
+                };
+                let _ = write!(out, "  {dst} = {kw} {ty}, ptr {ptr}, ");
+                push_args(out, idxs);
+            }
+            LlInst::Phi { dst, ty, pairs } => {
+                let _ = write!(out, "  {dst} = phi {ty} ");
+                for (i, (v, l)) in pairs.iter().enumerate() {
+                    if i > 0 {
+                        out.push_str(", ");
+                    }
+                    let _ = write!(out, "[ {v}, %{l} ]");
+                }
+            }
         }
     }
 
-    /// Rendered byte length, excluding the trailing newline. Keeps
-    /// `estimated_ir_bytes` (codegen-unit balancing, #5391) render-free.
+    /// Rendered byte length, excluding the trailing newline. Exact — the
+    /// codegen-unit balancer (#5391) partitions on these sums, and an
+    /// estimate that drifted would change the DEFAULT path's unit split.
     pub fn text_len(&self) -> usize {
         match self {
             LlInst::Raw(s) => s.len(),
+            _ => {
+                thread_local! {
+                    static SCRATCH: std::cell::RefCell =
+                        std::cell::RefCell::new(String::with_capacity(128));
+                }
+                SCRATCH.with(|s| {
+                    let mut s = s.borrow_mut();
+                    s.clear();
+                    self.render_into(&mut s);
+                    s.len()
+                })
+            }
         }
     }
 
-    /// The rendered line for text-scanning consumers
-    /// (`contains_gc_unsafe_call`). Typed variants must answer such
-    /// predicates structurally rather than growing a renderer here.
+    /// The rendered line for text-scanning consumers that only make sense
+    /// on raw lines. Typed variants answer predicates structurally
+    /// (see `LlBlock::contains_gc_unsafe_call`).
     pub fn scan_str(&self) -> &str {
         match self {
             LlInst::Raw(s) => s,
+            _ => "",
+        }
+    }
+
+    /// True if this is a call into the perry runtime (anything that could
+    /// allocate / trigger GC): not an `@llvm.*` intrinsic, not the inline-asm
+    /// barrier. Mirrors the historical string scan in
+    /// `contains_gc_unsafe_call` exactly.
+    pub fn is_gc_unsafe_call(&self) -> bool {
+        match self {
+            LlInst::Raw(s) => {
+                let Some(pos) = s.find("call ") else {
+                    return false;
+                };
+                let callee = &s[pos..];
+                !callee.contains("@llvm.") && !callee.contains(" asm ")
+            }
+            LlInst::Call { callee, .. } => !callee.starts_with("llvm."),
+            LlInst::CallIndirect { .. } => true,
+            _ => false,
+        }
+    }
+}
+
+fn push_args(out: &mut String, args: &[(LlvmType, String)]) {
+    use std::fmt::Write;
+    for (i, (t, v)) in args.iter().enumerate() {
+        if i > 0 {
+            out.push_str(", ");
         }
+        let _ = write!(out, "{t} {v}");
     }
 }

From 1d6af8f20ebc7e1f8b9fd9e6278e9bd52ac79554 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ralph=20K=C3=BCpper?= 
Date: Mon, 3 Aug 2026 10:17:21 +0200
Subject: [PATCH 20/26] =?UTF-8?q?exp:=20typed=20dispatch=20=E2=80=94=20typ?=
 =?UTF-8?q?ed=20instructions=20construct=20with=20zero=20text?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

FnStream::item consumes FinalItem::Inst directly: every typed variant
builds through the C API with no line formatting and no parsing; only
labels, entry splices, ret-rewrite lines and Raw payloads remain text.
for_each_final_line is now a rendering adapter over for_each_final_item
so the two consumers cannot drift. Parser and typed paths both honor
!invariant.load (the parser silently dropped it before). finish()
returns (typed, raw) counts — the ratchet. Gates: 528 unit tests;
=diff object bytes identical on both corpora through the typed path.

Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo
---
 crates/perry-codegen/src/dialect.rs     | 547 +++++++++++++++++++++++-
 crates/perry-codegen/src/function.rs    | 146 +++++--
 crates/perry-codegen/src/native_emit.rs |  19 +-
 3 files changed, 660 insertions(+), 52 deletions(-)

diff --git a/crates/perry-codegen/src/dialect.rs b/crates/perry-codegen/src/dialect.rs
index 2bfca66de6..c6e81dad96 100644
--- a/crates/perry-codegen/src/dialect.rs
+++ b/crates/perry-codegen/src/dialect.rs
@@ -78,7 +78,22 @@ impl<'ctx, 'm> FnStream<'ctx, 'm> {
             .with_context(|| format!("in line: {t}"))
     }
 
-    pub(crate) fn finish(self) -> Result {
+    /// Consume one finalized item — the native fast path. Typed
+    /// instructions construct directly; only labels, splices, and `Raw`
+    /// payloads go through the line reader.
+    pub(crate) fn item(&mut self, item: &crate::function::FinalItem<'_>) -> Result<()> {
+        use crate::function::FinalItem as FI;
+        match item {
+            FI::Label(l) => self.inner.enter_block(l),
+            FI::Blank => Ok(()),
+            FI::Text(t) => self.line(t),
+            FI::Inst(crate::inst::LlInst::Raw(s)) => self.line(s),
+            FI::Inst(i) => self.inner.typed(i),
+        }
+    }
+
+    /// Returns `(typed, raw)` instruction counts — the migration ratchet.
+    pub(crate) fn finish(self) -> Result<(usize, usize)> {
         self.inner.finish()
     }
 }
@@ -96,7 +111,7 @@ pub(crate) fn add_function_from_text<'ctx>(
     for line in lines {
         stream.line(line)?;
     }
-    stream.finish()
+    stream.finish().map(|(t, r)| t + r)
 }
 
 struct FnReader<'ctx, 'm> {
@@ -129,7 +144,8 @@ struct FnReader<'ctx, 'm> {
     /// branch created the block object earlier.
     last_entered: Option>,
     positioned: bool,
-    count: usize,
+    raw_count: usize,
+    typed_count: usize,
 }
 
 /// Pieces of a `define [linkage] RET @NAME(T %p, ...) [attrs] {` line.
@@ -277,7 +293,8 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> {
             placeholders: HashMap::new(),
             last_entered: None,
             positioned: false,
-            count: 0,
+            raw_count: 0,
+            typed_count: 0,
         })
     }
 
@@ -353,7 +370,7 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> {
         if !self.positioned {
             bail!("instruction before first block label");
         }
-        self.count += 1;
+        self.raw_count += 1;
         // `%r = op ...` vs bare op.
         if let Some((lhs, rhs)) = t.split_once(" = ") {
             let (op, rest) = rhs
@@ -525,6 +542,11 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> {
         if volatile {
             let _ = v.as_instruction_value().map(|i| i.set_volatile(true));
         }
+        if rest.contains("!invariant.load") {
+            if let Some(i) = v.as_instruction_value() {
+                set_invariant_load(self.ctx, i);
+            }
+        }
         if atomic {
             let ord = match ordering {
                 Some("seq_cst") => {
@@ -988,7 +1010,503 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> {
         Ok(out)
     }
 
-    fn finish(mut self) -> Result {
+    /// Construct one typed instruction directly — the no-text fast path.
+    /// Each arm mirrors the corresponding string-parser arm exactly; the
+    /// parser remains authoritative for `Raw` lines and the corpus tests.
+    fn typed(&mut self, inst: &crate::inst::LlInst) -> Result<()> {
+        use crate::inst::{LlInst as I, LoadFlavor as LF};
+        if !self.positioned {
+            bail!("instruction before first block label");
+        }
+        self.typed_count += 1;
+        match inst {
+            I::Raw(_) => unreachable!("Raw goes through the line reader"),
+            I::Bin {
+                dst,
+                op,
+                pre,
+                ty,
+                a,
+                b,
+            } => {
+                let t = basic_type(self.ctx, ty)?;
+                let av = self.val(t, a)?;
+                let bv = self.val(t, b)?;
+                let name = dst.trim_start_matches('%');
+                let out: BasicValueEnum = match *op {
+                    "add" => self
+                        .builder
+                        .build_int_add(av.into_int_value(), bv.into_int_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "sub" => self
+                        .builder
+                        .build_int_sub(av.into_int_value(), bv.into_int_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "mul" => self
+                        .builder
+                        .build_int_mul(av.into_int_value(), bv.into_int_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "sdiv" => self
+                        .builder
+                        .build_int_signed_div(av.into_int_value(), bv.into_int_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "srem" => self
+                        .builder
+                        .build_int_signed_rem(av.into_int_value(), bv.into_int_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "and" => self
+                        .builder
+                        .build_and(av.into_int_value(), bv.into_int_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "or" => self
+                        .builder
+                        .build_or(av.into_int_value(), bv.into_int_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "xor" => self
+                        .builder
+                        .build_xor(av.into_int_value(), bv.into_int_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "shl" => self
+                        .builder
+                        .build_left_shift(av.into_int_value(), bv.into_int_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "lshr" => self
+                        .builder
+                        .build_right_shift(av.into_int_value(), bv.into_int_value(), false, name)
+                        .map_err(be)?
+                        .into(),
+                    "ashr" => self
+                        .builder
+                        .build_right_shift(av.into_int_value(), bv.into_int_value(), true, name)
+                        .map_err(be)?
+                        .into(),
+                    "fadd" => self
+                        .builder
+                        .build_float_add(av.into_float_value(), bv.into_float_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "fsub" => self
+                        .builder
+                        .build_float_sub(av.into_float_value(), bv.into_float_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "fmul" => self
+                        .builder
+                        .build_float_mul(av.into_float_value(), bv.into_float_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "fdiv" => self
+                        .builder
+                        .build_float_div(av.into_float_value(), bv.into_float_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    "frem" => self
+                        .builder
+                        .build_float_rem(av.into_float_value(), bv.into_float_value(), name)
+                        .map_err(be)?
+                        .into(),
+                    other => bail!("typed Bin: unknown op `{other}`"),
+                };
+                if !pre.is_empty() {
+                    let toks: Vec<&str> = pre.split_whitespace().collect();
+                    apply_flags(out.as_instruction_value(), &toks);
+                }
+                self.def(dst, out)
+            }
+            I::FNeg { dst, pre, a } => {
+                let t = basic_type(self.ctx, "double")?;
+                let av = self.val(t, a)?;
+                let out: BasicValueEnum = self
+                    .builder
+                    .build_float_neg(av.into_float_value(), dst.trim_start_matches('%'))
+                    .map_err(be)?
+                    .into();
+                if !pre.is_empty() {
+                    let toks: Vec<&str> = pre.split_whitespace().collect();
+                    apply_flags(out.as_instruction_value(), &toks);
+                }
+                self.def(dst, out)
+            }
+            I::FCmp { dst, pred, a, b } => {
+                let t = basic_type(self.ctx, "double")?;
+                let av = self.val(t, a)?;
+                let bv = self.val(t, b)?;
+                let out: BasicValueEnum = self
+                    .builder
+                    .build_float_compare(
+                        float_pred(pred)?,
+                        av.into_float_value(),
+                        bv.into_float_value(),
+                        dst.trim_start_matches('%'),
+                    )
+                    .map_err(be)?
+                    .into();
+                self.def(dst, out)
+            }
+            I::ICmp {
+                dst,
+                pred,
+                ty,
+                a,
+                b,
+            } => {
+                let t = basic_type(self.ctx, ty)?;
+                let av = self.val(t, a)?;
+                let bv = self.val(t, b)?;
+                let name = dst.trim_start_matches('%');
+                let out: BasicValueEnum = if av.is_pointer_value() {
+                    self.builder
+                        .build_int_compare(
+                            int_pred(pred)?,
+                            av.into_pointer_value(),
+                            bv.into_pointer_value(),
+                            name,
+                        )
+                        .map_err(be)?
+                        .into()
+                } else {
+                    self.builder
+                        .build_int_compare(
+                            int_pred(pred)?,
+                            av.into_int_value(),
+                            bv.into_int_value(),
+                            name,
+                        )
+                        .map_err(be)?
+                        .into()
+                };
+                self.def(dst, out)
+            }
+            I::Alloca { dst, ty } => {
+                let t = basic_type(self.ctx, ty)?;
+                let out = self
+                    .builder
+                    .build_alloca(t, dst.trim_start_matches('%'))
+                    .map_err(be)?;
+                self.def(dst, out.into())
+            }
+            I::Load {
+                dst,
+                ty,
+                ptr,
+                flavor,
+            } => {
+                let t = basic_type(self.ctx, ty)?;
+                let p = self
+                    .val(self.ctx.ptr_type(AddressSpace::default()).into(), ptr)?
+                    .into_pointer_value();
+                let v = self
+                    .builder
+                    .build_load(t, p, dst.trim_start_matches('%'))
+                    .map_err(be)?;
+                match flavor {
+                    LF::Plain => {}
+                    LF::Aligned(n) => {
+                        let _ = v.as_instruction_value().map(|i| i.set_alignment(*n));
+                    }
+                    LF::Volatile => {
+                        let _ = v.as_instruction_value().map(|i| i.set_volatile(true));
+                    }
+                    LF::AtomicSeqCst(n) => {
+                        if let Some(i) = v.as_instruction_value() {
+                            unsafe {
+                                llvm_sys::core::LLVMSetOrdering(
+                                    i.as_value_ref(),
+                                    llvm_sys::LLVMAtomicOrdering::LLVMAtomicOrderingSequentiallyConsistent,
+                                )
+                            };
+                            let _ = i.set_alignment(*n);
+                        }
+                    }
+                    LF::Invariant => {
+                        if let Some(i) = v.as_instruction_value() {
+                            set_invariant_load(self.ctx, i);
+                        }
+                    }
+                }
+                self.def(dst, v)
+            }
+            I::Store {
+                ty,
+                val,
+                ptr,
+                volatile,
+                align,
+            } => {
+                let t = basic_type(self.ctx, ty)?;
+                let v = self.val(t, val)?;
+                let p = self
+                    .val(self.ctx.ptr_type(AddressSpace::default()).into(), ptr)?
+                    .into_pointer_value();
+                let inst = self.builder.build_store(p, v).map_err(be)?;
+                if *volatile {
+                    let _ = inst.set_volatile(true);
+                }
+                if let Some(n) = align {
+                    let _ = inst.set_alignment(*n);
+                }
+                Ok(())
+            }
+            I::Cast {
+                dst,
+                op,
+                from,
+                v,
+                to,
+            } => {
+                let sty = basic_type(self.ctx, from)?;
+                let sv = self.val(sty, v)?;
+                let dty = basic_type(self.ctx, to)?;
+                let name = dst.trim_start_matches('%');
+                let out: BasicValueEnum = match *op {
+                    "bitcast" => self.builder.build_bit_cast(sv, dty, name).map_err(be)?,
+                    "zext" => self
+                        .builder
+                        .build_int_z_extend(sv.into_int_value(), dty.into_int_type(), name)
+                        .map_err(be)?
+                        .into(),
+                    "sext" => self
+                        .builder
+                        .build_int_s_extend(sv.into_int_value(), dty.into_int_type(), name)
+                        .map_err(be)?
+                        .into(),
+                    "trunc" => self
+                        .builder
+                        .build_int_truncate(sv.into_int_value(), dty.into_int_type(), name)
+                        .map_err(be)?
+                        .into(),
+                    "fptosi" => self
+                        .builder
+                        .build_float_to_signed_int(sv.into_float_value(), dty.into_int_type(), name)
+                        .map_err(be)?
+                        .into(),
+                    "fptoui" => self
+                        .builder
+                        .build_float_to_unsigned_int(
+                            sv.into_float_value(),
+                            dty.into_int_type(),
+                            name,
+                        )
+                        .map_err(be)?
+                        .into(),
+                    "sitofp" => self
+                        .builder
+                        .build_signed_int_to_float(sv.into_int_value(), dty.into_float_type(), name)
+                        .map_err(be)?
+                        .into(),
+                    "uitofp" => self
+                        .builder
+                        .build_unsigned_int_to_float(
+                            sv.into_int_value(),
+                            dty.into_float_type(),
+                            name,
+                        )
+                        .map_err(be)?
+                        .into(),
+                    "fpext" => self
+                        .builder
+                        .build_float_ext(sv.into_float_value(), dty.into_float_type(), name)
+                        .map_err(be)?
+                        .into(),
+                    "fptrunc" => self
+                        .builder
+                        .build_float_trunc(sv.into_float_value(), dty.into_float_type(), name)
+                        .map_err(be)?
+                        .into(),
+                    "ptrtoint" => self
+                        .builder
+                        .build_ptr_to_int(sv.into_pointer_value(), dty.into_int_type(), name)
+                        .map_err(be)?
+                        .into(),
+                    "inttoptr" => self
+                        .builder
+                        .build_int_to_ptr(sv.into_int_value(), dty.into_pointer_type(), name)
+                        .map_err(be)?
+                        .into(),
+                    other => bail!("typed Cast: unknown op `{other}`"),
+                };
+                self.def(dst, out)
+            }
+            I::Select {
+                dst,
+                cond_ty,
+                cond,
+                ty,
+                a,
+                b,
+            } => {
+                let ct = basic_type(self.ctx, cond_ty)?;
+                let cv = self.val(ct, cond)?;
+                let t = basic_type(self.ctx, ty)?;
+                let av = self.val(t, a)?;
+                let bv = self.val(t, b)?;
+                let out = self
+                    .builder
+                    .build_select(cv.into_int_value(), av, bv, dst.trim_start_matches('%'))
+                    .map_err(be)?;
+                self.def(dst, out)
+            }
+            I::Call {
+                dst,
+                ret,
+                callee,
+                args,
+            } => {
+                let mut argv: Vec = Vec::with_capacity(args.len());
+                let mut argtys: Vec =
+                    Vec::with_capacity(args.len());
+                for (t, v) in args {
+                    let bt = basic_type(self.ctx, t)?;
+                    argv.push(self.val(bt, v)?.into());
+                    argtys.push(bt.into());
+                }
+                let fn_ty = fn_type_of(self.ctx, ret, &argtys)?;
+                let f = match self.module.get_function(callee) {
+                    Some(f) => f,
+                    None if callee.starts_with("llvm.") => {
+                        self.module.add_function(callee, fn_ty, None)
+                    }
+                    None => bail!("call to undeclared @{callee}"),
+                };
+                let site = self
+                    .builder
+                    .build_indirect_call(
+                        fn_ty,
+                        f.as_global_value().as_pointer_value(),
+                        &argv,
+                        dst.as_deref()
+                            .map(|d| d.trim_start_matches('%'))
+                            .unwrap_or(""),
+                    )
+                    .map_err(be)?;
+                if let Some(d) = dst {
+                    match site.try_as_basic_value() {
+                        inkwell::values::ValueKind::Basic(v) => self.def(d, v)?,
+                        other => bail!("typed call expected a value, got {other:?}"),
+                    }
+                }
+                Ok(())
+            }
+            I::CallIndirect {
+                dst,
+                ret,
+                fptr,
+                args,
+            } => {
+                let mut argv: Vec = Vec::with_capacity(args.len());
+                let mut argtys: Vec =
+                    Vec::with_capacity(args.len());
+                for (t, v) in args {
+                    let bt = basic_type(self.ctx, t)?;
+                    argv.push(self.val(bt, v)?.into());
+                    argtys.push(bt.into());
+                }
+                let fn_ty = fn_type_of(self.ctx, ret, &argtys)?;
+                let fp = self
+                    .val(self.ctx.ptr_type(AddressSpace::default()).into(), fptr)?
+                    .into_pointer_value();
+                let site = self
+                    .builder
+                    .build_indirect_call(fn_ty, fp, &argv, dst.trim_start_matches('%'))
+                    .map_err(be)?;
+                match site.try_as_basic_value() {
+                    inkwell::values::ValueKind::Basic(v) => self.def(dst, v),
+                    other => bail!("typed indirect call expected a value, got {other:?}"),
+                }
+            }
+            I::AsmBarrier => {
+                let void_fn = self.ctx.void_type().fn_type(&[], false);
+                let ptr = self.ctx.create_inline_asm(
+                    void_fn,
+                    String::new(),
+                    String::new(),
+                    true,
+                    false,
+                    None,
+                    false,
+                );
+                self.builder
+                    .build_indirect_call(void_fn, ptr, &[], "")
+                    .map_err(be)?;
+                Ok(())
+            }
+            I::Br { label } => {
+                let b = self.block(label);
+                self.builder.build_unconditional_branch(b).map_err(be)?;
+                Ok(())
+            }
+            I::CondBr { cond, t, f } => {
+                let cv = self.val(self.ctx.bool_type().into(), cond)?;
+                let tb = self.block(t);
+                let fb = self.block(f);
+                self.builder
+                    .build_conditional_branch(cv.into_int_value(), tb, fb)
+                    .map_err(be)?;
+                Ok(())
+            }
+            I::Ret { ty, val } => {
+                let t = basic_type(self.ctx, ty)?;
+                let v = self.val(t, val)?;
+                self.builder.build_return(Some(&v)).map_err(be)?;
+                Ok(())
+            }
+            I::RetVoid => {
+                self.builder.build_return(None).map_err(be)?;
+                Ok(())
+            }
+            I::Unreachable => {
+                self.builder.build_unreachable().map_err(be)?;
+                Ok(())
+            }
+            I::Gep {
+                dst,
+                inbounds,
+                ty,
+                ptr,
+                idxs,
+            } => {
+                let pointee = basic_type(self.ctx, ty)?;
+                let p = self
+                    .val(self.ctx.ptr_type(AddressSpace::default()).into(), ptr)?
+                    .into_pointer_value();
+                let mut iv = Vec::with_capacity(idxs.len());
+                for (t, v) in idxs {
+                    iv.push(self.val(basic_type(self.ctx, t)?, v)?.into_int_value());
+                }
+                let name = dst.trim_start_matches('%');
+                let out = unsafe {
+                    if *inbounds {
+                        self.builder.build_in_bounds_gep(pointee, p, &iv, name)
+                    } else {
+                        self.builder.build_gep(pointee, p, &iv, name)
+                    }
+                }
+                .map_err(be)?;
+                self.def(dst, out.into())
+            }
+            I::Phi { dst, ty, pairs } => {
+                let t = basic_type(self.ctx, ty)?;
+                let phi = self
+                    .builder
+                    .build_phi(t, dst.trim_start_matches('%'))
+                    .map_err(be)?;
+                self.def(dst, phi.as_basic_value())?;
+                self.pending_phis.push((phi, t, pairs.clone()));
+                Ok(())
+            }
+        }
+    }
+
+    fn finish(mut self) -> Result<(usize, usize)> {
         // Phi incomings resolve against the COMPLETE value map — no
         // placeholders here; an unknown register at this point is a bug.
         for (phi, ty, incs) in std::mem::take(&mut self.pending_phis) {
@@ -1011,10 +1529,25 @@ impl<'ctx, 'm> FnReader<'ctx, 'm> {
         if let Some(name) = self.placeholders.keys().next() {
             bail!("register {name} was used but never defined");
         }
-        Ok(self.count)
+        Ok((self.typed_count, self.raw_count))
     }
 }
 
+/// Tag a load with `!invariant.load !0` (issue #52 semantics). Kind id via
+/// llvm-sys; the node is the empty MDNode, same as the textual `!0 = !{}`.
+fn set_invariant_load(ctx: &Context, inst: InstructionValue<'_>) {
+    use inkwell::context::AsContextRef;
+    let kind = unsafe {
+        llvm_sys::core::LLVMGetMDKindIDInContext(
+            ctx.as_ctx_ref(),
+            b"invariant.load".as_ptr() as *const std::os::raw::c_char,
+            14,
+        )
+    };
+    let node = ctx.metadata_node(&[]);
+    let _ = inst.set_metadata(node, kind);
+}
+
 /// Replace every use of a placeholder with the real definition. A type
 /// mismatch means the operand-context type at the USE disagreed with the
 /// defining instruction — always a reader bug, and silently leaving the
diff --git a/crates/perry-codegen/src/function.rs b/crates/perry-codegen/src/function.rs
index 22cf6ad620..dd2af748fe 100644
--- a/crates/perry-codegen/src/function.rs
+++ b/crates/perry-codegen/src/function.rs
@@ -655,23 +655,45 @@ impl LlFunction {
     pub fn for_each_final_line(
         &self,
         sink: &mut dyn FnMut(&str) -> Result<(), E>,
+    ) -> Result<(), E> {
+        let mut buf = String::new();
+        self.for_each_final_item::(&mut |item| {
+            buf.clear();
+            match item {
+                FinalItem::Label(l) => {
+                    buf.push_str(l);
+                    buf.push(':');
+                }
+                FinalItem::Blank => {}
+                FinalItem::Text(t) => buf.push_str(t),
+                FinalItem::Inst(i) => i.render_into(&mut buf),
+            }
+            sink(&buf)
+        })
+    }
+
+    /// Item-granular twin of [`for_each_final_line`], and the seam the native
+    /// backend consumes: typed instructions arrive as [`FinalItem::Inst`] and
+    /// are constructed directly, with no per-line text; only labels, entry
+    /// splices, synthesized return-site rewrites, and `Raw` payload splits
+    /// arrive as text. The two visitors cannot drift: the line visitor is a
+    /// rendering adapter over this one.
+    pub fn for_each_final_item(
+        &self,
+        sink: &mut dyn FnMut(FinalItem<'_>) -> Result<(), E>,
     ) -> Result<(), E> {
         let rewrite_rets =
             self.shadow_frame_slot.is_some() || !self.pre_return_void_calls.is_empty();
         let mut seq: u32 = 0;
-        let mut line_buf = String::new();
         for (i, blk) in self.blocks.iter().enumerate() {
             if i > 0 {
-                sink("")?;
+                sink(FinalItem::Blank)?;
             }
-            line_buf.clear();
-            line_buf.push_str(&blk.label);
-            line_buf.push(':');
-            sink(&line_buf)?;
+            sink(FinalItem::Label(&blk.label))?;
             let is_entry = i == 0;
             if is_entry {
                 for alloca in &self.entry_allocas {
-                    self.emit_maybe_ret_rewritten(alloca, rewrite_rets, &mut seq, sink)?;
+                    self.text_item(alloca, rewrite_rets, &mut seq, sink)?;
                 }
             }
             let boundary = if is_entry {
@@ -685,63 +707,111 @@ impl LlFunction {
             for inst in blk.insts() {
                 if idx == boundary {
                     for line in &self.entry_post_init_setup {
-                        self.emit_maybe_ret_rewritten(line, rewrite_rets, &mut seq, sink)?;
-                    }
-                }
-                line_buf.clear();
-                inst.render_into(&mut line_buf);
-                // Split multi-line raw payloads exactly like text rendering
-                // followed by the line-based rewrite pass would.
-                if line_buf.contains('\n') {
-                    let whole = std::mem::take(&mut line_buf);
-                    for l in whole.split('\n') {
-                        self.emit_maybe_ret_rewritten(l, rewrite_rets, &mut seq, sink)?;
+                        self.text_item(line, rewrite_rets, &mut seq, sink)?;
                     }
-                } else {
-                    let whole = std::mem::take(&mut line_buf);
-                    self.emit_maybe_ret_rewritten(&whole, rewrite_rets, &mut seq, sink)?;
-                    line_buf = whole;
                 }
+                self.inst_item(inst, rewrite_rets, &mut seq, sink)?;
                 idx += 1;
             }
             if is_entry && idx == boundary {
                 for line in &self.entry_post_init_setup {
-                    self.emit_maybe_ret_rewritten(line, rewrite_rets, &mut seq, sink)?;
+                    self.text_item(line, rewrite_rets, &mut seq, sink)?;
                 }
             }
         }
         Ok(())
     }
 
+    fn inst_item(
+        &self,
+        inst: &crate::inst::LlInst,
+        rewrite_rets: bool,
+        seq: &mut u32,
+        sink: &mut dyn FnMut(FinalItem<'_>) -> Result<(), E>,
+    ) -> Result<(), E> {
+        use crate::inst::LlInst;
+        // Multi-line raw payloads split exactly like text rendering followed
+        // by the line-based rewrite pass would.
+        if let LlInst::Raw(s) = inst {
+            if s.contains('\n') {
+                for l in s.split('\n') {
+                    self.text_item(l, rewrite_rets, seq, sink)?;
+                }
+                return Ok(());
+            }
+        }
+        if rewrite_rets {
+            let is_rewritable_ret = match inst {
+                LlInst::Ret { ty, .. } => *ty != "ptr",
+                LlInst::RetVoid => true,
+                LlInst::Raw(s) => {
+                    let t = s.trim_start();
+                    (t.starts_with("ret ") || t == "ret void") && !t.starts_with("ret ptr ")
+                }
+                _ => false,
+            };
+            if is_rewritable_ret {
+                self.yield_ret_prologue(seq, sink)?;
+            }
+        }
+        sink(FinalItem::Inst(inst))
+    }
+
     /// Return-site rewrite, streamed: before every `ret` (except `ret ptr`),
     /// inject the pre-return void calls and the shadow-frame pop. Byte-equal
     /// to the old whole-text line scan.
-    fn emit_maybe_ret_rewritten(
+    fn text_item(
         &self,
         line: &str,
         rewrite_rets: bool,
         seq: &mut u32,
-        sink: &mut dyn FnMut(&str) -> Result<(), E>,
+        sink: &mut dyn FnMut(FinalItem<'_>) -> Result<(), E>,
     ) -> Result<(), E> {
         if rewrite_rets {
             let trimmed = line.trim_start();
             if (trimmed.starts_with("ret ") || trimmed == "ret void")
                 && !trimmed.starts_with("ret ptr ")
             {
-                for func_name in &self.pre_return_void_calls {
-                    sink(&format!("  call void @{}()", func_name))?;
-                }
-                if let Some(handle_slot) = &self.shadow_frame_slot {
-                    let load_reg = format!("%shadow_pop_l_{}", seq);
-                    *seq += 1;
-                    sink(&format!("  {} = load i64, ptr {}", load_reg, handle_slot))?;
-                    sink(&format!(
-                        "  call void @js_shadow_frame_pop(i64 {})",
-                        load_reg
-                    ))?;
-                }
+                self.yield_ret_prologue(seq, sink)?;
             }
         }
-        sink(line)
+        sink(FinalItem::Text(line))
+    }
+
+    fn yield_ret_prologue(
+        &self,
+        seq: &mut u32,
+        sink: &mut dyn FnMut(FinalItem<'_>) -> Result<(), E>,
+    ) -> Result<(), E> {
+        for func_name in &self.pre_return_void_calls {
+            sink(FinalItem::Text(&format!("  call void @{}()", func_name)))?;
+        }
+        if let Some(handle_slot) = &self.shadow_frame_slot {
+            let load_reg = format!("%shadow_pop_l_{}", seq);
+            *seq += 1;
+            sink(FinalItem::Text(&format!(
+                "  {} = load i64, ptr {}",
+                load_reg, handle_slot
+            )))?;
+            sink(FinalItem::Text(&format!(
+                "  call void @js_shadow_frame_pop(i64 {})",
+                load_reg
+            )))?;
+        }
+        Ok(())
     }
 }
+
+/// One finalized item of a function body. See
+/// [`LlFunction::for_each_final_item`].
+pub enum FinalItem<'a> {
+    /// Block label (no trailing colon).
+    Label(&'a str),
+    /// Blank separator line between blocks.
+    Blank,
+    /// A pre-rendered text line (entry splices, return-site rewrites,
+    /// multi-line raw payload splits).
+    Text(&'a str),
+    /// A typed instruction — the native backend constructs it directly.
+    Inst(&'a crate::inst::LlInst),
+}
diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs
index 0a1b987085..1ca4c43a0e 100644
--- a/crates/perry-codegen/src/native_emit.rs
+++ b/crates/perry-codegen/src/native_emit.rs
@@ -72,7 +72,8 @@ fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result
         skeleton.push_str(&format!("declare {} @{}({})\n", f.return_type, f.name, tys));
     }
     let module = crate::inprocess::parse_ir_text(context, &skeleton, "perry_native_module")?;
-    let mut instructions = 0usize;
+    let mut typed_insts = 0usize;
+    let mut raw_insts = 0usize;
     for f in &funcs {
         let header = synth_define_header(f);
         let mut stream = crate::dialect::FnStream::begin(context, &module, &header)
@@ -92,19 +93,23 @@ fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result
                 })?;
             }
         } else {
-            // The common case: finalized lines stream straight into the
-            // C-API builder — no per-function text exists.
-            f.for_each_final_line::(&mut |line| stream.line(line))
+            // The common case: finalized items stream straight into the
+            // C-API builder — typed instructions carry no text at all.
+            f.for_each_final_item::(&mut |item| stream.item(&item))
                 .map_err(|e| anyhow!("native IR construction failed in @{}: {:#}", f.name, e))?;
         }
-        instructions += stream
+        let (t, r) = stream
             .finish()
             .map_err(|e| anyhow!("native IR construction failed in @{}: {:#}", f.name, e))?;
+        typed_insts += t;
+        raw_insts += r;
     }
     log::debug!(
-        "perry-codegen: native construction built {} functions, {} instructions, skeleton {} bytes",
+        "perry-codegen: native construction built {} functions, {} typed + {} raw instructions \
+         (ratchet: raw -> 0), skeleton {} bytes",
         funcs.len(),
-        instructions,
+        typed_insts,
+        raw_insts,
         skeleton.len()
     );
     Ok(module)

From f8773977ff91961164be1d8b11c27321bfe24394 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ralph=20K=C3=BCpper?= 
Date: Mon, 3 Aug 2026 10:19:25 +0200
Subject: [PATCH 21/26] exp: wire the debug view under native construction
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

PERRY_SAVE_LL (which --trace llvm sets, #7154) and PERRY_LLVM_KEEP_IR
now work under =native/=diff: they print the CONSTRUCTED module — what
LLVM actually verifies and optimizes, construction folds included —
instead of silently no-opping. Filenames mirror the text path's with a
.native infix. This closes the 'debug knobs dead under native' gap: the
in-process no-text pipeline and on-demand .ll dumps are now both flags,
independently switchable.

Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo
---
 crates/perry-codegen/src/codegen/mod.rs | 20 ++++++----
 crates/perry-codegen/src/native_emit.rs | 49 ++++++++++++++++++++++++-
 2 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/crates/perry-codegen/src/codegen/mod.rs b/crates/perry-codegen/src/codegen/mod.rs
index 79208bde05..62833745d1 100644
--- a/crates/perry-codegen/src/codegen/mod.rs
+++ b/crates/perry-codegen/src/codegen/mod.rs
@@ -2618,7 +2618,7 @@ pub fn compile_module(hir: &HirModule, opts: CompileOptions) -> Result>
     // textual); `=diff` builds both arms and diffs them. Unit-split and
     // emit_ir_only paths above stay textual (they fall into the in-process
     // *transport* under these values, so no clang subprocess either way).
-    if let Some(result) = try_native_construction(&llmod, opts.target.as_deref()) {
+    if let Some(result) = try_native_construction(&llmod, opts.target.as_deref(), &module_prefix) {
         return result;
     }
 
@@ -2650,15 +2650,20 @@ pub fn compile_module(hir: &HirModule, opts: CompileOptions) -> Result>
 fn try_native_construction(
     llmod: &crate::module::LlModule,
     target: Option<&str>,
+    module_prefix: &str,
 ) -> Option>> {
     match crate::native_emit::native_mode() {
         crate::native_emit::NativeMode::Off => None,
-        crate::native_emit::NativeMode::Native => {
-            Some(crate::native_emit::compile_module_native(llmod, target))
-        }
-        crate::native_emit::NativeMode::Diff => {
-            Some(crate::native_emit::compile_module_diff(llmod, target))
-        }
+        crate::native_emit::NativeMode::Native => Some(crate::native_emit::compile_module_native(
+            llmod,
+            target,
+            module_prefix,
+        )),
+        crate::native_emit::NativeMode::Diff => Some(crate::native_emit::compile_module_diff(
+            llmod,
+            target,
+            module_prefix,
+        )),
     }
 }
 
@@ -2666,6 +2671,7 @@ fn try_native_construction(
 fn try_native_construction(
     _llmod: &crate::module::LlModule,
     _target: Option<&str>,
+    _module_prefix: &str,
 ) -> Option>> {
     None
 }
diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs
index 1ca4c43a0e..17944b4a4b 100644
--- a/crates/perry-codegen/src/native_emit.rs
+++ b/crates/perry-codegen/src/native_emit.rs
@@ -128,13 +128,53 @@ fn plan_for(llmod: &LlModule, target: Option<&str>) -> (String, Vec) {
     crate::linker::native_plan_args(target, est_bytes, fn_count)
 }
 
-pub fn compile_module_native(llmod: &LlModule, target: Option<&str>) -> Result> {
+pub fn compile_module_native(
+    llmod: &LlModule,
+    target: Option<&str>,
+    module_prefix: &str,
+) -> Result> {
     let context = Context::create();
     let module = build_native_module(&context, llmod)?;
+    debug_dump(&module, module_prefix);
     let (effective_target, args) = plan_for(llmod, target);
     crate::inprocess::optimize_and_emit_module(&module, &effective_target, &args)
 }
 
+/// The debug view under native construction: `PERRY_SAVE_LL=` (which
+/// `--trace llvm` sets, #7154) and `PERRY_LLVM_KEEP_IR` both print the
+/// CONSTRUCTED module — exactly what LLVM will verify and optimize,
+/// including construction-time constant folds — rather than re-rendering
+/// the emitter's text. Filenames mirror the text path's so tooling that
+/// greps the trace dir keeps working; the `.native` infix says which
+/// pipeline produced them.
+fn debug_dump(module: &Module<'_>, module_prefix: &str) {
+    let keep = std::env::var_os("PERRY_LLVM_KEEP_IR").is_some();
+    let save_dir = std::env::var("PERRY_SAVE_LL").ok();
+    if !keep && save_dir.is_none() {
+        return;
+    }
+    let printed = module.print_to_string().to_string();
+    if let Some(dir) = save_dir {
+        let path = format!("{}/{}.native.ll", dir, module_prefix);
+        if std::fs::write(&path, &printed).is_ok() {
+            eprintln!("[perry-codegen] saved native-construction IR: {path}");
+        }
+    }
+    if keep {
+        let path = std::env::temp_dir().join(format!(
+            "perry_native_{}_{}.ll",
+            module_prefix,
+            std::process::id()
+        ));
+        if std::fs::write(&path, &printed).is_ok() {
+            eprintln!(
+                "[perry-codegen] kept LLVM IR (native construction): {}",
+                path.display()
+            );
+        }
+    }
+}
+
 /// Differential harness: text-parsed arm vs natively-built arm, same LLVM,
 /// same plan. The verdict is **emitted object bytes** — the C-API builder
 /// constant-folds at construction (`zext i1 false`, `select i1 false, ...`),
@@ -143,7 +183,11 @@ pub fn compile_module_native(llmod: &LlModule, target: Option<&str>) -> Result) -> Result> {
+pub fn compile_module_diff(
+    llmod: &LlModule,
+    target: Option<&str>,
+    module_prefix: &str,
+) -> Result> {
     let text = llmod.to_ir();
     let ctx_text = Context::create();
     let m_text = crate::inprocess::parse_ir_text(&ctx_text, &text, "perry_native_module")?;
@@ -157,6 +201,7 @@ pub fn compile_module_diff(llmod: &LlModule, target: Option<&str>) -> Result {
+            debug_dump(&m_native, module_prefix);
             // Capture pre-opt prints BEFORE optimization mutates the modules;
             // they are the localization artifact when bytes mismatch.
             let dump_dir = std::env::var("PERRY_LLVM_DIFF_DIR").ok();

From ec26e954fe6462c4a3e68eb4230ab67d81b86620 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ralph=20K=C3=BCpper?= 
Date: Mon, 3 Aug 2026 10:25:40 +0200
Subject: [PATCH 22/26] exp: native construction for codegen-unit splits
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

LlModule::codegen_unit_parts extracts the #5391 partition (greedy
size-balanced buckets + per-unit skeleton) with render_codegen_units as
a thin text renderer over it (existing unit tests pin the bytes).
compile_module_units_native builds each unit as its own context+module —
same peak-RSS bound as the per-unit clang model — with internal/private
definitions promoted exactly like render_fn_external, then partial-links
via the extracted linker::merge_unit_objects. =diff gains a unit-split
harness (merged-object byte verdict). PERRY_CODEGEN_UNITS=3 on the batch
kernel: byte-identical merged objects. The only remaining text
fallthrough is emit_ir_only, which by definition wants text.

Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo
---
 crates/perry-codegen/src/codegen/mod.rs |  34 ++++++
 crates/perry-codegen/src/linker.rs      |  23 ++--
 crates/perry-codegen/src/module.rs      |  92 +++++++++++-----
 crates/perry-codegen/src/native_emit.rs | 133 +++++++++++++++++++++---
 4 files changed, 232 insertions(+), 50 deletions(-)

diff --git a/crates/perry-codegen/src/codegen/mod.rs b/crates/perry-codegen/src/codegen/mod.rs
index 62833745d1..3f41e6135f 100644
--- a/crates/perry-codegen/src/codegen/mod.rs
+++ b/crates/perry-codegen/src/codegen/mod.rs
@@ -2589,6 +2589,11 @@ pub fn compile_module(hir: &HirModule, opts: CompileOptions) -> Result>
         decide_codegen_units(module_callable_count(hir))
     };
     if n_units > 1 {
+        if let Some(result) =
+            try_native_units(&llmod, n_units, opts.target.as_deref(), &module_prefix)
+        {
+            return result;
+        }
         let units = llmod.render_codegen_units(n_units);
         log::debug!(
             "perry-codegen: split '{}' into {} codegen units",
@@ -2641,6 +2646,35 @@ pub fn compile_module(hir: &HirModule, opts: CompileOptions) -> Result>
     }
 }
 
+/// exp/llvm-inprocess: unit-split twin of [`try_native_construction`].
+#[cfg(feature = "llvm-inprocess")]
+fn try_native_units(
+    llmod: &crate::module::LlModule,
+    n_units: usize,
+    target: Option<&str>,
+    module_prefix: &str,
+) -> Option>> {
+    match crate::native_emit::native_mode() {
+        crate::native_emit::NativeMode::Off => None,
+        crate::native_emit::NativeMode::Native => Some(
+            crate::native_emit::compile_module_units_native(llmod, n_units, target, module_prefix),
+        ),
+        crate::native_emit::NativeMode::Diff => Some(
+            crate::native_emit::compile_module_units_diff(llmod, n_units, target, module_prefix),
+        ),
+    }
+}
+
+#[cfg(not(feature = "llvm-inprocess"))]
+fn try_native_units(
+    _llmod: &crate::module::LlModule,
+    _n_units: usize,
+    _target: Option<&str>,
+    _module_prefix: &str,
+) -> Option>> {
+    None
+}
+
 /// exp/llvm-inprocess Phase 2 dispatch. `None` = native construction not
 /// requested (or not compiled in) — continue on the text path. The
 /// feature-off twin returns `None` unconditionally; a build without the
diff --git a/crates/perry-codegen/src/linker.rs b/crates/perry-codegen/src/linker.rs
index 02e13306f1..a0429d2821 100644
--- a/crates/perry-codegen/src/linker.rs
+++ b/crates/perry-codegen/src/linker.rs
@@ -780,16 +780,27 @@ pub fn compile_units_to_object(units: &[String], target_triple: Option<&str>) ->
         _ => {}
     }
 
+    let mut objs: Vec> = Vec::with_capacity(units.len());
+    for (i, unit) in units.iter().enumerate() {
+        objs.push(compile_ll_to_object(unit, target_triple).with_context(|| {
+            format!("codegen unit {}/{} failed to compile", i + 1, units.len())
+        })?);
+    }
+    merge_unit_objects(&objs)
+}
+
+/// Partial-link (`ld -r`) already-compiled codegen-unit objects into one
+/// object. Shared by the text path above and the native construction path
+/// (`native_emit::compile_module_units_native`).
+pub(crate) fn merge_unit_objects(objs: &[Vec]) -> Result> {
     let tmp_dir = env::temp_dir();
     let pid = std::process::id();
     let nonce = TEMP_NONCE_COUNTER.fetch_add(1, Ordering::Relaxed);
 
-    let mut obj_paths: Vec = Vec::with_capacity(units.len());
-    for (i, unit) in units.iter().enumerate() {
-        let bytes = compile_ll_to_object(unit, target_triple)
-            .with_context(|| format!("codegen unit {}/{} failed to compile", i + 1, units.len()))?;
+    let mut obj_paths: Vec = Vec::with_capacity(objs.len());
+    for (i, bytes) in objs.iter().enumerate() {
         let p = tmp_dir.join(format!("perry_cgu_{}_{}_{}.o", pid, nonce, i));
-        fs::write(&p, &bytes)
+        fs::write(&p, bytes)
             .with_context(|| format!("failed to write codegen-unit object {}", p.display()))?;
         obj_paths.push(p);
     }
@@ -811,7 +822,7 @@ pub fn compile_units_to_object(units: &[String], target_triple: Option<&str>) ->
         Err(anyhow!(
             "partial link `{} -r` of {} codegen units failed (status={}).\nstderr:\n{}",
             ld,
-            units.len(),
+            objs.len(),
             out.status,
             String::from_utf8_lossy(&out.stderr)
         ))
diff --git a/crates/perry-codegen/src/module.rs b/crates/perry-codegen/src/module.rs
index be4f14ddee..3ee9c164bf 100644
--- a/crates/perry-codegen/src/module.rs
+++ b/crates/perry-codegen/src/module.rs
@@ -159,7 +159,7 @@ fn helper_decl_attrs(name: &str) -> &'static str {
 /// Synthesize an external `declare` line matching a locally-defined function's
 /// signature, so a codegen unit that calls it (but does not define it) resolves
 /// the call at link time.
-fn declare_line_for(f: &LlFunction) -> String {
+pub(crate) fn declare_line_for(f: &LlFunction) -> String {
     let params = f
         .params
         .iter()
@@ -612,13 +612,18 @@ impl LlModule {
     ///     `internal` init/wrapper is promoted so cross-unit calls bind);
     ///   * the shared attribute groups + metadata (so `#N`/`!N` refs resolve).
     ///
-    /// `n <= 1` (or a single-function module) returns one text identical to
-    /// [`to_ir`]. The caller compiles each text to an object and combines them
-    /// (`ld -r`) into one object, keeping `compile_module`'s single-object API.
-    pub fn render_codegen_units(&self, n: usize) -> Vec {
+    /// `n <= 1` (or a single-function module) returns a single part whose
+    /// `funcs` are all functions (callers use the whole-module path). The
+    /// text caller compiles each rendered part and combines them (`ld -r`)
+    /// into one object, keeping `compile_module`'s single-object API.
+    pub(crate) fn codegen_unit_parts(&self, n: usize) -> Vec> {
         let funcs = self.deduped_function_refs();
         if n <= 1 || funcs.len() <= 1 {
-            return vec![self.to_ir()];
+            return vec![CodegenUnitPart {
+                pre: String::new(),
+                post: String::new(),
+                funcs,
+            }];
         }
         let n = n.min(funcs.len());
 
@@ -671,46 +676,79 @@ impl LlModule {
                 .or_insert_with(|| declare_line_for(f));
         }
 
-        let mut units = Vec::with_capacity(n);
-        for bucket in &buckets {
+        let mut post = String::new();
+        self.push_attrs_and_metadata(&mut post);
+
+        let mut parts = Vec::with_capacity(n);
+        for bucket in buckets {
             let defined: HashSet<&str> = bucket.iter().map(|f| f.name.as_str()).collect();
-            let mut ir = String::new();
-            ir.push_str("; Generated by perry-codegen (codegen unit)\n");
-            ir.push_str(&format!("target triple = \"{}\"\n\n", self.target_triple));
+            let mut pre = String::new();
+            pre.push_str("; Generated by perry-codegen (codegen unit)\n");
+            pre.push_str(&format!("target triple = \"{}\"\n\n", self.target_triple));
 
             for sc in &shared_strings {
-                ir.push_str(sc);
-                ir.push('\n');
+                pre.push_str(sc);
+                pre.push('\n');
             }
-            ir.push('\n');
+            pre.push('\n');
             for g in &shared_globals {
-                ir.push_str(g);
-                ir.push('\n');
+                pre.push_str(g);
+                pre.push('\n');
             }
-            ir.push('\n');
+            pre.push('\n');
 
             // Declares for everything this unit references but does not define.
             for (name, decl) in &decl_by_name {
                 if defined.contains(name) {
                     continue;
                 }
-                ir.push_str(decl);
-                ir.push('\n');
+                pre.push_str(decl);
+                pre.push('\n');
             }
-            ir.push('\n');
+            pre.push('\n');
 
-            for func in bucket {
-                ir.push_str(&render_fn_external(func));
-                ir.push('\n');
-            }
+            parts.push(CodegenUnitPart {
+                pre,
+                post: post.clone(),
+                funcs: bucket,
+            });
+        }
+        parts
+    }
 
-            self.push_attrs_and_metadata(&mut ir);
-            units.push(ir);
+    /// Render this module as `n` independent codegen-unit `.ll` texts (#5391).
+    /// Thin text renderer over [`codegen_unit_parts`]; the native construction
+    /// path consumes the parts directly.
+    pub fn render_codegen_units(&self, n: usize) -> Vec {
+        let parts = self.codegen_unit_parts(n);
+        if parts.len() == 1 {
+            return vec![self.to_ir()];
         }
-        units
+        parts
+            .into_iter()
+            .map(|part| {
+                let mut ir = part.pre;
+                for func in &part.funcs {
+                    ir.push_str(&render_fn_external(func));
+                    ir.push('\n');
+                }
+                ir.push_str(&part.post);
+                ir
+            })
+            .collect()
     }
 }
 
+/// One codegen unit, pre-render: the textual skeleton around the functions
+/// (`pre` = header/strings/globals/cross-unit declares; `post` = shared
+/// attribute groups + metadata) plus the functions themselves, un-rendered so
+/// the native backend can construct them directly.
+pub(crate) struct CodegenUnitPart<'m> {
+    pub pre: String,
+    pub post: String,
+    pub funcs: Vec<&'m LlFunction>,
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/crates/perry-codegen/src/native_emit.rs b/crates/perry-codegen/src/native_emit.rs
index 17944b4a4b..2dd7e77f52 100644
--- a/crates/perry-codegen/src/native_emit.rs
+++ b/crates/perry-codegen/src/native_emit.rs
@@ -15,9 +15,11 @@
 //!   the text-parsed arm's object. Any non-cosmetic difference is a
 //!   construction bug — report it, never normalize it away silently.
 //!
-//! Paths not yet ported (codegen-unit splitting, `emit_ir_only`) fall through
-//! to the text pipeline, where `native`/`diff` still select the in-process
-//! *transport*, so no clang subprocess appears in any in-process mode.
+//! Codegen-unit splitting is ported (`compile_module_units_native`): each
+//! unit is its own context+module, functions stream with external linkage
+//! forced, and unit objects partial-link exactly like the text path. The
+//! only remaining text fallthrough is `emit_ir_only` (bitcode-link mode),
+//! which by definition WANTS the whole-module text.
 //!
 //! Construction consumes `LlFunction::for_each_final_line` — the finalized
 //! per-line stream including entry-alloca hoists, boundary splices and
@@ -72,11 +74,31 @@ fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result
         skeleton.push_str(&format!("declare {} @{}({})\n", f.return_type, f.name, tys));
     }
     let module = crate::inprocess::parse_ir_text(context, &skeleton, "perry_native_module")?;
+    let (typed_insts, raw_insts) = stream_functions(context, &module, &funcs, false)?;
+    log::debug!(
+        "perry-codegen: native construction built {} functions, {} typed + {} raw instructions \
+         (ratchet: raw -> 0), skeleton {} bytes",
+        funcs.len(),
+        typed_insts,
+        raw_insts,
+        skeleton.len()
+    );
+    Ok(module)
+}
+
+/// Stream every function's finalized items into the module. Returns
+/// `(typed, raw)` instruction totals — the migration ratchet.
+fn stream_functions<'ctx>(
+    context: &'ctx Context,
+    module: &Module<'ctx>,
+    funcs: &[&crate::function::LlFunction],
+    force_external: bool,
+) -> Result<(usize, usize)> {
     let mut typed_insts = 0usize;
     let mut raw_insts = 0usize;
-    for f in &funcs {
-        let header = synth_define_header(f);
-        let mut stream = crate::dialect::FnStream::begin(context, &module, &header)
+    for f in funcs {
+        let header = synth_define_header(f, force_external);
+        let mut stream = crate::dialect::FnStream::begin(context, module, &header)
             .map_err(|e| anyhow!("native IR construction failed in @{}: {:#}", f.name, e))?;
         if f.has_try {
             // The setjmp volatile pass needs whole-function analysis; keep
@@ -104,15 +126,90 @@ fn build_native_module<'ctx>(context: &'ctx Context, llmod: &LlModule) -> Result
         typed_insts += t;
         raw_insts += r;
     }
-    log::debug!(
-        "perry-codegen: native construction built {} functions, {} typed + {} raw instructions \
-         (ratchet: raw -> 0), skeleton {} bytes",
-        funcs.len(),
-        typed_insts,
-        raw_insts,
-        skeleton.len()
-    );
-    Ok(module)
+    Ok((typed_insts, raw_insts))
+}
+
+/// Native construction for a module large enough to split into codegen
+/// units (#5391): each unit is its own context+module (peak RSS stays
+/// ~whole/n, same bound as the per-unit clang model), functions stream with
+/// external linkage forced (mirror of `render_fn_external`), and the unit
+/// objects partial-link exactly like the text path.
+pub fn compile_module_units_native(
+    llmod: &LlModule,
+    n: usize,
+    target: Option<&str>,
+    module_prefix: &str,
+) -> Result> {
+    let parts = llmod.codegen_unit_parts(n);
+    if parts.len() == 1 {
+        return compile_module_native(llmod, target, module_prefix);
+    }
+    let mut objs = Vec::with_capacity(parts.len());
+    for (i, part) in parts.iter().enumerate() {
+        let context = Context::create();
+        let mut skeleton = format!("{}{}", part.pre, part.post);
+        for f in &part.funcs {
+            skeleton.push_str(&crate::module::declare_line_for(f));
+            skeleton.push('\n');
+        }
+        let module = crate::inprocess::parse_ir_text(&context, &skeleton, "perry_native_module")
+            .map_err(|e| anyhow!("unit {i} skeleton: {e:#}"))?;
+        let (t, r) = stream_functions(&context, &module, &part.funcs, true)
+            .map_err(|e| anyhow!("unit {i}: {e:#}"))?;
+        debug_dump(&module, &format!("{module_prefix}.unit{i}"));
+        let est: usize = part
+            .funcs
+            .iter()
+            .map(|f| f.estimated_ir_bytes())
+            .sum::()
+            + skeleton.len();
+        let (effective_target, args) =
+            crate::linker::native_plan_args(target, est, part.funcs.len());
+        objs.push(
+            crate::inprocess::optimize_and_emit_module(&module, &effective_target, &args)
+                .map_err(|e| anyhow!("unit {i}: {e:#}"))?,
+        );
+        log::debug!(
+            "perry-codegen: native unit {i}: {} fns, {t} typed + {r} raw insts",
+            part.funcs.len()
+        );
+    }
+    crate::linker::merge_unit_objects(&objs)
+}
+
+/// Unit-split differential harness: text-rendered units through the
+/// in-process transport vs natively-constructed units, merged objects
+/// byte-compared. Returns the text arm (the trusted reference).
+pub fn compile_module_units_diff(
+    llmod: &LlModule,
+    n: usize,
+    target: Option<&str>,
+    module_prefix: &str,
+) -> Result> {
+    let units = llmod.render_codegen_units(n);
+    let bytes_text = crate::linker::compile_units_to_object(&units, target)?;
+    match compile_module_units_native(llmod, n, target, module_prefix) {
+        Err(e) => {
+            eprintln!("perry: [ir-diff] native unit construction FAILED (text arm used): {e:#}");
+        }
+        Ok(bytes_native) => {
+            if bytes_text == bytes_native {
+                eprintln!(
+                    "perry: [ir-diff] OK — native and text unit arms emit byte-identical merged \
+                     objects ({} bytes, {} units)",
+                    bytes_text.len(),
+                    units.len()
+                );
+            } else {
+                eprintln!(
+                    "perry: [ir-diff] MISMATCH — merged unit objects differ (text {} vs native {})",
+                    bytes_text.len(),
+                    bytes_native.len()
+                );
+            }
+        }
+    }
+    Ok(bytes_text)
 }
 
 /// The plan argv for a natively-built module. Same decision code as the text
@@ -247,14 +344,16 @@ pub fn compile_module_diff(
 /// The one-line define header for `f`, matching `LlFunction::to_ir`'s
 /// rendering (linkage, return type, params, inline/try attributes) so the
 /// reader applies identical linkage and function attributes.
-fn synth_define_header(f: &crate::function::LlFunction) -> String {
+fn synth_define_header(f: &crate::function::LlFunction, force_external: bool) -> String {
     let params = f
         .params
         .iter()
         .map(|(t, n)| format!("{t} {n}"))
         .collect::>()
         .join(", ");
-    let linkage = if f.linkage.is_empty() {
+    // Codegen units promote internal/private definitions so cross-unit
+    // calls bind — mirror of `render_fn_external`.
+    let linkage = if f.linkage.is_empty() || force_external {
         String::new()
     } else {
         format!("{} ", f.linkage)

From 4b0b09bcaedcbcb98e0d2c08167920dcf38f65fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ralph=20K=C3=BCpper?= 
Date: Mon, 3 Aug 2026 10:30:34 +0200
Subject: [PATCH 23/26] =?UTF-8?q?exp:=20pin=20layer-2=20readiness=20?=
 =?UTF-8?q?=E2=80=94=20RS4GC=20schedules=20in-process?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

rs4gc_schedules_in_process: RewriteStatepointsForGC runs as a module
pass through the in-process pipeline at the pinned LLVM (no opt
subprocess, no toolchain skew — the exact blocker #7108 measured), a
statepoint lands at the may-GC call, and the live addrspace(1) pointer
is gc.relocate'd across it. This is the mechanism engine-plan layer 2
(#7174) was waiting on; the test keeps it true.

Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo
---
 crates/perry-codegen/src/inprocess.rs | 57 +++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/crates/perry-codegen/src/inprocess.rs b/crates/perry-codegen/src/inprocess.rs
index 13f727c843..3bc870e6d6 100644
--- a/crates/perry-codegen/src/inprocess.rs
+++ b/crates/perry-codegen/src/inprocess.rs
@@ -245,3 +245,60 @@ fn optimize_and_emit(
         .map_err(|e| anyhow!("object emission failed:\n{}", e.to_string()))?;
     Ok(obj.as_slice().to_vec())
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    /// Layer-2 readiness (#7174, engine-plan layer 0 -> 2): the in-process
+    /// pipeline can schedule `RewriteStatepointsForGC` at the pinned LLVM —
+    /// no `opt` subprocess, no version-skewed toolchain. This is the exact
+    /// mechanism #7108 measured as viable-but-blocked under text-plus-clang.
+    /// A statepoint lands at the may-GC call and the live GC pointer is
+    /// relocated across it — the property that makes the register-held-
+    /// pointer bug class unrepresentable.
+    #[test]
+    fn rs4gc_schedules_in_process() {
+        let context = Context::create();
+        let ir = r#"
+declare ptr addrspace(1) @alloc()
+
+define ptr addrspace(1) @f(ptr addrspace(1) %p) gc "statepoint-example" {
+entry:
+  %q = call ptr addrspace(1) @alloc()
+  ret ptr addrspace(1) %p
+}
+"#;
+        let module = parse_ir_text(&context, ir, "rs4gc_probe").expect("probe parses");
+        global_init(&[]);
+        let triple = TargetMachine::get_default_triple();
+        let target = Target::from_triple(&triple).expect("host target");
+        let tm = target
+            .create_target_machine(
+                &triple,
+                "",
+                "",
+                OptimizationLevel::None,
+                RelocMode::PIC,
+                CodeModel::Default,
+            )
+            .expect("target machine");
+        module
+            .run_passes(
+                "rewrite-statepoints-for-gc",
+                &tm,
+                PassBuilderOptions::create(),
+            )
+            .expect("RS4GC pipeline runs in-process");
+        let printed = module.print_to_string().to_string();
+        assert!(
+            printed.contains("gc.statepoint"),
+            "no statepoint emitted:\n{printed}"
+        );
+        assert!(
+            printed.contains("gc.relocate"),
+            "live GC pointer not relocated across the call:\n{printed}"
+        );
+        module.verify().expect("statepoint IR verifies");
+    }
+}

From ba0c1cd4d774cc31326563301f0e88f791f62ee3 Mon Sep 17 00:00:00 2001
From: Ralph Kuepper 
Date: Mon, 3 Aug 2026 10:59:43 +0200
Subject: [PATCH 24/26] =?UTF-8?q?exp:=20Linux=20results=20=E2=80=94=20459/?=
 =?UTF-8?q?466=20A/B,=20math-errno=20question=20closed?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Second OS, second architecture, second object format, same conclusions.

Full 466-test gap A/B under =native on Fedora 43 / x86_64 / glibc / LLVM
22.1.8: 459 SAME, 7 DIFF, 0 compile failures on either arm, 466/466 compiles
carrying the liveness line. The 7 residuals are the three macOS noise families
(perry-ext-http SIGABRT, tokio listener panic, console.time jitter) and each
was proven by re-running a single arm's binary twice — all 7 differ against
themselves, so none is backend-attributable. =diff reports byte-identical
objects on both corpora, so the two construction paths agree on ELF as they do
on Mach-O.

-fno-math-errno is closed rather than deferred: it only governs whether LLVM
may treat a call to a NAMED libm function as errno-free, and Perry never emits
one — math lowers to llvm.* intrinsics (errno-free by definition) or to
js_math_* runtime helpers, whose libm behavior lives in libperry_runtime.a and
is not produced by this compile. Measured on a 431 KB real module and on a
probe with 10 intrinsic call sites, 6 frems and zero named libm callees:
byte-identical objects with and without the flag, under clang 22 and clang 19.
The in-process backend needs no equivalent knob on glibc.
---
 docs/llvm-inprocess-experiment.md | 59 +++++++++++++++++++++++++++----
 1 file changed, 53 insertions(+), 6 deletions(-)

diff --git a/docs/llvm-inprocess-experiment.md b/docs/llvm-inprocess-experiment.md
index 0c37492379..e33bf8fd13 100644
--- a/docs/llvm-inprocess-experiment.md
+++ b/docs/llvm-inprocess-experiment.md
@@ -2,8 +2,9 @@
 
 **Status: Phase 0 complete (transport, byte-identical) and Phase 2 landed
 opt-in (native construction — module-scale IR text no longer exists under
-`PERRY_LLVM_INPROCESS=native`).** The default path is untouched: the default
-build links no LLVM and compiles `.ll` through `clang -c` exactly as before.
+`PERRY_LLVM_INPROCESS=native`), validated on macOS/arm64 and Linux/x86_64.**
+The default path is untouched: the default build links no LLVM and compiles
+`.ll` through `clang -c` exactly as before.
 
 ## Phase 2: native construction (`=native` / `=diff`)
 
@@ -210,9 +211,54 @@ must account for.
 
 **`-fno-math-errno`:** the C API has no equivalent knob, so it was measured
 instead of assumed: on macOS/arm64 the flag produces a byte-identical object
-on Perry IR (Darwin already defaults to errno-free math). **Re-measure on
-Linux before trusting the in-process backend there** — glibc targets default
-the other way.
+on Perry IR (Darwin already defaults to errno-free math). Now also measured on
+Linux/glibc and **closed** — see below.
+
+## Linux results (Fedora 43, x86_64, glibc, LLVM 22.1.8, ELF)
+
+The macOS conclusions reproduce on a second OS, architecture and object format.
+Measured at `89b7dd191` — i.e. *before* the typed-`LlInst` migration, the
+unit-split native path and in-process RS4GC landed. Those five commits change
+what the native path covers, so the sweep below is evidence about the
+construction reader as it stood, not about branch HEAD; re-running it on
+Linux is the first item in "still open".
+
+- **Unit gate**: 528/528 `perry-codegen --features llvm-inprocess`, both
+  corpus gates confirmed constructing (not skipping — that branch is now a
+  hard error).
+- **`=diff` byte verdict**: `[ir-diff] OK` on `spike.ts` (31,929 B) and
+  `batch.ts` (84,345 B). The two construction paths are byte-identical on
+  ELF/x86-64, not only Mach-O/arm64.
+- **Full 466-test gap A/B under `=native`** (one binary, flag-only arm
+  difference): **459 SAME, 7 DIFF, 0 compile failures on either arm, 466/466
+  compiles carrying the liveness line, 0 NOT_LIVE.** 71 min wall.
+- **The 7 residuals are the same three families as macOS, and each was proven
+  by re-running one arm's binary twice**: all 7 differ against *themselves*.
+  5× `perry-ext-http` `server.rs:911` SIGABRT and 1× tokio `listener.rs:304`
+  panic (stderr embeds the OS thread id), 1× `console.time()` wall-clock
+  jitter. None is backend-attributable.
+- **Peak RSS per compile**: 244 MB text arm, 273 MB native arm — the
+  in-process context costs ~29 MB at gap-test scale. The bundle-scale RSS
+  question is untouched by this.
+
+**`-fno-math-errno` on Linux: measured no-op, question closed.** The flag only
+governs whether LLVM may treat a call to a *named* libm function as
+errno-free, and Perry never emits one. Math lowers either to `llvm.*`
+intrinsics (errno-free by definition) or to `js_math_*` runtime helpers, whose
+libm behavior lives inside `libperry_runtime.a` and is not produced by this
+compile at all. Verified on a 431 KB real module and on a purpose-built probe
+exercising every `Math.*` entry point plus `frem`: 10 intrinsic call sites, 6
+`frem`s, **zero** named libm callees; objects byte-identical with and without
+the flag under both clang 22.1.8 and clang 19. The in-process backend needs no
+equivalent knob on glibc. (The property that makes this true is "no named libm
+callee in emitted IR" — if the emitter ever gains one, this must be re-measured.)
+
+Scope limits of the Linux run, stated plainly: `PERRY_NO_AUTO_OPTIMIZE=1` on
+both arms; the box's node is v22.22.2 against a 26.5.1 pin, which does not
+affect a perry-vs-perry A/B but means this run makes no oracle-parity claim;
+at `89b7dd191` codegen-unit-split modules still fell through to transport, so
+the sweep did not exercise native construction on them (`e370f5554` has since
+ported that path — unvalidated on Linux).
 
 ## Measurements (honest scope)
 
@@ -273,7 +319,8 @@ this transport, not assumed.
   everything, and `-target` handling mirrors the clang path, but COFF and the
   MSVC/MinGW distinction (see `probe_clang_default_triple`) need their own
   A/B before any claim.
-- **`-fno-math-errno` on Linux**: measure before enabling there (see above).
+- ~~**`-fno-math-errno` on Linux**~~: **closed — measured, no-op.** See the
+  Linux results section.
 
 ## Recommendation, with its price
 

From 440ed8d1c4896e831d996ca660fac770a690e817 Mon Sep 17 00:00:00 2001
From: Ralph Kuepper 
Date: Mon, 3 Aug 2026 11:35:18 +0200
Subject: [PATCH 25/26] exp: ship the llvm-sys shim generator instead of
 describing it

The Linux bring-up needed one artifact that lived only on the box that did it:
a wrapper llvm-config. Upstream LLVM release tarballs are built on Ubuntu and
report the BUILD HOST's static system libs by absolute path
(/usr/lib/x86_64-linux-gnu/libzstd.a), and llvm-sys panics on any --system-libs
entry that is neither `-lfoo` nor an existing file -- so on a distro without an
LLVM 22 package the build dies before compiling anything. The write-up
described the fix in prose, which left the next person to re-derive it.

mk_llvm_sys_shim.sh generates the prefix instead. It generalizes past the one
symptom: any dangling absolute path in --system-libs becomes `-lname`, while
paths that DO exist are left alone, since llvm-sys handles a real absolute path
and silently converting a deliberate static link to a dynamic one is not a
change to make on the user's behalf.

Verified against the hand-written shim the Linux sweep actually built with:
identical output for --system-libs/--version/--libdir/--includedir/--prefix/
--libnames, and a full relink of the perry-codegen test binary through the
generated prefix resolves dylib=zstd and passes the corpus gates.
---
 docs/llvm-inprocess-experiment.md             | 30 ++++++---
 .../llvm-inprocess-spike/mk_llvm_sys_shim.sh  | 61 +++++++++++++++++++
 2 files changed, 84 insertions(+), 7 deletions(-)
 create mode 100755 experiments/llvm-inprocess-spike/mk_llvm_sys_shim.sh

diff --git a/docs/llvm-inprocess-experiment.md b/docs/llvm-inprocess-experiment.md
index e33bf8fd13..ba2346eb4c 100644
--- a/docs/llvm-inprocess-experiment.md
+++ b/docs/llvm-inprocess-experiment.md
@@ -374,13 +374,29 @@ tar -xf LLVM-22.1.8-Linux-X64.tar.xz -C ~/opt      # ~12 GB unpacked
 ```
 
 One trap: that tarball is built on Ubuntu, so its baked-in
-`llvm-config --system-libs` answer names the *build host's* static zstd by
-absolute path (`/usr/lib/x86_64-linux-gnu/libzstd.a`). llvm-sys panics on any
-`--system-libs` entry that is neither `-lfoo` nor an existing file, so on any
-other distro the build dies before it starts. Point `LLVM_SYS_221_PREFIX` at a
-one-file shim prefix whose `bin/llvm-config` rewrites that path to `-lzstd` and
-forwards everything else (the real binary still answers all path queries
-relative to its own prefix, so nothing else needs redirecting).
+`llvm-config --system-libs` answer names the *build host's* static system libs
+by absolute path (`/usr/lib/x86_64-linux-gnu/libzstd.a`). llvm-sys panics on
+any `--system-libs` entry that is neither `-lfoo` nor an existing file, so on
+any other distro the build dies before it compiles anything:
+
+```
+Unable to parse result of llvm-config --system-libs: /usr/.../libzstd.a
+```
+
+`mk_llvm_sys_shim.sh` generates the prefix that fixes it — a single wrapper
+`llvm-config` that rewrites *dangling* absolute paths to plain `-lname` and
+forwards everything else, including every path query (the real binary answers
+those relative to its own prefix, so the shim needs no `lib/` or `include/`):
+
+```bash
+experiments/llvm-inprocess-spike/mk_llvm_sys_shim.sh \
+  ~/opt/LLVM-22.1.8-Linux-X64 ~/opt/llvm22-shim
+export LLVM_SYS_221_PREFIX=~/opt/llvm22-shim
+```
+
+Entries that *do* exist are left alone: llvm-sys handles a real absolute path
+fine, and quietly turning a deliberate static link into a dynamic one would be
+a change nobody asked for.
 
 Measured cost of the feature build on this host: `perry` 199 MB (vs 53 MB
 default), `cargo build --profile perry-dev` 2m49s warm-registry cold-target.
diff --git a/experiments/llvm-inprocess-spike/mk_llvm_sys_shim.sh b/experiments/llvm-inprocess-spike/mk_llvm_sys_shim.sh
new file mode 100755
index 0000000000..12dc13f951
--- /dev/null
+++ b/experiments/llvm-inprocess-spike/mk_llvm_sys_shim.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# Build an LLVM_SYS_221_PREFIX shim for a downloaded upstream LLVM release.
+#
+#   ./mk_llvm_sys_shim.sh ~/opt/LLVM-22.1.8-Linux-X64 ~/opt/llvm22-shim
+#   export LLVM_SYS_221_PREFIX=~/opt/llvm22-shim
+#
+# Why this exists: on a distro with no LLVM 22 package (Fedora 43 stops at
+# llvm20-devel; its system libs are 21), the upstream release tarball is the
+# only route. But those tarballs are built on Ubuntu, and `llvm-config
+# --system-libs` reports the BUILD HOST's static system libraries by absolute
+# path -- e.g. /usr/lib/x86_64-linux-gnu/libzstd.a, which exists on no other
+# distro. llvm-sys's build script panics on any --system-libs entry that is
+# neither `-lfoo` nor an existing file:
+#
+#   Unable to parse result of llvm-config --system-libs: /usr/.../libzstd.a
+#
+# so the build dies before compiling anything. This wrapper rewrites exactly
+# those dangling absolute paths to plain `-lname` flags, letting the linker
+# resolve them against the host's own shared libraries. Entries that DO exist
+# are left alone -- llvm-sys handles a real absolute path fine, and silently
+# converting a deliberate static link into a dynamic one would be a change we
+# were not asked to make.
+#
+# Everything else passes through untouched, including every path query: the
+# real llvm-config still answers those relative to its own prefix, so the shim
+# needs no lib/ or include/ of its own.
+set -euo pipefail
+
+REAL=${1:?usage: mk_llvm_sys_shim.sh  }
+SHIM=${2:?usage: mk_llvm_sys_shim.sh  }
+REAL=$(cd "$REAL" && pwd)
+
+[ -x "$REAL/bin/llvm-config" ] || { echo "no llvm-config under $REAL/bin" >&2; exit 1; }
+
+mkdir -p "$SHIM/bin"
+cat > "$SHIM/bin/llvm-config" < $REAL/bin/llvm-config"
+echo "  --version:     $("$SHIM/bin/llvm-config" --version)"
+echo "  --libdir:      $("$SHIM/bin/llvm-config" --libdir)"
+echo "  --system-libs: $("$SHIM/bin/llvm-config" --system-libs --link-static)"
+echo
+echo "export LLVM_SYS_221_PREFIX=$SHIM"

From 2c6ff439672761dfe55ba39ee9b999e464dc8c56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ralph=20K=C3=BCpper?= 
Date: Mon, 3 Aug 2026 10:35:51 +0200
Subject: [PATCH 26/26] exp: changelog fragment + status update for landing

Claude-Session: https://claude.ai/code/session_01GsQbePfACqFLd4LaGfQzLo
---
 ...7241-inprocess-llvm-native-construction.md | 18 +++++++++++++++
 docs/llvm-inprocess-experiment.md             | 23 +++++++++++++++----
 2 files changed, 36 insertions(+), 5 deletions(-)
 create mode 100644 changelog.d/7241-inprocess-llvm-native-construction.md

diff --git a/changelog.d/7241-inprocess-llvm-native-construction.md b/changelog.d/7241-inprocess-llvm-native-construction.md
new file mode 100644
index 0000000000..7573eea0a0
--- /dev/null
+++ b/changelog.d/7241-inprocess-llvm-native-construction.md
@@ -0,0 +1,18 @@
+Opt-in in-process LLVM backend (#7241, engine-plan layer 0): with the
+`llvm-inprocess` cargo feature built in and `PERRY_LLVM_INPROCESS=native`,
+Perry constructs LLVM modules through the C API against pinned LLVM 22 — no
+module-scale IR text, no `.ll` on disk, no `clang` subprocess, no dependence
+on the user's toolchain. All 68 `LlBlock` semantic methods emit typed
+instructions that build directly (`inst.rs`/`dialect.rs`); codegen-unit
+splits build per-unit native modules and partial-link as before; `=diff`
+mode byte-compares the two backends' objects (both corpora byte-identical);
+`PERRY_SAVE_LL`/`--trace llvm`/`PERRY_LLVM_KEEP_IR` print the constructed
+module as the debug view. `=1` selects the transport-only mode (whole-module
+text parsed in-process). The flag participates in the build- and
+object-cache keys; a build without the feature fails loudly if the flag is
+set. The default build is unchanged: no LLVM link dependency, and emitted
+IR is byte-identical to the merge-base (verified over a 12-file corpus; the
+only divergence class is a pre-existing run-to-run closure-name
+registration ordering coin that flips within a single binary).
+`RewriteStatepointsForGC` scheduling in-process is pinned by test —
+the layer-2 (#7174) unblock this branch exists for.
diff --git a/docs/llvm-inprocess-experiment.md b/docs/llvm-inprocess-experiment.md
index ba2346eb4c..da7da578d1 100644
--- a/docs/llvm-inprocess-experiment.md
+++ b/docs/llvm-inprocess-experiment.md
@@ -1,10 +1,23 @@
 # In-process LLVM backend experiment (`exp/llvm-inprocess`)
 
-**Status: Phase 0 complete (transport, byte-identical) and Phase 2 landed
-opt-in (native construction — module-scale IR text no longer exists under
-`PERRY_LLVM_INPROCESS=native`), validated on macOS/arm64 and Linux/x86_64.**
-The default path is untouched: the default build links no LLVM and compiles
-`.ll` through `clang -c` exactly as before.
+**Status: native construction COMPLETE, opt-in, validated on macOS/arm64
+and Linux/x86_64.** Under
+`PERRY_LLVM_INPROCESS=native` (with the `llvm-inprocess` cargo feature),
+every construction path is native: all 68 `LlBlock` semantic methods emit
+typed instructions that build straight through the C API (no per-line text),
+codegen-unit splits build per-unit native modules and partial-link, and the
+debug knobs (`PERRY_SAVE_LL` / `--trace llvm` / `PERRY_LLVM_KEEP_IR`) print
+the constructed module. `Raw` text remains only for the 89 `emit_raw`
+bespoke sites and the `LlFunction` entry-splice strings (streamed through
+the bounded line reader; the `(typed, raw)` counts are the ratchet), plus
+`has_try` functions whose setjmp volatile pass needs whole-function text.
+`rewrite-statepoints-for-gc` scheduling in-process is pinned by test
+(`rs4gc_schedules_in_process`) — the #7174 / engine-plan layer-2 unblock.
+The default path is untouched: the default build links no LLVM, and emitted
+IR is byte-identical to the merge-base over a 12-file proof corpus (the
+only divergence class is a PRE-EXISTING run-to-run coin in closure-name
+registration order — it flips between two runs of a single binary; a
+side-finding for the #7131 determinism work, not a branch effect).
 
 ## Phase 2: native construction (`=native` / `=diff`)